質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Q&A

解決済

3回答

21875閲覧

C言語のfscanf()関数を用いてCSVファイルを読み込む方法

Uh37

総合スコア11

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

0グッド

0クリップ

投稿2019/06/07 02:55

前提・実現したいこと

C言語で<stdio.h>のfscanf()関数を使って、CSVファイルの内容を読み込みたいのですが、意図しない結果となってしまいます。

発生している問題・エラーメッセージ

CSVファイルの中身は

"comma.csv"

test,10,11,1.1,1.2

test,20,21,2.1,2.2
test,30,31,3.1,3

と記述したのですが、後述のコードを実行したときにこのような結果が得られました。
CSVファイルと同じ記述を標準出力に表示するにはどのようにすればよいのでしょうか?

実行結果

・ソtest 10 11 1.1 1.2

test 20 21 2.1 2.2
test 30 31 3.1 3.2
30 31 3.1 3.2
続行するには何かキーを押してください . . .

該当のソースコード

C

1#include <stdio.h> 2 3int main(void) 4{ 5 FILE *fp; 6 char *fname = "comma.csv"; 7 char s[16]; 8 int ret, n1, n2; 9 float f1, f2; 10 11 fp = fopen(fname, "r"); 12 if (fp == NULL) 13 { 14 printf("%sファイルが開けません\n", fname); 15 return -1; 16 } 17 18 while ((ret = fscanf(fp, "%[^,],%d,%d,%f,%f", s, &n1, &n2, &f1, &f2)) != EOF) 19 { 20 printf("%s %d %d %.1f %.1f\n", s, n1, n2, f1, f2); 21 } 22 23 fclose(fp); 24 return 0; 25}

試したこと

ファイル操作については初心者であるため、コードを書く以外に試したことはありません。

開発環境

Visual Stdio 2015

補足情報(FW/ツールのバージョンなど)

今回はネットに掲載されていたコードを写経していたために、fscanf()関数を用いていますが、もし他の方法をご存じでしたら参考までに教えていただけると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

3行目を読んだときに、改行文字が読み残されるので、4回目の読み込みでsに改行が入ります。
改行文字までを喰うために、フォーマット文字列の最後に、空白を入れると良いでしょう。
また、scanf系の関数は戻り値が、変数の数と一致しているか確認しましょう。文字列を読むときは長さを入れましょう。

C

1 while ((ret = fscanf(fp, "%15[^,],%d,%d,%f,%f ", s, &n1, &n2, &f1, &f2)) != EOF) 2 { 3 if(ret!=5) { 4 printf("ファイル内容がおかしい ret=%d\n",ret); 5 printf("<%s>\n",s); 6 return 1; 7 } 8 printf("%s %d %d %.1f %.1f\n", s, n1, n2, f1, f2); 9 }

別案としては、while条件を!=EOFじゃなくて==5にする。

scanf系はいつも難しいです。この問題に関してだけだと、fgets+sscanfだとフォーマット文字列の空白が無くても大丈夫です。

投稿2019/06/07 04:26

otn

総合スコア84498

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Uh37

2019/06/07 07:35

ひとまずフォーマット文字列の最後に空白を入れた段階で、csvファイル内のデータを読み込むことには成功したようです、ありがとうございます。"fgets" と "sscanf" を使った方法にも挑戦してみたいと思います。
otn

2019/06/07 13:33

fgets + strtok という方法もあります。
guest

0

一つ前の行の改行コードを読み飛ばすために
"%[^,],%d,%d,%f,%f" の %[ の前にスペースを入れて
" %[^,],%d,%d,%f,%f" にする。

ファイル入力の場合はスペースを最後においても構いませんが、
キーボード入力の場合に困ります。

C

1#include <stdio.h> 2 3int main(void) 4{ 5 char s[16]; int n; 6 while (scanf("%[^,],%d ", s, &n) == 2) 7 printf("%s %d\n", s, n); 8}

スペースが前の場合の実行例

abc,123 (入力) abc 123 def,-45 (入力) def -45 , (^D または ^Z でもよい)

スペースが最後の場合の実行例

abc,123 (入力) def,-45 (入力) abc 123 , (^D または ^Z でもよい) def -45

次の行を入力するまで、今の出力が出ません。

投稿2019/06/07 06:25

編集2019/06/07 07:23
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Uh37

2019/06/07 07:30

参考になります。ありがとうございます。
guest

0

fscanfには残念ながら正規表現を処理する機能はありません

CSVを読むには、fscanfを使うのはやめといたほうがいいと思います
fgetsで1行読み、そこから分解していくようにしましょう

投稿2019/06/07 03:01

y_waiwai

総合スコア87747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Uh37

2019/06/07 06:37

scanf()については妄信して使っていたので、勉強になります。 ありがとうございます。
y_waiwai

2019/06/07 06:56

scanf系の関数は危険な関数なんで、実務では殆ど使われません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問