プロが教えるわが家の防犯対策術!

ファイルの中身が例えば

600
0.6
3.5

となっているとき,
fscanfで読み込むと改行\nを読み込んでくれる場合と読み込まない場合がありませんか?
また,これだったら,経験から
fscanf(fp,"%d",&a);
fscanf(fp,"%f",&b);
fscanf(fp,"%c",&c); // \nの読み飛ばし
fscanf(fp,"%f",&d);
fscanf(fp,"%c",&e); // \nの読み飛ばし
でやるとできそうですが,fscanf(fp,"%d",&a);のあとの\nの読み飛ばしがいらないのは何故ですか?

A 回答 (8件)

#1です。


scanf()系は、
空白文字(スペース、改行、タブなど)の前まで読み込む


最後の改行文字はバッファの中に残っている


読み込む


空白文字はスペースとして扱われるため、
書式が"%c"以外なら読み込むが無視して次の行のものを読み込む。
書式が"%c"ならば、残っている改行文字を変数に入れてしまう

ということです。

#3の補足のソースで言えば、

fscanf( fp, "%d", &a ); //1行目の600を変数aに格納
            //→バッファに最後の改行が残る

fscanf( fp, "%f", &b ); //書式が"%f"なので、バッファに残った改行を無視
            //→2行目の0.6を変数bに格納
            //→バッファに最後の改行が残る

fscanf( fp, "%f", &c ); //書式が"%f"なので、バッファに残った改行を無視
            //→3行目の3.5を変数cに格納
            //→バッファに最後の改行が残る

fscanf( fp, "%c", &d ); //書式が"%c"なので、バッファに残った改行を変数cに格納

fscanf( fp, "%c", &e ); //4行目の"XYZ"の"X"を変数eに格納
            //→バッファに"YZ"と改行コードが残る

fscanf( fp, "%c", &f ); //バッファに残っている"YZ"と改行コードから
            //最初の"Y"を変数fに格納

ということです。

http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-4

も参考にしてください。

> C++の入門書にコアダンプっていうことばがあったんですけどこれはどんな意味かご存知ですか?

下のURLが参考になるかと。

http://www.atmarkit.co.jp/icd/root/39/63458339.h …

http://e-words.jp/w/E382B3E382A2E38380E383B3E383 …

参考URL:http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-4,http://www.atmarkit.co.jp/icd/root/39/63458339.h …

この回答への補足

%c以外で%sのときはどうなるのかと思い、下のテストプログラムを試しました。変な結果になっています。これはどのように説明がつくのでしょうか?
○テストプログラム
#include<stdio.h>
#include<stdlib.h>

int main()
{
int a;
float b, c;
char d[10], e[10], f[10];

FILE* fp;
fp = fopen( "datafile.txt", "r" );

fscanf( fp, "%d", &a );
fscanf( fp, "%f", &b );
fscanf( fp, "%f", &c );
fscanf( fp, "%s", d );
fscanf( fp, "%s", e );
fscanf( fp, "%s", f );

printf( "a %d\n", a );
printf( "b %f\n", b );
printf( "c %f\n", c );
printf( "d %s\n", d );
printf( "e %s\n", e );
printf( "f %s\n", f );

fclose(fp);

return 0;
}

●注;datafile.txtの中身
600
0.6
3.5
XYZ

○実行結果
a 600
b 0.600000
c 3.500000
d XYZ
e フフフフフフフフフフフフXYZ
f フフフフフフフフフフフフフフフフフフフフフフフフXYZ

補足日時:2004/04/14 01:28
    • good
    • 0
この回答へのお礼

丁寧な回答ありがとうございました。とても分かりやすく理解できました!!原因がすっきりしました。
コアダンプについてもURLを載せて頂きありがとうございました。

お礼日時:2004/04/14 01:26

#5です。



#5の補足のソースを拝見しました。

まず、最初に言っておきますが、Cでは、変数を宣言した時点では、
変数は初期化されておらず、ごみが入っています。

