• ベストアンサー

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が入りました。これはなぜなのでしょうか。

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

  • ベストアンサー
  • wolv
  • ベストアンサー率37% (376/1001)
回答No.5

> 最初の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を使っている、というあたりに原因がありそうです。

grothendieck
質問者

お礼

ご回答ありがとうございます。fgetsでファイルを読むと、ご回答に書かれている様になってしまいます。

その他の回答 (5)

  • wolv
  • ベストアンサー率37% (376/1001)
回答No.6

UNIXのコマンドラインが使えて、odコマンドが使えるようなら、  od -cx data.rtf|head -20 を実行してみてください。 どのような改行コードが使われているか調べることができます。

grothendieck
質問者

お礼

ご回答ありがとうございます。Mac OSXのProject builderを使っているのですが、UNIXのコマンドラインの使い方は分かりません。しかし、原因はやっと分かりました。データファイルの2行目の0.4の0と.4の間に半角のスペースが入っていてそれを見落としていました。そのため2行目が0と0.4の二つの数字とみなされていたのでした。お騒がせしましたが、ご回答下さった皆さんありがとうございました。

  • wolv
  • ベストアンサー率37% (376/1001)
回答No.4

素人です。 scanf系は、改行コードや想定しているフォーマット以外のデータの存在などが原因で、予期しない結果になる可能性があるので、一度変数に読み込んでから処理するようにしています。 #include <stdio.h> #define BUFSIZE 256 char buf[BUFSIZE];  : fgets(buf,BUFSIZE,fp); /*printf("[%s]\n",buf);*/ sscanf(buf,"%lf",&data[i]);  : こうしておくと、問題が起こった場合のチェックも楽なので。

grothendieck
質問者

お礼

御回答ありがとうございます。私はiBookでMac OSX carbonを使っています。データはExcelで作成しています。fgetsとsscanfにしてみた所、最初のfgetsでファイルの全データがbufに読み込まれ、その後のfgetsでも同じものが読まれていました。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.3

一見して問題無いように見えますが、一部、処理系に依存している部分が問題を引き起こしている可能性があります。 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++; }

grothendieck
質問者

お礼

御回答ありがとうございます。教えて頂いた様に指定してみましたが、結果は同じでした。

  • mi-si
  • ベストアンサー率35% (200/567)
回答No.2

試しに動かしてみました。(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); }

grothendieck
質問者

お礼

御回答ありがとうございます。ご回答の様にdataをprintfさせるとdata[0]は0.0となりますが、data.rtfでは2行目に0でない数が入っています。

  • soma3
  • ベストアンサー率39% (16/41)
回答No.1

