- ベストアンサー
プログラム実行時の意図した出力が得られない理由を教えてください
- 質問者は、aaa.txtファイルとbbb.txtファイルに記述されている数値を比較し、bbb.txtファイルの中でaaa.txtファイルの数値と一致する行を「name」という文字と共に出力したいと考えています。
- しかし、現在のプログラムでは意図した出力が得られていません。
- 質問者は、このプログラムの誤りや改善点を知りたいとしています。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
> --- aaa.txt > 1.4 > 2.5 > 2.7 > 2.1 > > --- bbb.txt > XMS 2.5 > XMS 2.7 > XMS 1.1 > XMS 1.0 > XMS 2.1 > XMS 1.4 おおっ、なるほど。 もし私だったら、質問者さんと同様に rewind を使うでしょう。 ファイルをディスクから読み込むという前提を置いてよければ。 #include<stdlib.h> #include<stdio.h> #include<stdbool.h> #include<string.h> #include<math.h> #define EPS 10e-6 /* 数値の比較 */ static bool equal_distance(char *line_a, char *line_b) { double dist_a, dist_b; char ignore[64]; sscanf(line_a, "%lf", &dist_a); sscanf(line_b, "%s %lf", ignore, &dist_b); return fabs(dist_a - dist_b) < EPS; } /* ファイルaの各行と, 行line_b の比較 */ static void compare_lines(FILE *a, char *line_b) { char line_a[64]; rewind(a); while (fgets(line_a, sizeof line_a, a) != NULL) { if (equal_distance(line_a, line_b)) { if (strchr(line_b, '\n') != NULL) line_b[strlen(line_b)-1] = '\0'; printf("%s %s\n", line_b, "name"); return; } } printf("%s", line_b); } /* ファイルa,bの比較 */ static void compare_files(FILE *a, FILE *b) { char line_b[64]; while (fgets(line_b, sizeof line_b, b) != NULL) compare_lines(a, line_b); } int main(int argc ,char *argv[]) { FILE *a, *b; if (argc != 3) exit(EXIT_FAILURE); a = fopen(argv[1], "r"); b = fopen(argv[2], "r"); if ((a == NULL) || (b == NULL)) exit(EXIT_FAILURE); compare_files(a, b); fclose(a); fclose(b); return EXIT_SUCCESS; }
その他の回答 (5)
- redfox63
- ベストアンサー率71% (1325/1856)
--- aaa.txt 1.4 2.5 2.7 2.1 --- bbb.txt XMS 2.5 XMS 2.7 XMS 1.1 XMS 1.0 XMS 2.1 XMS 1.4 こんな具合かと #include <stdio.h> #include <string.h> int main(int argc, char* argv[]) { FILE *fp[3]; char lbuf[256]; char line[3][10][32] = {""}; char src[10][32] = {""}; int n, m; int cnt; // aaa.txtを取得 if ( NULL != ( fp[0] = fopen( "aaa.txt", "r" ) ) ) { cnt = 0; while( fgets( lbuf, sizeof( lbuf ), fp[0] ) ) { sscanf( lbuf, "%s", src[cnt] ); cnt++; } fclose( fp[0] ); // bbb.txtを読み込み aaa.txtを検索する if ( NULL != (fp[1] = fopen( "bbb.txt", "r") ) ) { n = 0; while( fgets( lbuf, sizeof( lbuf ), fp[1] ) ) { // XMS と 2.5などを分離して読み込む sscanf( lbuf, "%s %s", line[0][n], line[1][n] ); for( m=0; m < cnt; m++ ) { // 2.5などを aaa.txtのデータと照合 if ( strcmp( line[1][n], src[m] ) == 0 ) { // 見つかれば nameを設定し 照合を中断 strcpy( line[2][n], "name" ); break; } } n++; } fclose( fp[1] ); // ccc.txtの書き出し if ( NULL != ( fp[2] = fopen( "ccc.txt", "w" ) ) ) { for( n=0; line[0][n][0] != '\0'; n++ ) { // XMS 2.5を書き出し fprintf( fp[2], "%s %s", line[0][n], line[1][n] ); if ( line[2][n][0] != '\0' ) { // nameが設定されていれば書き出し fprintf( fp[2], " %s", line[2][n] ); } // 改行を追加 fprintf( fp[2], "\n" ); } fclose( fp[2] ); } } } return 0; }
- wormhole
- ベストアンサー率28% (1626/5665)
#1さんへ >> while(fscanf(gp,"%lf",&dis)==1){ >このgpは >> gp=fopen("Nline.txt","r"); >で代入されていますが、Nline.txtは >> system("rm Nline.txt"); >で削除されています。削除されたファイルからは読めないと思うのですが。 unix系限定になると思いますが、ファイルをオープンした状態ならファイル(名)を削除してもファイルの読み書きはできます。
- asuncion
- ベストアンサー率33% (2127/6289)
-------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の内容を正確に把握することができません。 >char command[30] = "wc "; > system("rm Nline.txt"); wcコマンドやrmコマンドがない環境のことを考慮される方がいいような気がします。 >while(fscanf (fp[0],"%s %lf",x,&distance==9){ 閉じカッコが足りないため、コンパイルエラーが出ると思います。
質問文にある aaa.txt と bbb.txt の例は下で正しいですか。 ------- aaa.txt 1.4 XMS 2.5 2.5 XMS 2.7 2.7 XMS 1.1 2.1 XMS 1.0 ------- ここまで ------- bbb.txt XMS 2.1 XMS 1.4 ------- ここまで ccc.txt の例で「name」が付いている行の数字は 2.5、 2.7、 2.1、 1.4 の四種類ですが、なぜ「同じ数値を示すものをその数値がある行ごと取り出し、行末にnameという文字を出力」すると ccc.txtのようになるのでしょう? 何か足りないのでは。
- kmee
- ベストアンサー率55% (1857/3366)
> while(fscanf(gp,"%lf",&dis)==1){ このgpは > gp=fopen("Nline.txt","r"); で代入されていますが、Nline.txtは > system("rm Nline.txt"); で削除されています。削除されたファイルからは読めないと思うのですが。 間違いではないけど、気になる部分としては > FILE *fp[argc] argc個配列で用意する意味は?結局、fp[0]しか使ってないですよね? あと、最近の仕様では、配列の大きさの指定に変数が使えるようになっていますが、もともとは定数しか使えませんでした。 > fscanf(gp,"%d%s%s%s",&linemax,file1,file2,file3); fscanfのマニュアルで、書式のところを良く読みましょう。 変数に取り込まない書式があります。 単語数、文字数に対応する変数名がfile1,file2というのは、間違いではないですが、なんか気持ち悪いです。 > system(command); > system("rm Nline.txt"); なぜ、外部コマンドを使っているのでしょうか? ここでやってることは ・wcコマンドで行数を数えて Nline.txt という一時ファイルに保存する ・Nline.txtを消す の2つです。 ファイル消去にはremove関数があります。 行数を数える部分もCで書けば、そもそもNline.txtを作成する必要もありません。 C言語で作らず、シェルスクリプトやawk,Perl等のスクリプトで作った方が簡単ではないですか?
お礼
おお、なるほど。回答ありがとございます。