• ベストアンサー

fscanfについて

ファイルの中身が例えば 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の読み飛ばしがいらないのは何故ですか?

質問者が選んだベストアンサー

  • ベストアンサー
  • manayu
  • ベストアンサー率53% (79/148)
回答No.5

#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.html http://e-words.jp/w/E382B3E382A2E38380E383B3E38397.html

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

お礼

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

Rossana
質問者

補足

%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

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (7)

  • manayu
  • ベストアンサー率53% (79/148)
回答No.8

#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

Rossana
質問者

お礼

%sも改行を無視してくれるんですね。 XYZを読み込んだあとEOFとなることを見落としていました。それでごみが残ったままになってしまっていたんですね。よく分かりました!! 長々と本当にありがとうございました。今まで抱いていた疑問が一気に解消できました!またC言語の事で分からない事があったらよろしくお願いします。

全文を見る
すると、全ての回答が全文表示されます。
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.7

#3です。 >「fscanfで読み込むと改行\nを読み込んでくれる場合と読み込まない場合がありませんか?」 と最初の質問で言ったできごとをちゃんと起こす事ができました。 >補足回答よろしくお願いします。 うーむ。再現しましたね。私の環境でも再現しました。 >このようにどうやら%cで読み込む時になんか変なことが起こってしまうようなんです。 >何故なのでしょうか?? #3で「たぶん、正常なデータが入ってなかったのだと思います。」と回答しましたが、これは誤りでした。 #5の方が回答を書かれていますが、まさしくその通りです。お詫びして、訂正致します。

Rossana
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。
  • manayu
  • ベストアンサー率53% (79/148)
回答No.6

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

Rossana
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。
  • kmb01
  • ベストアンサー率45% (63/138)
回答No.4

scanf系で%c以外の書式指定ではデータの前の空白文字(スペース、タブ、改行)を読み込むが無視するという処理をします。データの後の空白文字は読み込まず次のscanf実行に持ち越されます。 対して%c書式指定では空白文字であっても読み込みます。

Rossana
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

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

Rossana
質問者

お礼

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

Rossana
質問者

補足

このようにどうやら%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

全文を見る
すると、全ての回答が全文表示されます。
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

通常は、全て正常データであれば、 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が表示されますか) 上記の点をチェックしてみて下さい。

Rossana
質問者

お礼

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

Rossana
質問者

補足

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

全文を見る
すると、全ての回答が全文表示されます。
  • manayu
  • ベストアンサー率53% (79/148)
回答No.1

参考になりそうなURL。 http://www.bohyoh.com/CandCPP/C/Library/fscanf.html 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()を使った方がいいです。

Rossana
質問者

お礼

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

Rossana
質問者

補足

