書式つきのファイルから入力するときは、fscanf関数をよく使います。
ただし、csvファイルから %s で読むときは、少し工夫が要ります。
たとえば、次の読み込みは上手くいきません。
fscanf( fp, "%d,%s,%d", &shcd, name, &price ); //商品コード,商品名,価格
正しく入力できません(shcd しか読めません)。
%s 変換では、空白文字(半角スペーやタブや改行、ほかに復帰、垂直タブ、改ページ)が来ると、読み込みを終わります。
,(カンマ)は、空白文字ではないので入力の区切りとならず、文字列の一部として読み込まれてしまいます。
もしも、文字列データが 1種類で、必ず行の最後にあるなら(上の例では、商品名と価格のデータ順を入れ替えたとき)、読み込みに成功します。
なぜかというと、文字列データのうしろにカンマがありません。そして改行で %s の入力が終わるからです。
次のプログラムのようにすると、順番を入れ替えなくても fscanf で csvファイルから入力できます。
【 fscanf で csvファイルを入力するプログラム例 】#include <stdio.h> #include <stdlib.h> main() { FILE *fp; int shcd, price; char name[24]; if( (fp = fopen( "data.csv", "r")) == NULL ) { printf( "入力ファイルがオープンできません\n" ); exit(1); } while( fscanf( fp, "%d,%[^,],%d", &shcd, name, &price ) == 3 ) { printf( "%d, %s, %d\n", shcd, name, price ); } fclose( fp ); }
%[^,]
と書くと , が現われるまで文字列として読み込みます。少し例を示します。
指定例 意味 例 [,] カンマの並び ",,,ABC" ⇒ ",,," [0-9] 数字の並び "001.321" ⇒ "001"(1ではありません) [a-z] 英小文字の並び "yes, I do" ⇒ "yes" [quick] いずれかの文字の並び "cuiqqkly" ⇒ "cuiqqk" | |
指定の前に ^(キャレット)を付けると否定の意味になります。 | |
[^,] カンマ以外の並び "AB,CD" ⇒ "AB"(カンマが現われるまで読み込むことになる) [^0-9] 数字以外の並び "wid24.5" ⇒ "wid"(数字が現われるまで読み込む) |
while( fscanf( fp, "%d,%[A-Z],%d", &shcd, name, &price ) == 3 ) {
その場合、データ 「1123,NOTEPC,59800」 の入力に成功するでしょうか?
2択です。[ 関連記事 ] fgets と sscanf で ファイルから入力, 入力時に不要データをスキップ
default:
// %dで読めれば西暦指定とみなしそれを返す、不可ならエラー
if( sscanf( wareki, "%d", &year ) == 1 ) return year;
return -1;