プログラムのファイル読み込みと図形描画に関する質問

このQ&Aのポイント
  • 質問者はテキストファイルを読み込み、XとYに付属する値を取り出して図形を描くプログラムについての質問をしています。
  • 質問者は、プログラムの中でのxstr=xbufの挙動と、xbufやybufの必要性について知りたいと思っています。
  • また、もしxbufやybufが不要であれば、どのように書き直すべきかも教えてほしいとしています。
回答を見る
  • ベストアンサー

プログラム

{ FILE *fp; char *str,buf[1000]; char xbuf[100],*xstr;   char ybuf[100],*ystr; static double bx=0; static double by=0; if ((fp = fopen("kadai.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) xstr=xbuf; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *xstr++=*str++; *xstr='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) ystr=ybuf; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *ystr++=*str++; *ystr='\0'; } else str++; } pDC->MoveTo((int)bx,(int)by); pDC->LineTo((int)atof(xbuf),(int)atof(ybuf)); bx=(int)atof(xbuf); by=(int)atof(ybuf); } } fclose(fp); return 0; } とテキストファイルを読み込みその中のXとYに付属する値を 取り出し図形を書くというプログラムなのですが X100Y100 X200Y100というファイルなら (0,0)→(100,100)→(200,100)という2つの直線が描かれます。 実行の結果正常に動きました。 str=buf; の部分ではbufの先頭要素のアドレスをstrに設定している のはわかりました。 しかしxstr=xbufの所ではわからないことがあります。 bufでfpから読み込んだ文字列1行が入っているのはわかります。 しかしxbufにはまだ何も入ってないはずなのに xstr=xbufの所でxbufにはxの値がしっかり入っていました。 これはどうしてでしょうか xbufとかybufとかいらないような気もするのですが もしそうならばどのように書き直せばいいのでしょうか? この2点について教えてください。

  • zaqwe
  • お礼率15% (19/123)

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

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

>xstr=xbufの意味合いがいまいち理解できないのですが >xbufに何も入ってないのに先頭にもっていくのは先頭から順にいれていくと意図でしょうか? >後xstrにxの値がはいってるのはわかりますが、xbufにまで入ってるのはどうしてでしょうか? xstr = xbuf; とやると「xstrはxbufの先頭を指す」のです。 その後、数字か-か.の間だけ *xstr++ = *str++; を繰り返すと「strの指す場所から、xstrに、つまり、xbufに」文字がコピーされていきます。 つまり「Xの次からの数字文字を、xbufにコピーしている」のです。 一見、xstrにコピーしているように見えますが「xstrはxbufを指している」ので、xstrにコピーしていくと、xbufにコピーする事になります。 xbufは「配列」ですから「xbuf++」というような事は出来ません。その代わりに「xstr++」で1バイトづつ進めながら、数字以外が来るまでコピーしているのです。

その他の回答 (3)

  • php504
  • ベストアンサー率42% (926/2160)
回答No.3

>xstrにxの値がはいってるのはわかりますが、xbufにまで入ってるのはどうしてでしょうか? *xstrに代入するということは同時にxbuf[ ]にも代入することになります。 xstr = xbuf; *xstr++ = *str++; これは int i = 0; xbuf[ i++ ] = *str++; と同じ処理になります

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

追記。 以下の条件式の「*str!='\0' &&」は、すべて無意味です。 if(*str!='\0' && *str=='X'){ if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) if(*str!='\0' && *str=='Y'){ if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) なぜなら if(*str!='\0' && *str=='X'){ *str=='X'が成り立つなら*str!='\0'も常に成り立ちます。 if(*str=='X'){ で充分です。 if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) (isdigit(*str) || *str=='-' || *str=='.')が成り立つなら、以下同文。 if(isdigit(*str) || *str=='-' || *str=='.')) で充分です。 これとは別に「同じ事をもう一度判定している」ので、殆どのif文が不要になります。 しかも、下手にif文で「条件が成り立った時しか代入しない」と言う処理をしているおかげで、イリーガルな文字列が入力されるとxstrやystrがリセットされず、想定外のメモリに書き込みし、不正な処理をする可能性があります。 上記を踏まえ、書き直すと、以下のようになります。 { FILE *fp; char *str,buf[1000]; char xbuf[100],*xstr; char ybuf[100],*ystr; static double bx=0; static double by=0; xbuf[0]='\0'; // 1行目に「X???」が無いとxbufが不定なままatof(xbuf)してしまうので空文字列に初期化しておく ybuf[0]='\0'; // 1行目に「Y???」が無いとybufが不定なままatof(ybuf)してしまうので空文字列に初期化しておく if ((fp = fopen("kadai.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf; while((*str!='\0'){ if(*str=='X'){ str++; // strを進めるだけで良い。*str++;と書く必要はない // if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) // このif文は不要。Xの後に変な文字があるとxstrが不定のまま処理が続いてしまう xstr=xbuf; // if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) // このif文は無意味。while文は「最初から条件が成り立ってなければ何もしない」ので、判定する意味がない while(isdigit(*str) || *str=='-' || *str=='.') *xstr++=*str++; *xstr='\0'; } if(*str++=='Y'){ // 判定のついでにstrを進めておく // if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) // このif文は不要。Yの後に変な文字があるとystrが不定のまま処理が続いてしまう ystr=ybuf; // if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) // このif文は無意味。while文は「最初から条件が成り立ってなければ何もしない」ので、判定する意味がない while(isdigit(*str) |*str=='||*str=='.') *ystr++=*str++; *ystr='\0'; } // else 下の行が要らないのでelseも要らない // str++; 判定のついでにstrを進めたので、もう要らない } pDC->MoveTo((int)bx,(int)by); bx=atof(xbuf); //MoveToし終ったbxはもう要らないので上書きしてもよい by=atof(ybuf); //MoveToし終ったbyはもう要らないので上書きしてもよい pDC->LineTo((int)bx,(int)by); } } fclose(fp); return 0; }

zaqwe
質問者

補足

xstr=xbufの意味合いがいまいち理解できないのですが xbufに何も入ってないのに先頭にもっていくのは先頭から順にいれていくと意図でしょうか? 後xstrにxの値がはいってるのはわかりますが、xbufにまで入ってるのはどうしてでしょうか?

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

>しかしxstr=xbufの所ではわからないことがあります。 >bufでfpから読み込んだ文字列1行が入っているのはわかります。 >しかしxbufにはまだ何も入ってないはずなのに >xstr=xbufの所でxbufにはxの値がしっかり入っていました。 最初は何も入っていませんよ。 このプログラムがやっている事は ・ファイルを開く ・「現在の描画位置」を指す変数bx、byを0.0にする ・1行をbufに読み込み、ファイルが尽きるまで以下を繰り返す  ・strをbufの先頭にする  ・strを1文字づつ進めながら以下を繰り返す   ・もし「X」を見つけたら    ・xstrをxbufの先頭にする    ・strが「0~9」、「-」、「.」の間、strからxstrに1文字づつコピーする    ・コピーしたら、xstrの末尾に終端記号'\0'を足す    ⇒つまりstrの指す場所に「X123」があったら、xbufに「123」がコピーされる。strは「3」の次の位置になる   ・もし「Y」を見つけたら    ・ystrをybufの先頭にする    ・strが「0~9」、「-」、「.」の間、strからystrに1文字づつコピーする    ・コピーしたら、ystrの末尾に終端記号'\0'を足す    ⇒つまりstrの指す場所に「Y456」があったら、ybufに「456」がコピーされる。strは「6」の次の位置になる   ・「X」も「Y」も見付からないなら、strを1つ進める   ・strが「行の最後」の'\0'を見付けたら、繰り返しをやめる  ・「現在の描画位置」を(bx,by)に移動  ・xbuf、ybufの内容を数値として、そこの位置まで線を引く  ・「現在の描画位置」を指す変数bx、byをxbuf、ybufの値にする  ・fgetsでもう読めたくなったら、繰り返しをやめる ・ファイルを閉じる ・0を返り値としてリターンする と言う処理です。 xbufは「X???」が来た時だけ、更新されます。 ybufは「Y???」が来た時だけ、更新されます。 なので X100Y100 X50 Y50 と言う3行があると 1行目:xbufが「100」、ybufが「100」になる⇒(100,100)まで線を引く 2行目:xbufが「50」になり、ybufは「100」のまま⇒(50,100)まで線を引く 3行目:xbufは「50」のまま、ybufが「50」になる⇒(50,50)まで線を引く と言う事になります。 因みに、以下の部分 pDC->MoveTo((int)bx,(int)by); pDC->LineTo((int)atof(xbuf),(int)atof(ybuf)); bx=(int)atof(xbuf); by=(int)atof(ybuf); は「(int)atof(xbuf)」「(int)atof(ybuf)」が2回出て来るので pDC->MoveTo((int)bx,(int)by); bx=atof(xbuf); //MoveToし終ったbxはもう要らないので上書きしてもよい by=atof(ybuf); //MoveToし終ったbyはもう要らないので上書きしてもよい pDC->LineTo((int)bx,(int)by); と書き変えた方が良いでしょう。

関連するQ&A

  • プログラム

    { FILE *fp; char *str,buf[1000];   char subbuf[100],*s1; char buf2[100],*s2;   char buf3[100],*s3; char buf4[100],*s4; static double bx=0; static double by=0; if ((fp = fopen("test.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='G'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s2=buf2; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0'&&(isdigit(*str) || *str=='-' || *str=='.')) *s2++=*str++; *s2='\0'; } if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s3=buf3; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *s3++=*str++; *s3='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s4=buf4; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *s4++=*str++; *s4='\0'; } CDC *v; v=GetDC(); if((int)atof(buf2)==92){ MoveTo((int)atof(buf3),(int)atof(buf4)); bx=(int)atof(buf3); by=(int)atof(buf4); ReleaseDC(v); } else if((int)atof(buf2)==01){ MoveTo((int)bx,(int)by); LineTo((int)atof(buf3),(int)atof(buf4)); bx=(int)atof(buf3); by=(int)atof(buf4); ReleaseDC(v); } else str++; } } fclose(fp); return 0; } という風なプログラムになっているのですが 今現在 G01X30Y30 G01X30Y120というファイルをこのプログラムにて実行すると (0,0)→(30,30)→(30,120)というような直線が引かれます。 しかしこれを G01X30Y30 Y120 とかかれたときも同様の結果がでるようにしたいです。 つまり最初のG○○が省略されているときは前回のGの値を X○○が省略されているときは前回のXの値を使うように 変更したいのですがどのように変更すればいいのかがわかりません。 教えてください。

  • プログラム

    以前ファイルからXとYの値だけ取り出し図形を作る質問をした者ですが void Ctest::OnOK() { FILE *fp; char *str,buf[1000];     char buf3[100],*s3; char buf4[100],*s4; if ((fp = fopen("test.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s3=buf3; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *s3++=*str++; *s3='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s4=buf4; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *s4++=*str++; *s4='\0'; CDC *v; GetDC(); MoveTo(0,0); LineTo(atof(buf3),atof(buf4)); ReleaseDC(v); } else str++; } } fclose(fp); return 0; } でコンパイルはできるのですが直線の作図がされません。 どこが間違ってるのでしょうか。VC+6.0のMFC使ってます

  • 関数

    FILE *fp; char *str,buf[1000]; char xbuf[100],*xstr;   char ybuf[100],*ystr; static double bx=0; static double by=0; if ((fp = fopen("kadai.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str=='X'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') xstr=xbuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) || *str=='-' || *str=='.')*xstr++=*str++; *xstr='\0'; } if(*str=='Y'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') ystr=ybuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) |*str=='||*str=='.') *ystr++=*str++; *ystr='\0'; } else str++; } } ファイルからの一行の切り分けのプログラムなのですが if(*str=='X'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') xstr=xbuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) || *str=='-' || *str=='.')*xstr++=*str++; *xstr='\0'; } の部分と if(*str=='Y'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') ystr=ybuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) |*str=='||*str=='.') *ystr++=*str++; *ystr='\0'; } の部分は変数が違うだけでほとんど同じ文ですよね。 関数を作ってこの処理のときに呼び出せれば応用が利くと思い 考えてみたのですが中々できません。よろしければ教えて下さい。 まだ戻り値や関数の理解が今ひとつです。

  • このプログラムは

    どこかおかしいですか? int main(void){ FILE *str; char buf[1000]; if((fp=fopen("ファイル名","r"))=NULL){ printf("ファイルが開けません"); return EXIT_SUCCESS; } while(fgets(buf,1000,fp) !=NULL){ str=buf; printf("%s",buf); } return EXIT_SUCCESS; } で実行すると前半4割程度が表示されません。 何故だかわかる人いませんか? 使用言語:C言語 環境:visualC++6.0 のコンソールアプリケーション。

  • プログラムが止まってしまいます

    Visual Studio 2012 c++ でプログラムを動かそうと思っているのですが、デバッグ開始すると画像のようなウィンドウが出て実行途中で止まってしまいます。 呼び出し履歴のint mqoLoadFileのソースを貼ります. int mqoLoadFile( MQO_OBJECT *mqoobj, char *filename, double scale, unsigned char alpha) { FILE *fp; MQO_OBJDATA obj[MAX_OBJECT]; MQO_MATDATA *M = NULL; char buf[SIZE_STR]; // 文字列読み込みバッファ char path_dir[SIZE_STR]; // ディレクトリのパス char path_tex[SIZE_STR]; // テクスチャファイルのパス char path_alp[SIZE_STR]; // アルファテクスチャファイルのパス int n_mat = 0; // マテリアル数 int n_obj = 0; // オブジェクト数 int i; // MaterialとObjectの読み込み fopen_s(&fp,filename,"rb"); if (fp==NULL) return 0; mqoobj->alpha = alpha; memset(obj,0,sizeof(obj)); i = 0; while ( !feof(fp) ) { fgets(buf,SIZE_STR,fp); // Material if (strstr(buf,"Material")) { sscanf_s(buf,"Material %d", &n_mat); M = (MQO_MATDATA*) calloc( n_mat, sizeof(MQO_MATDATA) ); mqoReadMaterial(fp,M); } // Object if (strstr(buf,"Object")) { sscanf_s(buf,"Object %s", obj[i].objname);//ココの実行中に止まる mqoReadObject(fp, &obj[i]); i++; } } n_obj = i; fclose(fp);

  • ファイル

    ファイルを読み込み単語ごとに表示するプログラムです。 例 ファイル データ 形式 歴史・・ のように単語の後には空白がありますファイルです FILE *fp; char buf[1000]; char buf_word[1000]; char *str; char *bufstr; if((fp = fopen("test.txt","r")) == NULL){ printf("error!"); return 0; } while(fgets(buf,1000,fp) !=NULL){ str = buf; while(*str !='\0'){ strbuf = buf_word; if(*str ==' '){ printf("%s",buf_word); } else{ *strbuf++ = *str++; } } } とプログラムしてみましたが*strの値がどうもおかしく 最初が "フ" じゃなく"・"になってます。 最初の単語がG11とかなら"G"になっていますが・・ 教えて下さい。

  • ファイルを読み込むプログラムについて

    下のプログラムで分からない所がありますので、教えて頂ければと思います。宜しくお願い致します。 text = fgets(buf,256,fp);はfpのファイルから一行を読み込んでbufに格納するという処理ということは分かります。でも、while文内なので次にこの処理をする時に今度は、2行目(下の段)を読み込むはずですが、プログラム中のどこに2行目に移動させる処理があるのか分かりません。 予想ですが、text = fgets(buf,256,fp);の中にそのような意味の処理が含まれているのでしょうか? どなたかご教授お願い致します。 #include <stdio.h> int main(void) { FILE *fp; char buf[256]; char *text; char flname[256]; printf("ファイル名:"); gets(flname); fp = fopen(flname,"r"); do{ text = fgets(buf,256,fp); if(text != NULL){ printf("%s",text); } }while(text != NULL); fclose(fp); return(0); }

  • メモリ2(ポインタ編)

    #include "stdafx.h" #include <ctype.h> #include <string.h> #include <stdlib.h> int check(int a[100], int n); typedef struct { char *number; char *class_type; char *name; char *subject; } my; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char bufG[1111]; int i, len; my *o; if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf,1000,fp) !=NULL){ str=buf; len = strlen(buf); o = (my *) calloc(len + 1, sizeof(my *)); while(*str != '\0'){ if(*str != ','){ for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; switch(field){ case 0: o[line].number = bufG; break; case 1: o[line].class_type = bufG; break; case 2: o]line].name = bufG; break; case 3: o[line].subject = bufG; } field++; } else{ str++; } } line++; field = 0; } fclose(fp); return 0; } 固定なのがいけないといわれたのでこのように 変更しました。もちろん上手く動かないわけですが 原因を教えて下さい。 ちなみにエラーはo[0].numberが国語とかになってたり ちゃんとアクセスができません。

  • メモリ

    #include "stdafx.h" #include <ctype.h> #include <string.h> #include <stdlib.h> int check(int a[100], int n); typedef struct { char number[6]; char class_type[20]; char name[8]; char subject[5]; } my; my data[100]; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char bufG[1111]; int i; if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf,1000,fp) !=NULL){ str=buf; while(*str != '\0'){ if(*str != ','){ for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; switch(field){ case 0: strcpy(data[line].number, bufG); break; case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; } field++; } else{ str++; } } line++; field = 0; } int p, q; int a[100]; int u = 0; for(p = 0; p < line; p++){ for(q = 0; q < line; q++){ if(strcmp(data[p].class_type, data[q].class_type) == 0 && strcmp(data[p].subject, data[q].subject) == 0 && p != q ){ //処理 } } } } fclose(fp); return 0; } 先日文字列入れ替えについてご質問したものですが メモリの取り方についてご質問します。 先日このプログラムにおいて my data[100]と固定してるのはいけないという意見をもらったので メモリを取得しようと思ってるのですが できればdata[i].○○の形でアクセスしたいのでこのままの形は あまりかえたくないです。この場合 while(fgets(buf,1000,fp) !=NULL){ str=buf;     int len = strlen(buf); my *o; o = (my *)calloc( len + 1, sizeof(my *)) while(*str != '\0'){ としてみたのですがこれは実際どうなのでしょうか? NULLは帰ってきてないみたいなので割り当ては出来てるとは思うんですが この一行の文字列の大きさにぴったり合うメモリを割り当てたいのですが ちゃんとなっているか調べる方法を教えて下さい。

  • 迷路を解くプログラムについて

    迷路を脱出する経路を探索するプログラムを作成したいのですが、 何をすればいいのかまったくわかりません 以下のプログラムはあるんですが、このプログラムを改良していくということなんでしょうか?左上からスタートして右下がゴールらしいのですがやり方教えてください #include <stdlib.h> #include <stdio.h> #include "List.h" #define LEN 256 int maze[LEN][LEN]; void readMaze(char* filename, int *w, int *h, int maze[LEN][LEN]) { FILE *fp; int x, y; if (0 != fopen_s(&fp, filename, "r")) { fprintf(stderr, "指定された迷路の入力ファイルを開くことができませんでした.\n"); exit(-1); } fscanf_s(fp, "%d,%d\n", w, h); for (y = 0; y < 2 * *h + 1; y++) { for (x = 0; x < 2 * *w + 1; x++) { fscanf_s(fp, "%d%*[^-0-9]", &(maze[y][x])); } } fclose(fp); } void writeMaze(char* filename, int w, int h, int maze[LEN][LEN]) { FILE *fp; int x, y; if (0 != fopen_s(&fp, filename, "w")) { fprintf(stderr, "指定された迷路の出力ファイルを開くことができませんでした.\n"); exit(-1); } fprintf_s(fp, "%d,%d\n", w, h); for (y = 0; y < 2 * h + 1; y++) { for (x = 0; x < 2 * w + 1; x++) { fprintf_s(fp, "%d", maze[y][x]); if (x < 2 * w) { fprintf_s(fp, ","); } else { fprintf_s(fp, "\n"); } } } fclose(fp); } // シンプルなバージョン:なるべく右下へ行けるなら右下へ int main(int argc, char** argv) { int w, h; int x, y; if (argc < 3) { fprintf(stderr, "迷路の入出力ファイル名を指定してください.\n"); exit(-1); } // 迷路読込 readMaze(argv[1], &w, &h, maze); // maze[1][1] から maze[2*h-1][2*w-1] までのルートを探す x = 1; //座標の初期化 y = 1; while (x != 2 * w - 1 || y != 2 * h - 1){ if (maze[y][x + 1] == 0) { // 右にまだ行ってない? maze[y][x] = 1000; x = x + 1; } else if (maze[y + 1][x] == 0) { // 下にまだ行ってない? maze[y][x] = 1000; y = y + 1; } else if (maze[y][x - 1] == 0) { // 左にまだ行ってない? maze[y][x] = 1000; x = x - 1; } else if (maze[y - 1][x] == 0) { // 上にまだ行ってない? maze[y][x] = 1000; y = y - 1; } else if (maze[y][x + 1] == 1000) { // 行き止まりなので右に引き返す maze[y][x] = 1; x = x + 1; } else if (maze[y + 1][x] == 1000) { // 行き止まりなので下に引き返す maze[y][x] = 1; y = y + 1; } else if (maze[y][x - 1] == 1000) { // 行き止まりなので左に引き返す maze[y][x] = 1; x = x - 1; } else if (maze[y - 1][x] == 1000) { // 行き止まりなので上に引き返す maze[y][x] = 1; y = y - 1; } } maze[2 * h - 1][2 * w - 1] = 1000; // ゴール // 答えを濃い色に // 上記のプログラムはすでに答えを濃い色(1000)にしている // 迷路書出 writeMaze(argv[2], w, h, maze); return 0; }

専門家に質問してみよう