- ベストアンサー
C言語:単語カウント
英文中に現れる異なる単語の数を表示するプログラムがわかりません。 例えば 「the a the」と入力されたら the=2 a=1 と表示されるプログラムです。 なんとかカウントはされるのですが出力がうまくいきません。同じ単語も表示されてしまいます。 どなたかご教授お願いします。 WindowsXP、コンパイラはBCCを使っています。 #include <stdio.h> #include <string.h> #define MAX 256 int main() { struct { char word[MAX]; int counter; }list[50]; int i,j,total=0; i=0; while(scanf("%s",list[i].word)!=EOF){ /*キーボードから文字列をすべて読み込む*/ total++; i++; } list[0].counter=1; for(i=0;i<=total;i++,list[i].counter=0){ /*比較*/ for(j=1;j<=total;j++){ if(strcmp(list[i].word,list[j].word)==0){ list[i].counter++; } } } for(i=0;i<=total;i++){ printf("%s %d\n",list[i].word,list[i].counter); /*出力 the=2 a=1 the=1となってしまう*/ } return(0); }
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
#2補足を手直ししてみました。 ------------------------------ #include <stdio.h> #include <string.h> #define MAX 256 int main(){ struct { char word[MAX]; int counter; }list[50]; int i,j,total,find; char text[MAX]; total=0; while(scanf("%s",text)!=EOF){ find=-1; for(i=0;i<total;i++){ if(strcmp(list[i].word,text)==0){ find=i; } } if(find<0){ /* 見つからない */ strcpy(list[total].word,text); list[total++].counter=1; } else { list[find].counter++; } } for(i=0;i<total;i++){ printf("%s %d\n",list[i].word,list[i].counter); } return(0); }
その他の回答 (5)
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
>全く初期化していないプログラムでも正常にカウントされていくので 考えられる理由としては、 使っているメモリ領域がたまたま0だったというのが普通考えられる理由です。 コンパイラによっては、変数を暗黙的に0で初期化してくれるものもありますが、そういう期待はすべきではありません。
お礼
偶然ですか。 やはり初期化はきちんとしておかないとダメですね。 本当に何度もありがとうございました。
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
#3補足>list[i].counterは初期化しておかなくても正常にカウントされていくのは何故でしょうか。 始めて見つかった単語が出てきた時に >list[total++].counter=1; として、1回として数えています。 つまり、ここで初期化していることになります。
お礼
すみません、説明不足でした。 このプログラムではなく、全く初期化していないプログラムでも正常にカウントされていくので 不思議だなと思ったのです。 何度もありがとうございます。
- t_nojiri
- ベストアンサー率28% (595/2071)
この辺の構文解析きっちりやるなら、是非ともトークン関数を調べてみることをお勧めします。 strtok()でお調べ下さい。 非常に参考になる筈です。
お礼
ありがとうございます。 参考URLも見てみました。 もっと勉強していきたいと思います。
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
while(scanf(… で読み込むループで input_word[MAX]に読み込んで すでに登録されている部分に同じワードが見つからない時 追加してカウント(=1する) 既に登録してある時 見つかったlistをカウント したらどうでしょうか
お礼
回答ありがとうございます。 そういうタイプのもかいてみたのですが、やはりうまくいきません。 #include <stdio.h> #include <string.h> #define MAX 256 int main() { struct { char word[MAX]; int counter; }list[50]; int i,j,total=1; char text[MAX]; scanf("%s",list[0].word); list[0].counter++; while(scanf("%s",text)!=EOF){ for(i=0;i<=total;i++){ /*ここの繰り返し条件がおかしいと思うのですが よくわかりません*/ if(strcmp(list[i].word,text)==0){ list[i].counter++; } else{ strcpy(list[i+1].word,text); /*i+1も おそらくおかしいです*/ list[i+1].counter++; } } total++; } for(i=0;i<=total;i++){ printf("%s %d\n",list[i].word,list[i].counter); } return(0); } 解決策が思い浮かびません。 どうすればいいでしょうか。
- buihyaku
- ベストアンサー率29% (97/326)
> list[0].counter=1; ここで1で初期化しているから、最初のthe=2になっています。初期化するなら0で初期化しましょう。 > for(j=1;j<=total;j++){ jのスタートがなぜに1で固定なのでしょうか? 同じ比較を何回もしないようにするのであればここはiからスタートすべきです。 for( j = i ; <= total; j++ ) { まとめると比較部分はこんな感じ -------------------------- list[0].counter=0; /*<<<0で初期化*/ for(i=0; i <= total ; i++, list[i].counter=0 ){ /*比較*/ for(j=i ; j <= total ; j++){ /*<<< iから*/ if( strcmp( list[i].word, list[j].word ) == 0){ list[i].counter++; } } } ----------------------------------- しかしこのアルゴリズムではどうしても同じ単語の重複はでてきます。(3つめのtheのところに1が立つ) それを回避するにはlistのメンバーにすでにチェックされたかどうかを示すフラグを追加するなどするとよいとおもいます。
お礼
回答ありがとうございます。 > list[0].counter=1; としたのは > for(j=1;j<=total;j++){ との兼ね合いからか、2文字目からのカウントがうまくできなかったからです(実際の文字数ー1になってしまう) 直したら出来ました、ありがとうございます。 チェックは色々試しましたがうまくできませんでした。 もう一度やってみたいと思います。
お礼
回答ありがとうございます。 無事 完成させることができました。 >if(find<0){ strcpy(list[total].word,text); list[total++].counter=1; の部分が少々わからなかったのですが、一つ一つ追っていくことで理解できました。 本当にありがとうございます。 あとよろしければ教えていただきたいのですが、 totalはtotal=0としておかないと実行時にエラーが出るのに list[i].counterは初期化しておかなくても正常にカウントされていくのは何故でしょうか。 おかしな値が出てしまうような気がするのですが。