かずま さんが書きました:
fscanf(fp, "%d %s", &j, str); のあとに printf("d=%d, s=%s\n", j, str);
を入れて、検出なしとなるような番号を指定するとどうなりますか?
なぜ、この質問には答えず、頓珍漢な説明をするんですか?
double-clutch. さんが書きました:
それに際し、処理をより細かく行いたいので、
関数 fprintf() では、一度の呼び出しに対し、制御文に含めて良い『フォーマット指
定子』はひとつまでとする
fprintf() は、fscanf() の間違いですよね。
double-clutch. さんが書きました:
コード:
[loop]-[ (fp が指しているファイルが終端に達している!!) の真偽反転 ]
// つまり、fp が指しているファイルが終端に達していない場合は、ループに入る
-[ file から数字を読込み、変数 j に保持する ]
-[ file から文字列を読込み、配列 str に保持する ]
-[ file の読込み地点を次の行の、行頭に移動する ]
[/loop]
fscanf を 2つに分けて、j への読み込みと、str の読み込みの 2行はいいとして、
行頭に移動するは、元のコードに対応しません。
その疑似コードは、C のプログラムと対応しないので、これから先の議論は無意味です。
さらに、ファイルのフォーマットが異なる場合について考察していますが、
それはまた別の話です。たとえ、フォーマットが異なっていたとしても、"%s" で
str に「改行文字」が入ることはあり得ません。
double-clutch. さんが書きました:
コード:
『ファイルの終端』以降の『何か』を配列 str に読み込もうとしている...
..... 処理③に対応している、codeは fscanf(fp, "%s", str) ...
...『フォーマット指定子』は %s ... これは、対象のfile から『ヌル文字列』を読み込む...ということ...
...ここで、『ヌル文字列』の定義は最後の一文字が '\0' である、何かしらの『文字列』...
file には、'\0' はありません。
"%s" は、0個以上の空白(スペース、タブ、改行など)を読み飛ばした後、空白でない
文字を 1個以上読み取って、空白が出てくるか EOF になるまでを文字列として str
に入れます。そして、scanf が str に '\0' を追加します。
最後に読み取った空白は、入力に押し戻し、これは次の fscanf で読み込まれます。
さて、元に戻って、次のように printf を追加してみましょう。
かずま さんが書きました:
fscanf(fp, "%d %s", &j, str); のあとに printf("d=%d, s=%s\n", j, str);
を入れて、検出なしとなるような番号を指定するとどうなりますか?
実行結果
コード:
調べたい番号を入力:: 3
j=15, str=いちご
j=2, str=にんじん
j=5, str=ごりら
j=5, str=ごりら
検出なし
printf は 4回実行されていることがわかります。
file には 3行しかないのに、です。
このため if (i == j) { も 4回実行されています。
3回目と 4回目は、j と str の値が同じなので、プログラムとしては何もおかしな
ことはおこりません。
しかし、3行すなわち 3組しかないデータを 4回チェックするのはロジックとして
間違いです。
3回目の fscanf を実行して、最後のデータを読み込んだ後、読み込み位置は
3行目の改行文字の直前になっています。まだ EOF に達していないので、feof()
は真にはなりません。
そして、4回目の fscanf を実行すると、"%d" が改行文字を読み飛ばし、読み込み
位置が EOF に達し、i への数値の読み込みに失敗します。
ここで feof が真になります。
feof のチェックは、fscanf の後に行わないと意味がないということです。
fscanf は書式に従って読み込みを続けるうちに EOF に達し、ひとつもデータを
読み込めなかった場合は、返却値として EOF を返します。だから、普通は、
コード:
while (fscanf(fp, "%d%s", &j, str) != EOF) {
のように書きます。feof を使いません。
fscanf は、読み込めたデータ数を返しますから、
コード:
while (fscanf(fp, "%d%s", &j, str) == 2) {
と書いたほうが、以後のデータ処理は正しく行われます。