- 締切済み
プログラミング(構造体、ファイル入出力、コマンドライン引数)
プログラミング(C言語)の質問です。 コマンドライン引数を使って3点の座標の並びが1レコードに記録されたファイルを読み込み、3点の並びが、時計回りに三角形を形作るか、反時計回りに三角形を形作るか、直線(あるいは一点)上にあるかを判定し、読み込んだ各レコードを判定に従って、3つの出力ファイル(時計回りだけのファイル、反時計回りだけのファイル、直線だけのファイル)に分配して書き込むプログラムを作成しています。しかし、なかなか完成しない上、どこが間違っているのかも分かりません。下に私が作ったプログラムを添付しておくのでどこが間違っているのか指摘してください。よろしくお願いします。 #include <stdio.h> #define BUFLEN 1024 int main(int argc, char *argv[]){ int difference_x1, difference_y1, difference_x2, difference_y2; int cross_product; char buf[BUFLEN]; struct points{ int x; int y; } point_a, point_b, point_c; FILE *fp1, *fp2; while(fgets(buf, BUFLEN, fp1) != NULL){ fp1 = fopen(argv[1], "r"); fgets(buf, BUFLEN, fp1); sscanf(buf, "%d,%d,%d,%d,%d,%d", &point_a.x, &point_a.y, &point_b.x, &point_b.y, &point_c.x, &point_c.y); difference_x1 = point_b.x - point_a.x; difference_y1 = point_b.y - point_a.y; difference_x2 = point_c.x - point_a.x; difference_y2 = point_c.y - point_a.y; cross_product = difference_x1 * difference_y2 - difference_x2 * difference_y1; if(cross_product < 0){ fp2 = fopen("clockwise.txt", "w"); }else if(cross_product > 0){ fp2 = fopen("counterclockwise.txt", "w"); }else if(cross_product == 0){ fp2 = fopen("straightline.txt", "w"); } fprintf(fp2, "%d,%d,%d,%d,%d,%d", point_a.x, point_a.y, point_b.x, point_b.y, point_c.x, point_c.y); fclose(fp2); } fclose(fp1); return 0; }
- みんなの回答 (5)
- 専門家の回答
みんなの回答
- yama5140
- ベストアンサー率54% (136/250)
>どこが間違っているのか指摘してください。 1) >while(fgets(buf, BUFLEN, fp1) != NULL){ ↑コンパイル時に「警告」がでますよね、fp1 は値が代入される前に使われたと。 これを無視せず、 >fp1 = fopen(argv[1], "r"); を前にし、fp1 を確定しましょう。 2) >fp2 = fopen("clockwise.txt", "w"); これらファイルオープン3行は「新規」ですので、「書き込み」の条件合致の都度、新たにオープンします。 (= >最後に判定したものしか書き込まれていません) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 以上、大きく2点について修正したものでアドバイス(BorlandC++5.5.1)。 あと、 ・fgets() + sscanf() を fscanf() で代用しています。 ・出力3ファイルのファイルポインタを使っています。 http://www.bohyoh.com/CandCPP/C/Library/fscanf.html 《蛇足》 プログラムの作成・実行は、自己責任?の世界です。 不具合時に、困るのは自分です。 例)実行時、コマンドラインに、入力ファイル名を付け忘れた場合。 これへの対応をコード化しておくも、しないも自由です。 ただし、 ☆課題等でソースを提出する場合は、上への対応や「ファイルがオープンできない」場合等の「エラー処理」を記述しておくことが必須となります。 #include <stdio.h> #define TOKEI 0 #define HNTKI 1 #define SLINE 2 int main( int argc, char *argv[] ) { int difference_x1, difference_y1, difference_x2, difference_y2; int cross_product; FILE *fp1, *fp2, *fP[ 3 ]; struct points{ int x; int y; }point_a, point_b, point_c; fp1 = fopen( argv[ 1 ], "r" ); fP[ TOKEI ] = fopen( "clockwise.txt", "w" ); fP[ HNTKI ] = fopen( "counterclockwise.txt", "w" ); fP[ SLINE ] = fopen( "straightline.txt", "w" ); while( 6 == fscanf( fp1, "%d,%d,%d,%d,%d,%d", &point_a.x, &point_a.y, &point_b.x, &point_b.y, &point_c.x, &point_c.y ) ){ difference_x1 = point_b.x - point_a.x; difference_y1 = point_b.y - point_a.y; difference_x2 = point_c.x - point_a.x; difference_y2 = point_c.y - point_a.y; cross_product = difference_x1 * difference_y2 - difference_x2 * difference_y1; fp2 = fP[ SLINE ]; if( cross_product < 0 ) fp2 = fP[ TOKEI ]; if( cross_product > 0 ) fp2 = fP[ HNTKI ]; fprintf( fp2, "%d,%d,%d,%d,%d,%d\n", point_a.x, point_a.y, point_b.x, point_b.y, point_c.x, point_c.y ); } fcloseall(); return( 0 ); } 注:インデントに全角空白を用いています。コピペ後、タブに一括変換して下さい。
- asuncion
- ベストアンサー率33% (2127/6289)
まあ、あれでしょうか。 fp2を3種類のファイルで使い回す代わりに、 1ファイルについて1ファイルポインターを対応させるのが、 わかりやすくてよいかもしれません。
- asuncion
- ベストアンサー率33% (2127/6289)
>3つのファイルができたのはいいんですが、最後に判定したものしか書き込まれていません。 だとすると、 >指摘された通り直したら上手くいきました。 そうではなくて、まだうまくいきません、ですね。 書込み用ファイルのオープンモードはどうなっていますか?
- asuncion
- ベストアンサー率33% (2127/6289)
>while(fgets(buf, BUFLEN, fp1) != NULL){ この「前に」ファイルをオープンしてください。 >fp1 = fopen(argv[1], "r"); この文は、ループの外に出してください。そして、 この文の前で、コマンドライン引数の個数をチェックしてください。 また、オープンがうまくいかなかったときの処理を加えてください。 >fgets(buf, BUFLEN, fp1); この文は不要です。 >fp2 = fopen("clockwise.txt", "w"); 毎回、新規作成モード("w")でよいのでしょうか? また、オープンがうまくいかなかったときの処理を加えてください。 >}else if(cross_product == 0){ 負でも正でもなければゼロに決まっていますので、 if~ は冗長です。else { でじゅうぶんです。 まだ、他にあるかもしれません。
- D-Matsu
- ベストアンサー率45% (1080/2394)
「何が間違いなのか」はわからなくても「実行結果がどう自分の期待通りでないのか」はわかりますよね? まずはそれを提示してください。
補足
回答ありがとうございます。 指摘された通り直したら上手くいきました。 ただ、3つのファイルができたのはいいんですが、最後に判定したものしか書き込まれていません。判定したもの全てが書き込まれているようにしたいのですがどうしたらよいでしょうか?