• ベストアンサー

ファイルの読み書きと行移動について

 ファイルaとファイルbから1行ずつ順にデータを読み込んでその行の大小関係を比較して、小さい方の行(同じ大きさなら両方)をファイルcに書き込むプログラムを作成したいと考えています。  そこで、以下のようなソースコード(途中まで)を書いてみました。 #include <stdio.h> main() { FILE *fpa,*fpb,*fpc; char fpa_data[200],fpb_data[200]; fpa=fopen("filea.txt","r"); fpb=fopen("fileb.txt","r"); fpc=fopen("filec.txt","a"); fscanf(fpa,"%s\n",fpa_data); fscanf(fpb,"%s\n",fpb_data); x = strcmp( fpa_data,fpb_data); if(x<0) fprintf(fpc,"%s\n",fpa_data); else if(x=0) fprintf(fpc,"%s\n%s\n",fpa_data,fpb_data); else fprintf(fpc,"%s\n",fpb_data); }  このソースコードですと、最初の1行目のみが正しく実行されると思いますが、これを2行目以降の行に対しても行うようにするには、どのようにすればよいでしょうか?  ご回答宜しくお願いします。

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

  • ベストアンサー
  • HOGERA3
  • ベストアンサー率35% (50/139)
回答No.4

>if (fgets(buff_a, BUFFSIZE, fp_a) == NULL) break; >ですと、行の終わりでwhileループから抜け出してしまい、 >1行目しかファイルcに書き込まれないような気がします。 いえいえ。 fgetsはファイルから1行読み込んで、その文字列を返します。 もしファイルの終端までいったら、NULLを返します。 >あと、ファイルの一方が先に終端までいった際には、もう一方の >ファイルの残りの行全てをファイルcに書き出したいのですが、 >どのようにすればいいでしょうか? 各ファイルが終端にいったかどうかをあらわすフラグを 用意すればいいでしょう。 たとえばこのように(a_is_endとb_is_end)。 #include <stdio.h> #include <string.h> int main(void) { #define BUFFSIZE 256   char buff_a[BUFFSIZE];   char buff_b[BUFFSIZE];   FILE *fp_a = fopen("a", "r");   FILE *fp_b = fopen("b", "r");   FILE *fp_c = fopen("c", "w");   int a_is_end = 0;   int b_is_end = 0;   while (1) {     if (!a_is_end && fgets(buff_a, BUFFSIZE, fp_a) == NULL)       a_is_end = 1;     if (!b_is_end && fgets(buff_b, BUFFSIZE, fp_b) == NULL)       b_is_end = 1;     if (a_is_end && b_is_end) break;     if (!a_is_end && !b_is_end) {       switch (strcmp(buff_a, buff_b)) {       case -1:         fprintf(fp_c, "%s", buff_a);         break;       case 0:         fprintf(fp_c, "%s%s", buff_a, buff_b);         break;       case 1:         fprintf(fp_c, "%s", buff_b);         break;       }     }     if (b_is_end) fprintf(fp_c, "%s", buff_a);     if (a_is_end) fprintf(fp_c, "%s", buff_b);   }   fclose(fp_a);   fclose(fp_b);   fclose(fp_c);   return 0; }

linuxbeginner
質問者

お礼

お礼の内容を回答に対する補足のところに書いてしまいました。申し訳ございませんでした。

linuxbeginner
質問者

補足

ご回答ありがとうございます。 >いえいえ。 fgetsはファイルから1行読み込んで、その文>字列を返します。 もしファイルの終端までいったら、N >ULLを返します。 なるほど、fgetsは文末まで順に読み込んでくれるのですね。fscanfは1行読み込んだら終わってしまいますので、私が最初に考えたプログラムではどうすることもできませんね。(笑) >各ファイルが終端にいったかどうかをあらわすフラグを >用意すればいいでしょう。 >たとえばこのように(a_is_endとb_is_end)。 そう考えたらよかったんですね。恐らく自分ひとりで考えていたら、そういう発想はできなかったと思います。  プログラムの方も先ほど実行したところ、きちんと動作しました。どうもありがとうございました。    Cをはじめて1ヶ月の初心者ですので、これからもお世話になることがあるかもしれませんが、その時には、宜しくお願い致します。(m_m)

その他の回答 (7)

  • HOGERA3
  • ベストアンサー率35% (50/139)
回答No.8

