- ベストアンサー
変な動作をしてしまう
月名の日本語を入力して英語にするプログラムなのですが、最後の 「間違えた月:」の結果がしっかり表示されません。 結果のどうこうに問わず、必ず「間違えた月:1月,1月,1月,1月, 1月,1月,4月,5月,」と表示されてしまうのです。 ちなみに、その上の「正解した月」はちゃんと思惑通りに 動作します。 このプログラムのどこがおかしいためにそのように表示されて しまうのでしょうか? よろしくお願いします。 #include<stdio.h> #include<time.h> #include<stdlib.h> #include<ctype.h> #include<string.h> #define swap(type,x,y) do{type t=x;x=y;y=t;}while(0) char *tukistr[]={"january","feburary","march","april","may","june","july", "augst","september","october","november","december"}; int main(void) { int nstr[12]={0,1,2,3,4,5,6,7,8,9,10,11}; char tuki[10]; int num; int seikai=0; int k=0; int seiho[12]; int huseiho[12]; int m=0; int i,j,p; char hen; srand(time(NULL)); printf("月名の英語を入力してください。入力は大文字でも小文字でも構いません。\n"); for(i=11;i>0;i--) { j=rand()%i; swap(int,nstr[j],nstr[i]); } for(i=0;i<12;i++) { printf("%d月 : ",nstr[i]+1); scanf("%s",tuki); do{ for(j=0;j<strlen(tukistr[nstr[i]]);j++) { hen=tolower(tuki[j]); if(hen!=tukistr[nstr[i]][j]) { printf("違います。正解を見ますか? 0-いいえ/1-はい:"); huseiho[m++]=nstr[i]; scanf("%d",&num); if(num==0) { printf("もう一度入力してください。:"); p=1; scanf("%s",tuki); j=0; } break; } } }while(num==0 && j<strlen(tukistr[nstr[i]])); if(j==strlen(tukistr[nstr[i]])) { printf("正解です。\n"); if(p!=1) { seikai++; seiho[k++]=nstr[i]; } p=0; } else if(num==1) { printf("%d月は%sです。\n",nstr[i]+1,tukistr[nstr[i]]); } } printf("12個のうち%d個が正解でした。\n",seikai); printf("正解した月:"); for(j=0;j<12;j++) { for(i=0;i<12;i++) { if(j==seiho[i]) { printf("%d月",j+1); if(j!=11) { printf(","); } } } } printf("\n\n"); printf("間違えた月:"); for(j=0;j<12;j++) { for(i=0;i<12;i++) { if(j==huseiho[i]) { printf("%d月",j+1); if(j!=11) { printf(","); } } } } return 0; }
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
任意月について求めようとしているのが外側の for(j....)ループであり、それに基づいて対応する入力誤りのデータを照合するために内側の for(i....)ループが1~12月まで実行されるようにプログラムされています。 「間違えた月:1月,1月,1月,1月,1月,1月,4月,5月,」の1月表示は、「printf("%d月",j+1);」によって出力されるのですから、外の月毎ループ「y==0」 と「int huseihou[12]」jが初期化されなかったことによって発生するメモリの内容がゼロ6つということです。また4月,5月は3,4いうことです。 そこで、nstr[]の月をゼロ月からではなく1月からに変更し、きちんと初期化するようにし、各添字やループも訂正してみました。 #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <time.h> #include <string.h> #define MANTH 12 #define swap(t,x,y) {t=x;x=y;y=t;} char *tukistr[]={"january","feburary","march","april","may","june","july", "augst","september","october","november","december"}; int main(void) { int nstr[MANTH]={1,2,3,4,5,6,7,8,9,10,11,12}; char tuki[10]; int num; int seikai; int seiho[MANTH]; int huseiho[MANTH]; int m; int i,j,p,len_tukistr; char hen,*temp; /* 初期値設定 */ srand(time(NULL)); for(i=MANTH-1;i>0;i--) { j=rand()%i; swap(p,nstr[j],nstr[i]); } seikai=m=p=0; for(i=0;i<MANTH;i++) seiho[i]=huseiho[i]=0; /* 入力と判定分類のメインプログラム部 */ printf("月名の英語を入力してください。入力は大文字でも小文字でも構いません。\n"); for(i=0;i<MANTH;i++) { /* 入力 */ printf("%d月 : ",nstr[i]); scanf("%s",tuki); /* 判定と分類 */ do { /* 追加:プログラムを見易くするため */ temp=tukistr[nstr[i] - 1]; len_tukistr = strlen(temp); for(j=0;j<len_tukistr;j++) { hen=tolower(tuki[j]); if(hen!=temp[j]) { huseiho[m++]=nstr[i]; printf("違います。正解を見ますか? 0-いいえ/1-はい:"); scanf("%d",&num); if(num==0) { printf("もう一度入力してください。:"); scanf("%s",tuki); p=1; } break; }} }while(num==0 && j<len_tukistr); if(j==len_tukistr) { printf("正解です。\n"); if(p!=1) seiho[seikai++]=nstr[i]; p=0; } else if(num==1) printf("%d月は%sです。\n",nstr[i],temp); } /* 結果の出力 */ printf("12個のうち%d個が正解でした。\n",seikai); printf("正解した月:"); for(j=1;j<=MANTH;j++) { for(i=0;i<MANTH;i++) { if(j==seiho[i]) { printf("%d月",j); if(j!=MANTH) printf(","); }}} printf("\n\n"); printf("間違えた月:"); for (j=1;j<=MANTH;j++) { for(i=0;i<MANTH;i++) { if(j==huseiho[i]) { printf("%d月",j); if (j!=MANTH) printf(","); }}} printf("\n\n"); return 0; }
その他の回答 (6)
- cyacya2000
- ベストアンサー率54% (39/71)
>たまたまというのは具体的にどういうことなのでしょうか。 つまり,seihoにもhuseihoにも初期値に0が入っているということ なのでしょうか。 ですが、このプログラムはseihoの方はちゃんと動作しているので なぜhuseihoの動作だけおかしいのかが知りたいです。 seiho、huseihoに初期値を設定していないため、seihoにはたまたま0以外が入っていて上手くいっている。huseihoにはたまたま0が入っていて上手くいかないということです。初期値を設定しないとメモリ中に残っている(直前に使用した)値を参照します。 前回 int seiho[12]; int huseiho[12]; を int seiho[12]={0}; int huseiho[12]={0}; とすれば、正解結果も正しく出力されなくなります。 とアドバイスしたと思うのですが、試してみましたか? 解らなければ、とりあえず試してみてください。 再度申し上げますが、 初期値に-1などを設定しておけば一応動くと思いますが(未確認です)、それは正しい修正とは思いません。 2重ループについて >これは、正解した月と間違っている月を順番に表示 させるためのものです。 よって、必要なものです。 この2重ループが正解した月と間違った月を順番に表示させていないのです。2重ループにする必要は無いのです。 プログラムの最後(returnの直前)に以下のコードを追加してみましょう。どうすればよいかヒントになると思います。 for(i=0;i<12;i++){ printf("\n%d",seiho[i]); } for(i=0;i<12;i++){ printf("\n%d",huseiho[i]); }
- cyacya2000
- ベストアンサー率54% (39/71)
#2さんの言うとおり2重ループにする必要がありません。 このプログラムが正解結果を正しく出力し、不正解結果を正しく出力しないのはたまたまです。 int seiho[12]; int huseiho[12]; を int seiho[12]={0}; int huseiho[12]={0}; とすれば、正解結果も正しく出力されなくなります。 つまり、初期値が設定されていないところにたまたま0が入ると、0=1月となり、1月が正解にも不正解にもなるのです。 seihoには正解した月が、kには正回数が入っているのですからあとは簡単にできるはずです(不正解も同様)。 そのほかの修正方法として、初期値に-1などを設定しておけば一応動くと思いますが(未確認です)、それは正しい修正とは思いません。
- d_g
- ベストアンサー率39% (48/121)
質問者ご自身ではどこまで調査されたのでしょうか? ソースが分かっていて実行できる環境もあるようですが、 デバッグ用に出力の追加等を行い、頭で考えた物と実際の動作でどこが異なっているか調査する事はできない状況にあるのでしょうか? 調査可能であるならば、バグ取りはプログラミングにおいて避けては通れない道なので、プログラマの1人として自分で調査修正してほしいと思いました。 間違えた月の出力内容がおかしいということは、出力処理自体か出力処理で使用している配列の中身が最も疑わしい事は見当が付くかと思います。 プログラムの詳細は解析していませんが(というかコメントが無く変数名で内容が想像しにくいので読みにくくて心が折れました) 以下を行えばおそらく自分で原因箇所を特定できるのではないかと考えます。 ・配列huseihoの中身を全部出力してみる。 ・間違えた月の出力ループにおいて、どのルートを通ったか、その時の値は何だったかが分かるよう出力してみる。 ・配列huseihoに値を代入している直後で一旦配列の中身を出力してみる。 ・間違えた月の出力内容を以下パターンにおいてそれぞれどうなるか確認する。 A)全問正解 B)全問不正解 C)1問不正解 D)半数が不正解
お礼
ご指摘ありがとうございました。 プログラムを書くときは今後読んでいただく人のことを 考えてコメントをつけようと思います。 また、配列huseihoの中身がおかしいためにそのようなことが 起こっているとは思っていたのですが他の部分も関係しているのでは ないかと思ってこのように書いてしまった次第です。 次回以降は気をつけたいと思います。
- asuncion
- ベストアンサー率33% (2127/6290)
ついでに、 2月と8月のつづりが誤っています。
お礼
回答ありがとうございます。 お恥ずかしい限りです…
- asuncion
- ベストアンサー率33% (2127/6290)
問題の趣旨とソースとが食い違っているのはさておくとして、 正解・不正解を出力するところで2重のループを使う理由がわかりません。 正解数はkに、不正解数はmに、それぞれ入っているのですから、 その回数だけ1重ループを回せばよいのではないでしょうか。
お礼
回答ありがとうございました。 これは、正解した月と間違っている月を順番に表示 させるためのものです。 よって、必要なものです。
- koko_u_u
- ベストアンサー率18% (216/1139)
>月名の日本語を入力して英語にするプログラムなのですが そんなプログラムには見えんのですけど、もっと問題を明確にする必要があると考えます。
お礼
ご指摘いただいてありがとうございました。 そうですね(恥) 日本語の月名が表示されて英語を入力するプログラム ですね。ちゃんと投稿する前によく見直せばよかったと思いました。
お礼
回答ありがとうございます。 >プログラムが正解結果を正しく出力し、不正解結果を正しく出力 しないのはたまたまです。 たまたまというのは具体的にどういうことなのでしょうか。 つまり,seihoにもhuseihoにも初期値に0が入っているということ なのでしょうか。 ですが、このプログラムはseihoの方はちゃんと動作しているので なぜhuseihoの動作だけおかしいのかが知りたいです。