おそらくですが、 for(i=0;i<n;++i){ が++iになっているからだと思います。 i++なら期待通りの動きをするのではないでしょうか?

grothendieck
質問者

お礼

御回答ありがとうございます。Cの文法から言えば、この場合++iでもi++でも良いと思います。i++もしてみましたが、同じ結果でした。

関連するQ&A

  • C言語のプログラムを見てください

    ある100行の値がx列、y列の2列あるファイルを読み込んでそれを配列に入れ、yの最小値及びそれと同じ行にあるxの値を表示するプログラムを書きたいのですがy列の最小値を表示するプログラムを書き終えた所でコンパイルして実行してみると正しく値が表示されませんでした。それどころか実行するたびに値が変わってしまいます。どこがおかしいのかわからないため、ご指摘のほどよろしくお願いします。また、できれば同じ行にあるx列の値も表示させるプログラムを教えてください。 よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #define N 100 int main(void) { int x[N],i; double y[N],min; FILE *fp; fp=fopen("book.dat","r"); if(fp==NULL){ puts("can't open file!"); exit(-1); } for(i=0;i<N;i++){ fscanf(fp,"%d %lf", &x[N],&y[N]); printf("x=%d\n y=%lf\n",x[N],y[N]); } min=y[0]; for(i=1;i<N;i++){ if(y[i]<min) min=y[i]; } fclose(fp); printf("最小値:%lf\n",min); return 0; }

  • Cプログラミングの質問なのですが,

    Cプログラミングの質問なのですが, 以下のプログラムで正規乱数を発生させたいのですが,どこがおかしいのでしょうか? fp1のransuuはきちんとtxtで作成されています。 至急お助けください。 #include <stdio.h> #include<stdlib.h> #include<math.h> #define PI 3.141592653589793238 int main (void) { FILE *fp1,*fp2; int i,n; unsigned int x1,x2; double y1,y2; fp1=fopen("ransu.txt","r"); fp2=fopen("seikiransu.txt","w"); for(i=0;i<n;i++) { fscanf(fp1,"%lf",&x1); fscanf(fp1,"%lf",&x2); y1=sqrt(2)*sqrt(-2*log(x1))*cos(2*PI*x2); fprintf(fp2,"%lf\n",y1); } fclose(fp1); fclose(fp2); return 0; }

  • 離散フーリエ変換(DFT)のプログラム

    タイトルの通りのレポートを出されたのですが、その問題に似たサンプルソースすら何をいっているのかわからない状態です。ひとまず、サンプルソースが何をいっているのか理解したいので、いくつか教えてください。 ソースです。質問はその後に書かせてもらいました。 #include<stdio.h> #include<math.h> #define N 10 #define F 0.1 #define PI 3.14151692 #define SQR(x) ((x)*(x)) void func() { int n; FILE *fp; fp=fopen("temporal.data","w"); for(n=0;n<N;n++) fprintf(fp,"%lf\n",cos(2.0*PI*F*(double)n)); fclose(fp); } void get_data(double x[]) { int n; FILE *fp; fp=fopen("temporal.data","r"); for(n=0;n<N;n++) fscanf(fp,"%lf",&x[n]); fclose(fp); } void dft(double x[],double X_r[],double X_i[]) { int k,n; for(k=0;k<N;k++){ X_r[k]=X_i[k]=0.0; for(n=0;n<N;n++){ X_r[k]+=x[n]*cos(2.0*PI*(double)n*(double)k/(double)N); X_i[k]-=x[n]*sin(2.0*PI*(double)n*(double)k/(double)N); } } for(k=0;k<N;k++) printf("X[%d]=%lf+j%lf\n",k,X_r[k],X_i[k]); } void amplitude(double X_r[],double X_i[]) { int k; FILE *fp; double amp; fp=fopen("amp.data","w"); for(k=0;k<N;k++){ amp=sqrt(SQR(X_r[k])+SQR(X_i[k])); fprintf(fp,"%lf\n",amp); } fclose(fp); } main() { double x[N],X_r[N],X_i[N]; func(); get_data(x); dft(x,X_r,X_i); amplitude(X_r,X_i); } 文字数の制限があるみたいなので、質問を別にさせてもらいます。

  • C言語のプログラミングで困っています

    C言語を勉強しています。まだまだ初心者で分からないことだらけなのですが、今回はファイル入出力の部分が分からず苦戦しています。 『100個の実数が入った2つのテキストファイルから数値を読み込み、  絶対値を求めるなどの計算をする』プログラムを作成しているのですが、 コンパイルし実行すると強制終了してしまいます。 プログラムは、 void main(void) { FILE *fp; double c[50000];   double d[50000];   double e[50000]; int n = 0;   int m = 0;   int i = 0;   char fname[80];   char fname2[80]; printf("ファイル名 : ");    gets(fname); if((fp = fopen(fname, "r")) == NULL){ printf("ファイルがオープンできません\n"); exit(1); } printf("\n"); while (fscanf(fp,"%lf",&c[i])!=EOF){ printf("%3d : %3lf",++n,c[i]); printf("\n"); i++; } printf("\n"); i=0; n=0; printf("ファイル名 : ");    gets(fname2); if((fp = fopen(fname2, "r")) == NULL){ printf("ファイルがオープンできません\n"); exit(1); } printf("\n"); while (fscanf(fp,"%lf",&d[i])!=EOF){ printf("%3d : %3lf",++n,d[i]); printf("\n"); i++; } …(以下計算) のようになっています。 整数のデータで計算を行うと、正常に動くのですが…。 コンパイルしてもエラーが出ないので、どこが悪いのかわからず困っています。 どなたか教えていただけないでしょうか。お願いしますm(_ _)m

  • C言語の質問です。

    前にも質問したのですがなかなかうまくいかないのでよろしくお願いします。 データの書いてあるファイルを読み込んで処理するプログラムを書きたいと考えています。 読み込むデータ 0.012500 0.499167 1.382500 1.534444 2.489167 3.635000 3.775000 5.407500 5.705000 5.916667 6.115833 6.295278 6.825278 7.079722 . . . . この様な数値のかいてあるデータを使って0.5ずつに区切ってその中に何個データがあるか数えたいと考えています。(データは1万5千個以上あります) 例えば上のデータで考えると 0~0.5の範囲のデータは2個 0.5~1の範囲のデータは0個 1~1.5の範囲のデータは1個 1.5~2の範囲のデータは1個 2~2.5の範囲のデータは0個。。。 という風に数えるプログラムにしたいです。 僕が分からないところはどのように場合分けしていくか。。。です。 #include<stdio.h> //#include<process.h> int main(void) { FILE *fp; double n; int cnt,i,Cnt; fp=fopen("1.dat","r"); if(fp==NULL) { printf("file open error!!\n"); exit(1); } i=0; cnt=0; Cnt=0; while(fscanf(fp,"%lf\n",&n)!=EOF){ if(i<=n<(i+0.5)){ cnt++; printf("%lf %d\n",i,cnt); } else if((i+0.5)<=n<(i+1)){ Cnt++; printf("%lf %d\n",i,Cnt); } else{ i++; } } fclose(fp); return 0; } 僕の考えはデータを読み込む 変数 i を使って if文で i <= n <i+0.5の範囲のときはcntを足していく     i+0.5<= n <i+1の範囲のときはCntを足していく それ以外のときは i を+1して同じことを繰り返す というようなやり方を考えました。 しかしうまくいきませんでした。 どのようにすればよいでしょうか。 よろしくお願いします。

  • C言語 所々の意味を教えてください><;

    #include <stdio.h> #define N 100 int main(void) { double xn[N], yn[N], x, y; int i, cnt; FILE *fp; if((fp=fopen("data.txt", "r"))==NULL) return 0; for(i=0; fscanf(fp, "%lf%lf", xn + i, yn + i)==2; i++); cnt = i; scanf("%lf", &x); if(x < xn[0] || xn[cnt-1] <= x) return 0; for(i=0; xn[i] < x; i++); y = (yn[i+1] - yn[i]) * (x - xn[i]) / (xn[i+1] - xn[i]) + yn[i]; printf("y = %f\n", y); return 0; } この文の FILE *fp; if((fp=fopen("data.txt", "r"))==NULL) return 0; for(i=0; fscanf(fp, "%lf%lf", xn + i, yn + i)==2; i++); cnt = i; ここの部分でデータテキストを読み込んでるのはわかるんですが fscanf(fp, "%lf%lf", xn + i, yn + i)部分で何をやってるかわかりません。誰か教えてください

  • C言語の問題です。

    優勝者のデータを出力する以下のプログラムの空欄((1)~(3))を埋めて完成させてください。 #include<stdio.h> #define N 20 struct SANKA{ int zk; char name[30]; double time; }; void Yusyou⁽int n,struct SANKA ns[], struct SANKA *m){ struct SANKA wmin; int i; wmin = (1) for(i=1;i<n;i++){ if(wmin.time>ns[i].time) wmin=(2); } *m = wmin; } main(){ FILE *fp; struct SANKA score[N],max; int n=0; int i=0; fp=fopen("data100.txt","r"); while(fscanf(fp,"%d %s %lf,&score[n].zk,score[n].name,&score[n].time != EOF) n++ fclose(fp); Yusyou(n,score,(3)); printf("優勝者:ゼッケン番号 %3d番 %10s タイム%10.3f秒\n",max.zk,max.name,max.time); } data100.txtには 1 朝倉 20.5 2 池川 17.3 3.上原 19.2 4 榎本 17.1 5 岡田 16.2 6 河野 16.5 7 菊池 19.7 8 近藤 15.5 9 清水 18.8 10瀬田 16.8 全く見当がつきません。回答をお願いします。

  • 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 : :

  • 照合に関するプログラムについて

    2つのファイルを用意して1つが以下のaaa.txtのような数値が記述されているファイルで、もう1つがbbb.txtのようなファイルでこの中の2列目には、aaa.txtに記されている数値が含まれています。 -------aaa.txt------- -------bbb.txt------- 1.4 XMS 2.5 2.5 XMS 2.7 2.7 XMS 1.1 2.1 XMS 1.0               XMS 2.1 XMS 1.4 aaa.txtとbbb.txtそれぞれのテキストないで数字のダブリはない。bbb.txtはaaa.txtの数字をすべて含む。 aaa.txtに記述されている数値を利用して、bbb.txtの2列目で同じ数値を示すものをその数値がある行ごと取り出し、行末にnameという文字を出力し、bbb.txtの数値がaaa.txtのどの数値とも異なればそのままその行を出力するようなプログラムを書きたいと考えました。そこで、下記のようなプログラムを書いて実行したところ、こちらの意図した出力(ccc.txt)が得られませんでした。なぜ、cccのような出力にならなかったのかがわからなくて非常に困っています。どなたかこのプログラムの誤り又はもっと良い書き方を教えていただけないでしょうか。回答よろしくおねがいします。 ------------ccc.txt---------------- XMS 2.5 name XMS 2.7 name XMS 1.1 XMS 1.0 XMS 2.1 name XMS 1.4 name -----プログラム-------- #include<stdio.h> #include<string.h> int main(int argc ,char *argv[]) { FILE *fp[argc],*gp; char x[30]; int linemax,ret; double distance; int i=0; char command[30] = "wc "; char *re="> Nline.txt"; char file1[25],file2[25],file3[25],*ends;  strcat(command,argv[2]);  strcat(command,re);   system(command);  gp=fopen("Nline.txt","r"); fscanf(gp,"%d%s%s%s",&linemax,file1,file2,file3);   system("rm Nline.txt");  fp[0]=fopen(argv[1],"r");  linemax=linemax-1; while(fscanf (fp[0],"%s %lf",x,&distance==9){ while(fscanf(gp,"%lf",&dis)==1){  if(dis==distance){   printf("%s %lf name \n",x,distance);   i=0;   }else if(dis!=distance && i==linemax){    printf("%s %lf \n",x,distance);   i=0;   }   i++; }rewind(gp); } fclose(gp); fclose(fp[0]); return 0; }

  • C言語のプログラムに関する質問です。

    C言語初心者で困っています。 SNをサンプリング数、FNをファイル数として、テキストファイルの1行目のデータ(kari[0])と2行目のデータ(kari[1])をそれぞれCH1、CH2に読み込むような以下のようなプログラムがあります。 ------------------------------------------ //読込みファイル名の設定// for(j=1;j<FN+1;j++){ sprintf(file_name,"%s%d%s",file,j,".txt"); printf("%d%s\n",j,file_name); if ((fp = fopen(file_name, "r")) == NULL){ printf("Error: Can't open file; %s\n", file_name); } //データの読込み// for(i=0;i<SN;i++){ fscanf(fp,"%lf,%lf\n",&kari[0],&kari[1]); ch1[i]=kari[0]; ch2[i]=kari[1]; } fclose(fp);       ・       ・       ・ fclose(fp); } ---------------------------------------------- しかし、テキストファイルの初めの3行には不必要な文字列が存在するため、4行目から読み込むように設定したいのですが、やり方がよく分かりません。 どのようにプログラムを書き換えれば良いか、教えていただけると助かります。 よろしくお願いします。

専門家に質問してみよう