○作成したテストプログラム #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 フ

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • fscanfの書式について

    fscanfの書式について a[n][n]が、 a11,a12,a13---a1n, a21,----------a2n, . . an1,----------ann, という風に並んでいるファイルを読み込む場合、どのように記述すれば良いのでしょうか? 例えばFortranでは、 DO I=1,N READ(11,'(N(F8.4,A1))')(A(I,J),KAMA, I=1,N) END DO と書けば良いのですが、Cでの書き方が分りません。 元々Fortranを使いでCは初心者です。 ちなみに、 for(i=0;i<=n+1;i++){ for(j=0;j<=n+1;j++){ fscanf(fp,"%f7.6 %1s ",&a[i][j],kama); } } と書いて見たものの、駄目でした。 改行してしまうのだと思うのですが、避ける方法も、そもそも、それが出来るのかどうかも分りません。。 よろしくお願いいたします。

  • fscanf関数について

    -------------------------------------------------- #include<stdio.h> #include<stdlib.h> int main() { FILE*fp; int ch,dt; char ss[80]; if((fp=fopen("bbb.txt","w"))==NULL){ printf("出力ファイルをオープンできません.\n"); exit(1); } fprintf(fp,"%c",'A'); fprintf(fp,"%s\n","abcdeABCDE"); fprintf(fp,"%d\n",1234); fclose(fp); if((fp=fopen("bbb.txt","r"))==NULL){ printf("入力ファイルをオープンできません.\n"); exit(1); } ch=fgetc(fp); printf("ch=%c\n",ch); fscanf(fp,"%s",ss); printf("ss=%s\n",ss); fscanf(fp,"%d",&dt); printf("dt=%d\n",dt); fclose(fp); return 0; } -------------------------------------------------- 以上のプログラムで、プログラムの通り「bbb.txt」は、 AabcdeABCDE 1234 となっております。 そこで疑問なのですが、「ch=fgetc(fp);」は1文字読み込みなので、'A'だけと分かるのですが、「fscanf(fp,"%s",ss);」はfpからの読み込みで何故、 AabcdeABCDE 1234 の全部を読み込まず、'A'を抜かした、「abcdeABCDE」だけを読み込んでくれるのか? 後、「fscanf(fp,"%d",&dt);」は何故「AabcdeABCDE」を抜かした、「1234」だけを読み込んでくれるのかが分かりません。 「fscanf(fp,"%d",&dt);」については数値だけを読み込んでくれるのかと思い、 ch=fgetc(fp); printf("ch=%c\n",ch); fscanf(fp,"%s",ss); printf("ss=%s\n",ss); の部分を無くせば、「1234」だけを読み込んでくれるのかと思ったのですが、数値は正しく表示されません。 以上教えていただければ嬉しいです。

  • fscanf ファイルから数を読み込む。

    ファイルから数を読み込むと 4201696 4201696 4201696 と、sample.txtにない数が表示されます。 sample.txtの中身は、2から6の数です。 sample.txtの中身は画像に添付しました。 以下は実行したプログラムです。 #include<stdio.h> #include <assert.h> int main(void){ FILE *fp; int a,b,i; if((fp=fopen("sample.txt","a"))==NULL){ printf("fileopen error\n"); } printf("整数を入力してください。"); scanf("%d",&a); fprintf(fp,"%3d\n",a); printf("整数を入力してください。"); scanf("%d",&a); fprintf(fp,"%3d\n",a); i=0; while(i<3){ fscanf(fp, "%d",&b); assert(b>2); printf("%3d\n",b); i++; } return(0);} 2から6の間の数が表示されるよう、指摘をおねがいします。

  • fscanf()

    fcanf()がうまくいきません。 画面には、42640888のような数値が表示されます。 どこが間違ってるか教えてください。 (test.txtに23と書いてあるとします。) #include<stdio.h> int main(void) {    FILE *fp;    FILE *fp1;    char str[10];    int a;    fp=fopen("test.txt","r")    fp1=fopen("a.txt","w")    while(!feof(fp)){       fgets(str,8,fp);       fputs(str,fp1);    }    fscanf(fp,"%d",&a);    printf("%d",a);   fclose(fp);   fclose(fp1);   return 0; }

  • fscanf

    fscanfを使って、ファイル(普通の英文が入っています)から一単語ずつ読み込んでいきたいと思っているのですが、どうすれば良いのかわかりません。 int main(int argc,char *argv[]){ FILE *fp; char *word; fp = fopen(argv[1], "r"); if(fp == NULL){ printf("error: not open file.\n"); return(0) ;} while( ){ fscanf(fp,"%[a-zA-Z]",word); printf("%s\n", word); fflush(stdout); } fclose(fp); return 0; } とりあえず上の様なプログラムで、一単語ずつ順番に単語を出力できるようにしたいと思っているのですが。 いろいろ変なところなど在ると思いますが、whileの条件など、どうすればよいか教えてください。

  • fscanfについて

    教えてgooを参考にしましたが、fscanfを使ってテキストファイルの任意の行のデータを読み込みたいのですがうまくいきません。 テキストファイルは 0 1 1 0 0 1 0 1 1 0 0 1 0 1 0 0 0 1 0 1 1 といった感じの2進数で3行以上あります。 下に自分が作ったソースがあります。 どこがいけないのか、どういった手法があるのかを詳しく教えていただけたら幸いです。よろしくお願いします。 int gene[10]; FILE* f=fopen("Gene.txt","r"); while(fscanf(f,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &gene[0],&gene[1],&gene[2],&gene3],&gene     [4],&gene[5],&gene[6],&gene[7],&gene       [8],&gene[9])!=EOF) n++; fclose(f);

  • ファイルからの読み込み

    fscanfを使ってファイルの中身を読み込みたいのですが、ファイルの中身の長さが統一されていない場合どうしたらよいでしょうか? 読み込むファイルの中身 A d 1 B 3 2 G 5 1 2 B 6 G H 5 2 5 今まではファイルの中身の各行の文字数が全部3つだったので fp=fopen(A.txt,"r"); while(fscanf(fp,"%s %s %s",data,data+1,data+2)!=EOF) { printf("%s?n",data); }としていました。わかりにくい文章ですいません。

  • fscanf Segmentation fault

    すいません。Segmentation faultがでてプログラムが動きません・・・原因がわからないのでわかる方がおられましたら教えてください。 FILE* Bank::setFp( const char c[]){ if(fp!=NULL){ fclose(fp); }else{ fp = fopen("c[]","r"); } return fp; } Bank::Bank(char c[]){ fp = 0; size = 0; arraySize = 0; int some = 0 ; int bal; char ac[16]; char cust[316]; fp = setFp(c); fscanf(fp, "%d:",&some); grow(arraySize+10); for(int i=1 ; i<arraySize ; i++){ fscanf(fp, "%[^,],%d,[^;];",arraySize,ac,&bal,cust); savings[i].init(cust,ac,bal); size++; fclose(fp); } } ちなみにSegmentation fault は fscanf(fp, "%d:",&some);を作動した時にでました。 ちなみにサンプルデータは、 3:423423454567987,9234617,Woo,Charles,Winnipeg,416-555-5558;523423454567987,2534,DeJesus,Pancho,Edmonton,416-555-5559;623423454567987,543876,Smith,Bob,Charlottetown,416-555-5544; です。 メインプログラムでは、Bank one("a34.dat");と読んでるだけです。 よろしくお願いします

  • C言語 ファイルの読み込みについて

    以下のようなプログラムを実行します \nで改行が行われません。なぜでしょうか? #include <stdio.h> void main () { FILE *fp; double a, b; int count=0; fp = fopen("arm_x.csv","r"); while(1) { fscanf(fp,"%lf%lf\n",&a,&b); printf("%f::%f\n",a,b); count++; if(count==10)break; } fclose(fp); } csvファイルは 0.0 0.1 0.2 0.3 0.4 0.5 0.1 0.2 0.3 0.4 0.5・・・ 0.2 0.3 0.4・・・・・・・・・ : : です。 実行結果はこのようになってしまいます。 0.0 0.1 0.2 0.3 0.4 0.5 : :

  • fscanfを使った読み取り

    datファイルの内容が 100,KAWAI YOSIKI,299,AKASAKA NOBORU・・・・ のような感じになっていて その中身を構造体配列に格納したい場合についてお聞きしたいです。 構造体の型は struct date { int id; char name[80]; }; のような感じです。自分なりに考えてfscanfを使って(省略部分あり) struct o_kaiin[20]; fp=fopen("date.dat","rb"); for(i=0;i<20;i++) { fscanf(fp,"%d%s",&o_kaiin[i].id,&o_kaiin[i].name); } という感じで格納しようとしたのですが、エラーが起こってしまいます。 名前の間に空白が無ければ問題ないのですが、このような文字列の場合 どのようにして読み込めばいいのでしょうか?ご教授ください。

このQ&Aのポイント
  • 3720Fの複合機で手差しトレイが外れてしまった状態になっています。
  • トレイを無理にはめようとすると壊れる可能性があるため、修理依頼が必要です。
  • この問題についてキヤノン製品に関する質問として、修理依頼の問題はないのか気になっています。
回答を見る