• ベストアンサー

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

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

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

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

minato1985
質問者

お礼

回答ありがとうございます。 無事 完成させることができました。 >if(find<0){   strcpy(list[total].word,text);   list[total++].counter=1; の部分が少々わからなかったのですが、一つ一つ追っていくことで理解できました。 本当にありがとうございます。 あとよろしければ教えていただきたいのですが、 totalはtotal=0としておかないと実行時にエラーが出るのに list[i].counterは初期化しておかなくても正常にカウントされていくのは何故でしょうか。 おかしな値が出てしまうような気がするのですが。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (5)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.6

>全く初期化していないプログラムでも正常にカウントされていくので 考えられる理由としては、 使っているメモリ領域がたまたま0だったというのが普通考えられる理由です。 コンパイラによっては、変数を暗黙的に0で初期化してくれるものもありますが、そういう期待はすべきではありません。

minato1985
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.5

#3補足>list[i].counterは初期化しておかなくても正常にカウントされていくのは何故でしょうか。 始めて見つかった単語が出てきた時に >list[total++].counter=1; として、1回として数えています。 つまり、ここで初期化していることになります。

minato1985
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。
  • t_nojiri
  • ベストアンサー率28% (595/2071)
回答No.4

この辺の構文解析きっちりやるなら、是非ともトークン関数を調べてみることをお勧めします。 strtok()でお調べ下さい。 非常に参考になる筈です。

参考URL:
http://www1.cts.ne.jp/~clab/hsample/Func/Func08.html
minato1985
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

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

minato1985
質問者

お礼

回答ありがとうございます。 そういうタイプのもかいてみたのですが、やはりうまくいきません。 #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)
回答No.1

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

minato1985
質問者

お礼

回答ありがとうございます。 > list[0].counter=1; としたのは > for(j=1;j<=total;j++){ との兼ね合いからか、2文字目からのカウントがうまくできなかったからです(実際の文字数ー1になってしまう) 直したら出来ました、ありがとうございます。 チェックは色々試しましたがうまくできませんでした。 もう一度やってみたいと思います。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • C言語のファイル操作についての質問です

    #include <stdio.h> #include<process.h> int main(void) { FILE *fp; int a[200], i, j, cnt, max, max_i; fp = fopen("data.txt", "r"); if (fp == NULL) { printf("file cannot open.\n"); exit(1); } for(i = 0; i < 200 && fscanf(fp, "%d", &a[i]) == 1; ++ i) ; fclose(fp); for(max = max_i = j = 0; j < i; ++ j){ int k; for(cnt = 0, k = j + 1; k < i; ++ k) cnt += (a[j] == a[k]); if(cnt > max) max = cnt; max_i = j; } printf("%d\n", a[max_i]); return 0; } これは「data.txt」というファイルから最頻値を探し出し、その値を表示するプログラムです。 しかし、このプログラムだと最頻値が1つしか表示できないので、 最頻値が複数ある場合でも、すべての最頻値の値を表示させるようなプログラムに書き換えてほしいです。 よろしくお願いします。 例)data.txt 30000 100 150 30000 30000 100 4320 100 出力↓ 30000 100

  • C言語 プログラム問題

     すいません、C言語初心者です。以下のプログラムがわからないので、よければ教えてください。 #include<stdio.h> int f(int a); int g(int *a); main(){ int i, j, na =10; int a[12] = {1,2,3,4,5,6,7,8,9,10,11,12}; printf("a = "); for (i=0; i<na; i++); printf("%d ",a[i]); j = f(a[2]); j = f(a[3]); j = g(a+4); j = g(a+5); printf("\na = "); for (i=0;i<na;i++) printf("%d ",a[i]); printf("\nj = %d\n",j); } int f(int a) { static int total=0; total = total + a; a = a+50r; return total; } int g(int *a) { static int total=0; total = total+(*a); (*a) = (*a) +50; return total; } <結果> a = 1 2 3 4 5 6 7 8 9 10 a = 1 2 3 4 55 66 7 8 9 10 j = 11    まず、結果がなぜ下の段に55 56があるのか、そして関数f,gの機能、最後にj=11の意味です。j=5+6 =11とは聞きましたがどこから出ているのかがわかりません。  よろしくお願いします。

  • C言語のプログラムでおかしな動作をするのですが教えて頂けないでしょうか?

    VisualStudio2008使用しています。 問題は、サイコロを200回振ってその出た目の数の個数分*を表示するプログラムです。 サイコロの目はランダムで出しています。 次のプログラムは正常に動作するものです。 /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; int y[7]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } */ 次のプログラムが問題で、授業で先生が配列にはstaticをおまじないとしてつけないと暴走すると言われたので、つけて見ると明らかに間違ってると思われるプログラムで動作するのですが原因を教えて頂けないでしょうか? 以下問題のプログラム! 配列の前にstaticをつけたら、添え字をいくつにしても正常に動作します。普通は添え自分しか領域って確保されないですよね??? /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; //以下が問題の配列宣言 static int y[2]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } 質問の意味が正確に伝わらなかった場合は補足しますので、ご回答よろしくお願いします。

  • C言語の問題について

    下のプログラムにおいて実行結果は 02134 になります。 この02134になる過程は分かるのですが、時間がかかってしまいます。 iListとiGeneをいちいち紙に書き出さなければならないのでしょうか? 法則的なものが存在するとすれば、教えてください。 #include<stdio.h> #define MAX 5 void func(int *iGene); int main(void) { int i; int iGene[MAX]={0,1,0,0,0}; func(iGene); for(i=0;i<MAX;i++) { printf("%d",iGene[i]); } return (0); } void func(int *iGene) { int i,j; int iBuff; int iList[MAX]; for(i=0;i<MAX;i++) { iList[i]=i; } for(i=0;i<MAX;i++) { iBuff=iList[iGene[i]]; for(j=iGene[i]+1;j<MAX-i;j++) { iList[j-1]=iList[j]; } iGene[i]=iBuff; } } よろしくお願いします。

  • C言語でこのプログラムを完成させるには

    C言語でこのプログラムを完成させるには C言語初心者です。 1~6の乱数を100回発生させて、それぞれの出現回数をカウントし、ヒストグラムとして表示するプログラムを作成したいのですが上手くいきません。 #include <stdio.h> #include <time.h> #include <stdlib.h> int rnd(int m, int n) { return (int)(n-m+1)*(rand()/(RAND_MAX+0.1))+m; } int main(void) { int i, j, r; int hist[7]; for (i=1; i<7; i++) hist[i]=0; srand((unsigned)time(NULL)); for (i=0; i<100; i++) { r=6; while (6-- > 0) putchar('*'); putchar('\n'); } for (i=1; i<7; i++) { printf("%2d:", i); for (j=0; j<hist[i]; j++) printf("*"); printf("\n"); } return 0; } 何がいけないのでしょうか? よろしくお願いします。

  • C言語 ファイルポインタ

    度々同じプログラムで質問させてもらっています。 #include <stdio.h> #include <time.h> #include <math.h> #define N 10 void filewrite(int i,int a[]); void main(void){ int min,s,t,i,j,k,a[N]; srand((unsigned int)time(NULL)); for(i=0;i<N;i++) a[i]=rand()%10+1; for(j=0;j<i-1;j++){ min=a[j]; s=j; for(k=j+1;k<i;k++){ if(a[k]<min){ min=a[k]; s=k; } } t=a[j];a[j]=a[s];a[s]=t; filewrite(i,a); } } void filewrite(int i,int a[]){ int s; FILE *fp; fp = fopen("selection.txt","w"); if(fp == NULL)return; for(s=0;s<i;s++){ fprintf(fp,"%d,",a[s]); } fprintf(fp,"\n"); fclose(fp); } 途中経過もテキストファイルで出力したいのですが、このプログラムを実行すると最後の結果しか出力されません。 アドバイスをよろしくお願いします。

  • プログラムについて(C言語)

    #include<stdio.h> int main() { int i,n,total; for(;;){ /* 無限ループ*/ printf("整数n?"); /* nの値の表示 */ scanf("%d",&n); /* ifとbreakを使った終了判定 */ if(n<0)break; total=1; for(i=1;i<=n;i++){ printf("i=%d ",i); total*=i; /* total←total*i(階乗の計算) */ } printf("total=%d\n",total); /* totalの値(結果)の表示 */ } printf("Thanks\n"); /* 終了メッセージの表示 */ return(0); } これは階乗を求めるプログラムなのですが、i++ではなくi--をつかって求める場合 どのように変更すればよいでしょうか? for(i=1;i<=n;i++){ あたりをいろいろ弄ってみたのですが、求めてる結果は得られませんでした

  • C言語のプログラム

    以下のプログラムはハッシュテーブルを用いて文字列を探すプログラムなのですが、コンパイル時にセグメントエラーとなってしまいます。プログラム中に誤った箇所があれば教えて頂きたいです。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 10 #define MAX_LEN 64 #define N_WORDS 4 struct list { char word [MAX_LEN]; struct list *next; }; struct list *hash_table[HASHSIZE]; char colors[N_WORDS][MAX_LEN] = {"red", "blue", "green", "yellow"}; void my_strcpy(char* a, const char* b) { int i = 0; while(*b != '\0'){ *(a+i) = *(b+i); i++; } *(a+i) = '\0'; } int hash(char *key) { int hashval = 0; while (*key != '\0') { hashval += *key; key++; } return (hashval % HASHSIZE); } int find_word (char *key) { struct list *p; for (p = hash_table[hash(key)]; p != NULL; p++) if (strcmp(key, p->word) == 0) return 1; return 0; } void init_hash_table() { int i, hashvalue; struct list *p, *q; for (i = 0; i < HASHSIZE; i++) { hash_table[i] = NULL; } for (i = 0; i < N_WORDS; i++) { if ((find_word(colors[i])) == 0){ p = (struct list *)malloc(sizeof(struct list)); my_strcpy(p->word, colors[i]); hashvalue = hash(colors[i]); if (hash_table[hashvalue] = NULL) { hash_table[hashvalue] = p; p->next=NULL; } else { q = hash_table[hashvalue]; while (q->next != NULL) q = q->next; q->next = p; p->next=NULL; } } } } void main(void) { init_hash_table(); printf("result = %d\n", find_word("red")); }

  • 単語数のカウントについて

    C言語のプログラミングについて質問させていただきます。 『一行の入力に対し,入力された英文の文字数,単語数,文字の使用頻度を数える』という問題なんですが、一応プログラムを組むことはできました。 しかし、今のプログラムのままでは単語間にを連続して入力しても単語数が増加してしまいます。 そこで、単語間の空白が2文字以上でも安定して単語数を正しく数えることができるようにするためにはどのように変更すればいいのか教えてください。 よろしくお願いします。 #include <stdio.h> int main(void){ char line[100]; /* キーボード入力用汎用変数 */ int i; /* 繰り返し用カウンタ */ char temporary; /* テンポラリ */ int moji_acount[128]; /* 文字カウンタ */ int moji_count = 0; /* 文字数 */ int tango_count = 0; /* 単語数 */ /* 文字カウンタの初期化 */ for(i=32;i<128;i++){ moji_acount[i] = 0; } /* 文字列の入力 */ printf("文字列:"); fgets(line, sizeof(line), stdin); /* 繰り返し用カウンタの初期化 */ i = 0; /* 文字数を数える作業 */ while(line[i] != '\n'&& line[i] != '\0'){ moji_count++; i++; } /* 文字数の表示 */ printf("文字数:%d\n", moji_count); /* 文字をテンポラリに保存 + 文字カウンタを数える作業 */ for(i=0;i<moji_count;i++){ temporary = line[i]; moji_acount[(int)temporary]++; } /* 入力された文字と回数を表示 */ for(i=32;i<128;i++){ if(moji_acount[i] != 0){ /* 文字カウンタがゼロでないときに繰り返し */ printf("'%c': %2d個\n", (char)i, moji_acount[i]); } } /* 繰り返し用カウンタの初期化 */ i = 0; /* 単語数を数える作業 */ while(line[i] != '\n' && line[i] != '\0'){ if(line[i] == ' '){ /* もしline[i]がスペースのとき */ tango_count++; } i++; } printf("単語数:%d個\n", tango_count + 1); return 0; }

  • C言語 素数判定

    1000以下の素数を求めるプログラム kadai7-2.c を作成せよ。各素数を整数4桁で出力し、15個の素数を出力した時点で改行処理 を行うこと。作成したプログラムを提出せよ。 という問題なのですが、以下のプログラムを実行しても動きませんでした。どこが違うのでしょうか。ご指摘お願いします。 #include<stdio.h> #include<math.h> main(){ int i,j,ix,k,h; for (i=2;i<=1000;i++){ ix=(int)(sqrt((double)i)); k=0; for(j=2;j<=ix;j++){ if(i%j==0){ k=1; } } if(k==0){ printf("%4d",i); h+=1 if(h=15){ printf("\n"); h=0; } }