- ベストアンサー
Cプログラムの問題
簡単なCプログラムを作ったのですが、理解できない作動をしますので、教えて頂ければ幸いです。プログラムは int main(){ int i,j,k,n,m; double d,r; double data[300],distance[300][300]; FILE *fp; fp = fopen("data.rtf", "r"); fscanf(fp, "%d", &n); for(i=0;i<n;++i){ fscanf(fp, "%lf", &data[i]); } fclose(fp); のようなもので、data.rtfには 4 0.4 0.2 . . のようなデータが入っています。こうすると、data[0]に0.4が入ることを期待していたのですが、data[0]は0.0となり、data[1]に0.4が入りました。これはなぜなのでしょうか。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
> 最初のfgetsでファイルの全データがbufに読み込まれ、その後のfgetsでも同じものが読まれていました。 例えば、 #include <stdio.h> #define BUFSIZE 256 main(int argc,char**argv){ FILE*fp; char buf[BUFSIZE]; fp=fopen(argv[1],"r"); fgets(buf,BUFSIZE-1,fp); printf(" 1: [%s]\n",buf); fgets(buf,BUFSIZE-1,fp); printf(" 2: [%s]\n",buf); fclose(fp); } というプログラムで、 入力データが 4 0.4 0.2 だとすると、 出力が 1: [4 0.4 0.2] 2: [4 0.4 0.2] となってしまうっていうことですか? # そうだとすると、マックは改行コードとしてCRを、UNIXではLFを使っている、というあたりに原因がありそうです。
その他の回答 (5)
- wolv
- ベストアンサー率37% (376/1001)
UNIXのコマンドラインが使えて、odコマンドが使えるようなら、 od -cx data.rtf|head -20 を実行してみてください。 どのような改行コードが使われているか調べることができます。
お礼
ご回答ありがとうございます。Mac OSXのProject builderを使っているのですが、UNIXのコマンドラインの使い方は分かりません。しかし、原因はやっと分かりました。データファイルの2行目の0.4の0と.4の間に半角のスペースが入っていてそれを見落としていました。そのため2行目が0と0.4の二つの数字とみなされていたのでした。お騒がせしましたが、ご回答下さった皆さんありがとうございました。
- wolv
- ベストアンサー率37% (376/1001)
素人です。 scanf系は、改行コードや想定しているフォーマット以外のデータの存在などが原因で、予期しない結果になる可能性があるので、一度変数に読み込んでから処理するようにしています。 #include <stdio.h> #define BUFSIZE 256 char buf[BUFSIZE]; : fgets(buf,BUFSIZE,fp); /*printf("[%s]\n",buf);*/ sscanf(buf,"%lf",&data[i]); : こうしておくと、問題が起こった場合のチェックも楽なので。
お礼
御回答ありがとうございます。私はiBookでMac OSX carbonを使っています。データはExcelで作成しています。fgetsとsscanfにしてみた所、最初のfgetsでファイルの全データがbufに読み込まれ、その後のfgetsでも同じものが読まれていました。
- chie65536
- ベストアンサー率41% (2512/6032)
一見して問題無いように見えますが、一部、処理系に依存している部分が問題を引き起こしている可能性があります。 fopenのオープンモードに「テキスト形式」を指定可能であれば、指定してみて下さい。 fp = fopen("data.rtf", "r"); ↓ fp = fopen("data.rtf", "rt"); 入力ファイルの改行が<LF>のみではなく<CR><LF>になっていて、fscanfが<CR>をホワイトスペース以外のキャラクタとしてスキップしてくれていないかも知れません。 fscanf(fp, "%d", &n); ↓ fscanf(fp, "%d\r", &n); fscanf(fp, "%lf", &data[i]); ↓ fscanf(fp, "%lf\r", &data[i]); forループの増分の評価はループ処理の後に行われるので問題を起こさない筈ですが、ループ処理の前に増分の評価を行う「腐ったコンパイラ」を使ってはいませんか? for(i=0;i<n;++i){ fscanf(fp, "%lf", &data[i]); } ↓ for(i=0;i<n;){ fscanf(fp, "%lf", &data[i]); i++; }
お礼
御回答ありがとうございます。教えて頂いた様に指定してみましたが、結果は同じでした。
- mi-si
- ベストアンサー率35% (200/567)
試しに動かしてみました。(RedHat7.3 gcc 2.96) n=4 data[0] 0.400000 data[1] 0.200000 data[2] 0.600000 data[3] 0.800000 問題無いですねぇ・・・。 入力データをチェックしてみた方が良いかもしれません。 #include<stdio.h> int main(void){ int i,j,k,n,m; double d,r; double data[300],distance[300][300]; FILE *fp; fp = fopen("data.rtf", "r"); fscanf(fp, "%d", &n); printf("n=%d\n",n); for(i=0;i<n;++i){ fscanf(fp, "%lf", &data[i]); printf("data[%d] %lf\n",i,data[i]); } fclose(fp); }
お礼
御回答ありがとうございます。ご回答の様にdataをprintfさせるとdata[0]は0.0となりますが、data.rtfでは2行目に0でない数が入っています。
- soma3
- ベストアンサー率39% (16/41)
おそらくですが、 for(i=0;i<n;++i){ が++iになっているからだと思います。 i++なら期待通りの動きをするのではないでしょうか?
お礼
御回答ありがとうございます。Cの文法から言えば、この場合++iでもi++でも良いと思います。i++もしてみましたが、同じ結果でした。
お礼
ご回答ありがとうございます。fgetsでファイルを読むと、ご回答に書かれている様になってしまいます。