#5の補足のソースのfscanf()の4行目から説明しますと、
(3行目までは、#5と同じです)


fscanf( fp, "%s", d );//書式が"%s"なので、バッファに残った改行を無視
           //→ファイル4行目の"XYZ"を変数dに格納
           //→バッファに最後の改行が残る

fscanf( fp, "%s", e );//書式が"%s"なので、バッファに残った改行を無視
           //→ファイルがEOF(ファイルの終わり)
           //まで達したので読み込まない
           //変数eには何も入らない(ごみが入ったまま)

fscanf( fp, "%s", f );//ファイルがEOFまで達したので読み込まない
           //変数fには何も入らない(ごみが入ったまま)

ですから、実行結果のeとfについては、たまたま変数に入っていたごみのデータ
を表示していることになります。

このことは、変数を初期化するなり、
最初にprintf()で変数の中身を表示するなりで確認できるかと思います。


ちなみに、私の環境では実行結果がこうなりました。(コンパイラ bcc)
a 600
b 0.600000
c 3.500000
d XYZ
e 漾
f
    • good
    • 0
この回答へのお礼

%sも改行を無視してくれるんですね。

XYZを読み込んだあとEOFとなることを見落としていました。それでごみが残ったままになってしまっていたんですね。よく分かりました!!

長々と本当にありがとうございました。今まで抱いていた疑問が一気に解消できました!またC言語の事で分からない事があったらよろしくお願いします。

お礼日時:2004/04/14 22:36

#3です。


>「fscanfで読み込むと改行\nを読み込んでくれる場合と読み込まない場合がありませんか?」
と最初の質問で言ったできごとをちゃんと起こす事ができました。
>補足回答よろしくお願いします。

うーむ。再現しましたね。私の環境でも再現しました。

>このようにどうやら%cで読み込む時になんか変なことが起こってしまうようなんです。
>何故なのでしょうか??

#3で「たぶん、正常なデータが入ってなかったのだと思います。」と回答しましたが、これは誤りでした。
#5の方が回答を書かれていますが、まさしくその通りです。お詫びして、訂正致します。
    • good
    • 0
この回答へのお礼

再現してくださってありがとうございました。真剣に答えて頂きとても嬉しく思います。

お礼日時:2004/04/14 01:45

#1、5です。



#5で訂正があります。
#3の補足のソースのfscanf()の4行目は、
fscanf( fp, "%c", &d ); //書式が"%c"なので、バッファに残った改行を変数dに格納
です。
(変数cに格納 ではありません・・・)
    • good
    • 0
この回答へのお礼

迅速な訂正ありがとうございます。

お礼日時:2004/04/14 01:28

scanf系で%c以外の書式指定ではデータの前の空白文字(スペース、タブ、改行)を読み込むが無視するという処理をします。

データの後の空白文字は読み込まず次のscanf実行に持ち越されます。
対して%c書式指定では空白文字であっても読み込みます。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。なるほどこの問題は%cかそうでないかが決め手だったのですね。

お礼日時:2004/04/14 01:24

>ダンプって何ですか?


ファイルの内容を文字列ではなく、文字列のコードで出力することです。
たとえば、先頭の行は
600改行 ですので、文字列のコードを16進数で表示すると
3630300d0a と表示されるはずです。
このことにより、格納されている文字がなんなのかを正確に判断することができます。
空白の文字は見た目では半角のスペースか全角のスペースかタブなのか改行なのかが判りません、このような時に16進数で文字列のコード表示すると違いがはっきりと判ります。
このような表示が出来るエディタを「バイナリエディタ」と読んでいますので、そのエディタを使用して見てください。(無償でダウンロード可能なものが、たくさんあります)
>でも他のプログラムではそうならないときがあったんだけ>どなぁ?
>どうしてでしょうか?
たぶん、正常なデータが入ってなかったのだと思います。(例えばデータの後に全角のスペースがあると正しく動作しません)
そのファイルが、まだあれば、バイナリエディタで内容を参照してみてください。

この回答への補足

このようにどうやら%cで読み込む時になんか変なことが起こってしまうようなんです。
何故なのでしょうか??
「fscanfで読み込むと改行\nを読み込んでくれる場合と読み込まない場合がありませんか?」
と最初の質問で言ったできごとをちゃんと起こす事ができました。
補足回答よろしくお願いします。

○問題発生のテストプログラム
#include<stdio.h>
#include<stdlib.h>

int main()
{
int a;
float b, c;
char d, e, f;

FILE* fp;
fp = fopen( "datafile.txt", "r" );

fscanf( fp, "%d", &a );
fscanf( fp, "%f", &b );
fscanf( fp, "%f", &c );
fscanf( fp, "%c", &d );
fscanf( fp, "%c", &e );
fscanf( fp, "%c", &f );

printf( "a %d\n", a );
printf( "b %f\n", b );
printf( "c %f\n", c );
printf( "d %c\n", d );
printf( "e %c\n", e );
printf( "f %c\n", f );

fclose(fp);

return 0;
}

●注;datafile.txtの中身
600
0.6
3.5
XYZ

○実行結果
a 600
b 0.600000
c 3.500000
d

e X
f Y

補足日時:2004/04/12 23:17
    • good
    • 0
この回答へのお礼

補足回答ありがとうございました。
なんかC++の入門書にコアダンプっていうことばがあったんですけどこれはどんな意味かご存知ですか?
正常なデータが入っているにもかかわらず,
問題を発生させることに成功しました!
補足回答のプログラムをご覧下さい!!

お礼日時:2004/04/12 23:16

通常は、全て正常データであれば、


fscanf(fp,"%d",&a);
fscanf(fp,"%f",&b);
のあと
fscanf(fp,"%c",&c); // \nの読み飛ばし
を行う必要はありません。
但し、
600のデータが
600Xとか600の後に全角スペース
とかになっていると、次のデータを正しく読み込めません。
1.各データは全て正常なデータであること。
2.各データの後は改行だけであること。
上記の2条件が必ず成立するデータでも、\nの読み飛ばしが必要でしょうか。
また、このテスト環境は、windowsでしょうかunixでしょうか。windowsの場合、正しい改行になってますか。(16進ダンプで0x0d0aが表示されますか)
上記の点をチェックしてみて下さい。

この回答への補足

○#1から\n読み飛ばしをなくしたテストプログラム
#include<stdio.h>
#include<stdlib.h>

int main()
{
int a;
float b, d;

FILE* fp;
fp = fopen( "datafile.txt", "r" );

fscanf( fp, "%d", &a );
fscanf( fp, "%f", &b );
fscanf( fp, "%f", &d );

printf( "a %d\n", a );
printf( "b %f\n", b );
printf( "d %f\n", d );

fclose(fp);

return 0;
}

●注;datafile.txtの中身
600
0.6
3.5

○実行結果
a 600
b 0.600000
d 3.500000

あらら??
ちゃんと綺麗になっています。読み飛ばしがいらない!?ということを意味している!?
??????
でも他のプログラムではそうならないときがあったんだけどなぁ?
どうしてでしょうか?

補足日時:2004/04/12 21:41
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
>また、このテスト環境は、windowsでしょうかunixでし>ょうか。windowsの場合、正しい改行になってますか。>(16進ダンプで0x0d0aが表示されますか)
Windowsです。
ダンプって何ですか?

お礼日時:2004/04/12 21:35

参考になりそうなURL。



http://www.bohyoh.com/CandCPP/C/Library/fscanf.h …

http://homepage2.nifty.com/tenk/cgokai/scanf.htm

※scanfとfscanfは標準入力かファイル入力かが違うだけで、2つは等価です。

http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-4

http://www.catnet.ne.jp/kouno/c_faq/c12.html#20

基本的には、fscanf()ではなく、fgets()を使った方がいいです。

この回答への補足

○作成したテストプログラム
#include<stdio.h>
#include<stdlib.h>

int main()
{
int a;
float b, d;
char c, e;

FILE* fp;
fp = fopen( "datafile.txt", "r" );

fscanf( fp, "%d", &a );
fscanf( fp, "%f", &b );
fscanf( fp, "%c", &c ); // \n
fscanf( fp, "%f", &d );
fscanf( fp, "%c", &e ); // \n

printf( "a %d\n", a );
printf( "b %f\n", b );
printf( "c %c\n", c );
printf( "d %f\n", d );
printf( "e %c\n", e );

fclose(fp);

return 0;
}

●注;datafile.txtの中身
600
0.6
3.5

○実行結果
a 600
b 0.600000
c

d 3.500000
e フ

補足日時:2004/04/12 21:36
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
簡単なテストプログラムを作成しました。
補足にそのプログラムと結果を示しました。

お礼日時:2004/04/12 21:36

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!