> case文中で不等号を含む条件分岐は書けるのでしょうか?(多分無理だと思いますが・・・) おっしゃるとおり、無理です。 if文を使うのが普通の方法でしょう。

linuxbeginner
質問者

お礼

何度もありがとうございました。

  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.7

> >> result = stata ? 1 : -1; >の文はどういったことをしているのでしょうか? まず、この if文(else)に入る条件は ファイルAまたは ファイルBのいずれかが既にファイルの終端まで達している場合です。 stata 及び statbは fgetsの戻り値を格納する変数で、ファイルが終端に達していれば NULLが入ってますよね。 result = stata ? 1 : -1 はご存じかもしれませんが、三項演算子で、stataが 0(NULL)ではないとき、resultに 1を格納、0以外の時は -1を格納します。つまり、stata (ファイルA)にデータが残っている場合は 1を入れ、stataが空の時(ファイルBにデータが残っているとき)は -1を入れます。 ...とここまで書いて、バグに気が付きました^^;)。 ---  int stata = 1, statb = 1;  while (1) {   if (stata) stata = fgets (fpa_data, 200, fpa);   if (statb) statb = fgets (fpb_data, 200, fpb);   if (stata && statb) {    result = strcmp (fpa_data, fpb_data);   } else if (stata || statb) {    result = stata ? 1 : -1;   } else {    break;   }   if (result <= 0) fprint (fpc, "%s\n", fpa_data);   if (result >= 0) fprint (fpc, "%s\n", fpb_data);  } --- #はづかしい...

linuxbeginner
質問者

お礼

 なるほど、そういうことだったんですね。  何度もありがとうございました。

  • HOGERA3
  • ベストアンサー率35% (50/139)
回答No.6

ちょっと注意。 strcmp(a, b)の戻り値は、 ・a < b のとき ゼロより小さいint (-1とは限らない) ・a > b のとき ゼロより大きいint(1とは限らない) ・a == b のとき 0 ですので、No.4のように-1、1と比較するのは よくないでしょう。 (自分で書いといてなんなんですが)

linuxbeginner
質問者

補足

度々ありがとうございます。 私の処理系では-1,0,1でも問題ありませんでしたが、念のために変えといた方がいいですね。 if文を使ってなら、 int x; x=strcmp(buff_a,buff_b); if(x<0); ・・・  と書けますが、  case文中で不等号を含む条件分岐は書けるのでしょうか?(多分無理だと思いますが・・・)

  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.5

締め切られていないようなので、参考までに自分のソースを改造して要求仕様に合わせてみました。 ---  int stata = 1, statb = 1;  while (stata || statb) {   if (stata) stata = fgets (fpa_data, 200, fpa);   if (statb) statb = fgets (fpb_data, 200, fpb);   if (stata && statb) {    result = strcmp (fpa_data, fpb_data);   } else {    result = stata ? 1 : -1;   }   if (result <= 0) fprint (fpc, "%s\n", fpa_data);   if (result >= 0) fprint (fpc, "%s\n", fpb_data);  } ---

linuxbeginner
質問者

補足

 度々ありがとうございます。  早速、質問させていただきたいのですが、  stataは普通の変数と考えれば宜しいのでしょうか?  それとも、何か特別な意味があるのでしょうか?  また、  >> result = stata ? 1 : -1; の文はどういったことをしているのでしょうか?  いままで、こういった文を見たことがないもので・・  低レベルな質問と思いますが、宜しければご回答をお願いします。

  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.3

