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

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

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

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

CSV

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

解決済

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

Uh37
Uh37

総合スコア11

C

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

CSV

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

3回答

0グッド

0クリップ

18522閲覧

投稿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()関数を用いていますが、もし他の方法をご存じでしたら参考までに教えていただけると幸いです。

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答3

2

ベストアンサー

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

総合スコア80419

Uh37, pepperleaf👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

Uh37

2019/06/07 07:35

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

2019/06/07 13:33

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

1

一つ前の行の改行コードを読み飛ばすために
"%[^,],%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

総合スコア8080

Uh37👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

Uh37

2019/06/07 07:30

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

1

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

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

投稿2019/06/07 03:01

y_waiwai

総合スコア86013

Uh37👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

Uh37

2019/06/07 06:37

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

2019/06/07 06:56

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

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

C

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

CSV

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