アプリ版:「スタンプのみでお礼する」機能のリリースについて

英文中に現れる異なる単語の数を表示するプログラムがわかりません。
例えば 「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);
}

A 回答 (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);
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
無事 完成させることができました。

>if(find<0){
  strcpy(list[total].word,text);
  list[total++].counter=1;

の部分が少々わからなかったのですが、一つ一つ追っていくことで理解できました。
本当にありがとうございます。

あとよろしければ教えていただきたいのですが、
totalはtotal=0としておかないと実行時にエラーが出るのに
list[i].counterは初期化しておかなくても正常にカウントされていくのは何故でしょうか。
おかしな値が出てしまうような気がするのですが。

お礼日時:2005/07/08 23:56

>全く初期化していないプログラムでも正常にカウントされていくので


考えられる理由としては、
使っているメモリ領域がたまたま0だったというのが普通考えられる理由です。
コンパイラによっては、変数を暗黙的に0で初期化してくれるものもありますが、そういう期待はすべきではありません。
    • good
    • 0
この回答へのお礼

偶然ですか。
やはり初期化はきちんとしておかないとダメですね。
本当に何度もありがとうございました。

お礼日時:2005/07/10 11:33

#3補足>list[i].counterは初期化しておかなくても正常にカウントされていくのは何故でしょうか。


始めて見つかった単語が出てきた時に
>list[total++].counter=1;
として、1回として数えています。
つまり、ここで初期化していることになります。
    • good
    • 0
この回答へのお礼

すみません、説明不足でした。
このプログラムではなく、全く初期化していないプログラムでも正常にカウントされていくので
不思議だなと思ったのです。
何度もありがとうございます。

お礼日時:2005/07/09 15:08

この辺の構文解析きっちりやるなら、是非ともトークン関数を調べてみることをお勧めします。



strtok()でお調べ下さい。

非常に参考になる筈です。

参考URL:http://www1.cts.ne.jp/~clab/hsample/Func/Func08. …
    • good
    • 0
この回答へのお礼

ありがとうございます。
参考URLも見てみました。
もっと勉強していきたいと思います。

お礼日時:2005/07/09 15:04

while(scanf(…


で読み込むループで
input_word[MAX]に読み込んで
すでに登録されている部分に同じワードが見つからない時
 追加してカウント(=1する)
既に登録してある時
 見つかったlistをカウント
したらどうでしょうか
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
そういうタイプのもかいてみたのですが、やはりうまくいきません。

#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);
}

解決策が思い浮かびません。
どうすればいいでしょうか。

お礼日時:2005/07/08 12:34

> 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のメンバーにすでにチェックされたかどうかを示すフラグを追加するなどするとよいとおもいます。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
> list[0].counter=1;

としたのは

> for(j=1;j<=total;j++){

との兼ね合いからか、2文字目からのカウントがうまくできなかったからです(実際の文字数ー1になってしまう)
直したら出来ました、ありがとうございます。
チェックは色々試しましたがうまくできませんでした。
もう一度やってみたいと思います。

お礼日時:2005/07/08 12:22

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!