あ、いきなり間違いに気が付きました^^;)。  while (stata && statb) { ->  while (stata || statb) { でした。

  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.2

若干条件があいまいなので、いくつか仮定して書いてみました。 ファイルA, ファイルBは昇順にソート済である。 同じ行同士を比較するのではなく、AとBのファイルをマージしながら昇順に書き込む。 fopen以降の例 ---  stata = fgets (fpa_data, 200, fpa);  statb = fgets (fpb_data, 200, fpb);  while (stata && statb) {   if (stata && statb) {    result = strcmp (fpa_data, fpb_data);   } else {    result = stata ? 1 : -1;   }   if (result <= 0) {    fprint (fpc, "%s\n", fpa_data);    stata = fgets (fpa_data, 200, fpa);   } else {    fprint (fpc, "%s\n", fpb_data);    statb = fgets (fpb_data, 200, fpb);   }  } --- #未検証です。

linuxbeginner
質問者

お礼

ご回答ありがとうございます。 >ファイルA, ファイルBは昇順にソート済である。 >同じ行同士を比較するのではなく、AとBのファイルをマー>ジしながら昇順に書き込む。  せっかく回答して頂いて申し訳ないのですが、ファイルA とファイルBは昇順にソート済みではないのです。私としましては、1行1行の大きさを調べながらファイルに書き込んでいくといったプログラムを作成したいと考えておりました。  誤解を与える表現で申し訳ございませんでした。

  • HOGERA3
  • ベストアンサー率35% (50/139)
回答No.1

とりあえずどっちかのファイルの終端までいったら そこでおしまいってことにするとこんな感じでしょうか。 #include <stdio.h> #include <string.h> int main(void) { #define BUFFSIZE 256   char buff_a[BUFFSIZE];   char buff_b[BUFFSIZE];   FILE *fp_a = fopen("a", "r");   FILE *fp_b = fopen("b", "r");   FILE *fp_c = fopen("c", "w");   while (1) {     if (fgets(buff_a, BUFFSIZE, fp_a) == NULL) break;     if (fgets(buff_b, BUFFSIZE, fp_b) == NULL) break;     switch (strcmp(buff_a, buff_b)) {     case -1:       fprintf(fp_c, "%s", buff_a);       break;     case 0:       fprintf(fp_c, "%s%s", buff_a, buff_b);       break;     case 1:       fprintf(fp_c, "%s", buff_b);       break;     }   }   fclose(fp_a);   fclose(fp_b);   fclose(fp_c);   return 0; }

linuxbeginner
質問者

補足

 レスありがとうございます。 少し、分からないことがありますので、質問させていただきたいのですが、 if (fgets(buff_a, BUFFSIZE, fp_a) == NULL) break; ですと、行の終わりでwhileループから抜け出してしまい、 1行目しかファイルcに書き込まれないような気がします。  あと、ファイルの一方が先に終端までいった際には、もう一方のファイルの残りの行全てをファイルcに書き出したいのですが、どのようにすればいいでしょうか?  ご回答宜しくお願い致します。

関連するQ&A

  • テキストファイルの任意の行への読み書き

    VisualC++6.0でMFCのプログラムを組んでいるのですが、 ファイルの操作で分からないことがあるので教えてください。 数行にわたってデータの書き込んであるテキストファイルがある場合、 任意の行に新たに文字を書き込んだり、任意の行のデータを読み込んだりすることは可能ですか?? fprintf,fscanfを用いて1行目から順に読み込んだり、1行目に書き込んだりという処理はできたのですが、 任意の行への読み書きができずに困っています。 初歩的な質問だとは思いますが、よろしくおねがいします。

  • コマンドラインによるファイル名指定

    #include<stdio.h> #include<stdlib.h> int main(int argc,char *argv[]) { FILE *fp,*fpc; int i=0; char line[1000]; fp = fopen("test.txt","r"); if(fp == NULL) { printf("File not found.\n"); exit(1);  }  fpc = fopen(argv[1],"w"); if(fpc==NULL){ fprintf(stdout,"Can not open file.\n"); exit(1); } while(fgets(line[i],1000,fp)!=NULL){ i++; } for(i=3;i<0;i--){ fprintf(fpc,"%s",line[i]); } fclose(fp); fclose(fpc); return 0; } コマンドラインでファイル名を指定し、そのファイルに、test.txt(4行の文字列)の内容を各行を逆順に書き出すプログラムですが、上手くいきません。ご指摘を願いします。

  • ファイルの読み書き

    ファイルに文字列を追加したいのですがファイルの開き方が "a" モードで開くと当然文章の最後に文字列が書き込まれることになります。 ですが、最後ではなく最初に文字列を追加したいためにファイルを2回づつ読み込んだり書いたりしたら2回目の読み込み時にバグが出ました どうしたらファイルの文字列を最後ではなく最初に追加できますか? 追加したい文字が: もも 今までのデーターが オレンジ みかん なら、 もも オレンジ みかん のようにしたい。 以下ソース ---ソース--- #include <stdio.h> void main(void){ FILE *fp; char *tm[1000]; char buf[400]; int i=1,sei; fp= fopen("now.txt","w+"); fprintf(fp,"もも"); fclose(fp); //何で最初に書き込んでるんだ? //という突っ込みがあるでしょうが本当に作りたいプログラムは最初にファイルに書き込まないといけないためです。 fp= fopen("now.txt","r"); while( fgets( buf, 400, fp ) != NULL ){ tm[0]=buf; } fclose(fp); printf("%s<br>",tm[0]); //確認用 この時点ではtm[0]に"もも"が入っている fp =fopen("moto.txt","r"); while( fgets( buf, 400, fp ) != NULL ){ tm[i]=buf; printf("%s<br>",tm[i]); //確認 この時点ではtm[1]に"オレンジ" tm[2]にみかんが入っている i++; } printf("%s<br>",tm[0]); //確認用 バグったtm[2]のみかんが入っている printf("%s<br>",tm[1]); //確認用 バグったtm[2]のみかんが入っている printf("%s<br>",tm[2]); //確認用 バグじゃない? fclose(fp); if(i<=1000){ sei=i; } else{ sei=1000; } fp =fopen("chat_deta.txt","w+"); for(i=0;i<sei;i++){ fprintf(fp,"%s\n",tm[i]); //バグった内容が書き込まれるためみかんが3列かきこまれる } fclose(fp); } } ---now.txt--- もも ---moto.txt--- オレンジ みかん 結果として みかん みかん みかん っとなっていますね。

  • 行ごとにファイル結合

    下記プログラムは、input1.txtの内容 0 1 2 3 4 5 6 7 8 をファイル入力して、行番号とファイルの内容を表示できるように作成したものです。 このプログラムにinput2.txt 9 10 11 12 13 14 とinput3.txt 15 16 17 をファイル入力し、行ごとに結合して 0 0 1 2 9 10 15 1 3 4 5 11 12 16 2 6 7 8 13 14 17 と表示できるようにしたいのですが、どのようにすればよいのでしょうか。ご存知の方、お手数ですが教えてください。よろしくお願いします。 #include <stdio.h> main(){ int i,j=0,N=0,n,a[100],m=0; FILE *fpi; if((fpi=fopen("input1.txt","r"))==NULL){ fprintf(stderr,"ファイルを開けません。\n"); exit(1); } while(fscanf(fpi,"%d",&a[N])!=EOF && N<100){ N++; } n=N/3; printf("%d",m); for(i=0;i<N;i++){ printf(" %2d",a[i]); j++; if(j==n && m<n-1){ printf("\n"); m++; printf("%d",m); j=0; } } fclose(fpi); }

  • 動的メモリとexit(C言語)

    fpA=fopen("name1", "r"); fpB=fopen("name2", "r"); fpC=fopen("name3", "r"); if(fpA==NULL || fpB==NULL || fpC==NULL){ exit(1); } fpAとfpBのファイルオープンに成功してfpCで失敗した場合、exit(1)によってfpAとfpBはクローズされますよね? じゃあ、 a=malloc(size); b=malloc(size); c=malloc(size); if(a==NULL || b==NULL || c==NULL){ exit(1); } aとbのメモリ確保に成功してcで失敗した場合、aとbのメモリはどうなっちゃうんでしょう?exitは動的メモリも解放してくれるのですか? とりあえず以下のようにしてますが…。 a=malloc(size); b=malloc(size); c=malloc(size); if(a==NULL || b==NULL || c==NULL){ free(a); free(b); free(c); exit(1); }

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

    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); }としていました。わかりにくい文章ですいません。

  • ファイル入力の仕方

    下記のような入力ファイル(input.txt)を配列に格納するプログラムを作成しています。 下のソースコードは行数・列数が一定の場合のものですが、実際の入力データは行数・列数とも不定です。つまり、行数・列数をプログラムで読み取らなければなりません。この場合、ソースコードをどのようにすれば良いのでしょうか? 大変お手数ですが、教えてください。よろしくお願いします。 x y1 y2 y3 y4 10.0 1.2 1.5 1.0 2.1 10.5 1.3 1.4 1.2 2.2 11.0 1.8 1.2 2.2 3.1 11.5 2.1 1.0 1.2 4.5 12.0 1.9 1.1 1.1 5.5 13.0 2.4 1.1 2.1 4.2 ・1行目をchar型配列に格納したい。 ・2行目以降はdouble型配列で1列目をX[]、2列目以降をY[][]に格納したい。 ・行数は20(2行目以降)まで、列数は10(2列目以降)まで #include <stdio.h> #include <stdlib.h> int main(){ int i,j; double X[20],Y[20][4]; char x[2],y[10][4]; FILE *fpi; if((fpi=fopen("input.txt","r"))==NULL){ fprintf(stderr,"Cannot open file.\n"); exit(1); } fscanf(fpi,"%s %s %s %s %s",x,y[0],y[1],y[2],y[3]); printf("%s %s %s %s %s\n",x,y[0],y[1],y[2],y[3]); for(i=0;i<6;i++){ fscanf(fpi,"%lf",&X[i]); printf("%4.1lf ",X[i]); for(j=0;j<4;j++){ fscanf(fpi,"%lf",&Y[i][j]); printf("%4.1lf ",Y[i][j]); } printf("\n"); } printf("\n"); return 0; }

  • 複数テキストファイルを読み込み、複数テキストファイルの出力

    質問は100個のテキストファイル(それぞれ10個のデータを含む)を読み込み、それぞれのテキストファイルから5個ずつデータを抽出し、200個のテキストファイルとして出力するというプログラムについての質問です。 以下が僕の作ったファイル出力部分のプログラムです。 /************/ void ecg_rr(fp,data_max) FILE *fp; { int b,i=0; int c=1; char fname[64]; data[0][i]=trend_data[0][i]; for(i=0;i<100;i++) sprintf(fname,"ss[%d].txt",1+i); fp = fopen(fname,"w"); fprintf(fp,"%4d\n",c); fprintf(fp,"%8.8f\n",data[0][0]); fprintf(fp,"%8.8f\n",data[0][2]); fprintf(fp,"%8.8f\n",data[0][4]); fprintf(fp,"%8.8f\n",data[0][6]); fclose(fp); sprintf(fname,"sk[%d].txt",1+i); fp = fopen(fname,"w"); fprintf(fp,"%4d\n",c); fprintf(fp,"%8.8f\n",data[0][1]); fprintf(fp,"%8.8f\n",data[0][3]); fprintf(fp,"%8.8f\n",data[0][5]); fprintf(fp,"%8.8f\n",data[0][9]); fclose(fp); } 複数ファイルの読み込み方がわからず、自分のプログラムだと1つのテキストファイルしか読み込めないので、16_4.batを作り、その中身を 16_4 読み込むテキストファイル名1.txt ss[1] 16_4 読み込むテキストファイル名1.txt sk[1] 16_4 読み込むテキストファイル名2.txt ss[2] 16_4 読み込むテキストファイル名2.txt sk[2] ・・・ とやったのですが、うまくいきませんでした。 どうすればよいのでしょうか。

  • fprintfで出力するファイルのパス指定について

    cで以下のコードを書いています。 file.txtを任意の場所に作りたいのですが どうすればいいのでしょうか。 fopen("c:\file.txt", "r"))と書くとエラーになって しまいました。 void main(void) { FILE *fp; if ((fp = fopen("file.txt", "r")) == NULL) { fprintf ( stderr, "err\n" ); exit (2); } fprintf(fp,"%s\n",a);; fclose(fp); }

  • クイックソート

    実行時にエラーが出てしまいます。問題点がわかる方お願いします。(インクルード略、800字に収まらなかったので問題があると思われる部分だけ書きます。)ちなみにエラーは外部参照~という感じです。 typedef struct in_data { char bango[No_SIZE]; int ki; }RD; RD *q_sort(RD a[],int n0,int nn); void swap(RD *pa,RD *pb); void main() { FILE *fpa; FILE *fpb; char in_buff[BUFF_SIZE]; RD buff[ARRY_SIZE]; int i; fpa = fopen("data.TXT","r"); for(i=0;i < ARRY_SIZE;i++){ fgets(in_buff,BUFF_SIZE,fpa); strncpy(buff[i].bango,in_buff,No_SIZE); buff[i].bango[No_SIZE] = '\n'; buff[i].ki = atoi(&in_buff[No_SIZE]); } fclose(fpa); q_sort(buff,0,ARRY_SIZE-1); fpb = fopen("result.TXT","w"); for(i=0;i < ARRY_SIZE ; i++) fprintf(fpb,"%*s %*d\n",No_SIZE,buff[i].bango, season_SIZE,buff[i].ki); fclose(fpb); } RD *qsort(RD a[],int n0,int nn) { char x; int i,j; if(nn - n0 == 1){ if(strcmp(a[n0].bango,a[nn].bango)>0) swap(&a[n0],&a[nn]); } else if (nn - n0 >1){ x = (n0+nn)/2;

専門家に質問してみよう