- ベストアンサー
文字列の入力
I have a pen. You have 6 brothers. と書かれたテキストファイルを入力し, 文字の連結を調べたいと思っています。 例えば have だったら、 h-aが1つ a-vが1つ v-eが1つ ところが、 have a となっているためか e-aも1つとしてカウントされるのです。 スペースや数字はカウントせずに処理したいんですが、 どうすればよいでしょうか? 一応、ソースは、 #include<stdio.h> #include <ctype.h> #include <stdlib.h> int main(void) { int count[26]={0}; int ren[26][26]={0}; char c,cc='a',ccc='a'; FILE *fp,*fo; int j,jj,k=0; int i[50000]={0}; if((fp=fopen("penin.txt","r"))!=NULL){ while((c=fgetc(fp))!=EOF){ putchar(c); c = tolower(c); i[k]=c-'a'; count[i[k]]++; if(k>1){ ren[i[k-1]][i[k]]++; } k++;} } if((fo = fopen("penout.tsv", "w")) == NULL){ /* 出力ファイルオープン */ printf("出力ファイルがオープンできません\n"); exit(1); /* 強制終了 */ } for(j=0;j<=25;j++){ fprintf(fo,"%c = %d個\n",cc,count[j]); cc=cc++; } cc='a'; for(j=0;j<=25;j++){ for(jj=0;jj<=25;jj++){ fprintf(fo,"%c %c = %d個\n",cc,ccc,ren[j][jj]); ccc=ccc++; } ccc='a'; cc=cc++;} fclose(fp); fclose(fo); return(0); } です。 もし、ソース自体をもっと スマートにできるのであれば それもご教授ください。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
#include <stdio.h> #include <ctype.h> int main(int argc, char *argv[]) { FILE *fp1, *fp2; int c[26] = {0}, cc[26][26] = {0}, c0, c1, i, j; if(argc != 3) return 1; if(!(fp1 = fopen(argv[1], "r"))) return 1; for(c0 = tolower(fgetc(fp1)); c0 !=EOF; c0 = c1){ c1 = tolower(fgetc(fp1)); if(isalpha(c0)){ c[c0 - 'a'] ++; if(isalpha(c1)) cc[c0 - 'a'][c1 - 'a'] ++; } } fclose(fp1); if(!(fp2 = fopen(argv[2], "w"))) return 1; for(i = 0; i < 26; i ++){ if(c[i]) fprintf(fp2, "%c %d\n", 'a' + i, c[i]); } for(i = 0; i < 26; i ++){ for(j = 0; j < 26; j ++){ if(cc[i][j]) fprintf(fp2, "%c - %c %d\n", 'a' + i, 'a' + j, cc[i][j]); } } fclose(fp2); return 0; }
その他の回答 (4)
- Oh-Orange
- ベストアンサー率63% (854/1345)
★アドバイス >もし、ソース自体をもっと >スマートにできるのであれば >それもご教授ください。 文字列をトークン(単語)ごとに切り出してから処理すれば分かりやすくなります。 サンプルを載せると下のようになります。 サンプル: #include <ctype.h> #include <stdio.h> // メイン関数 int main( void ) { char token[ 256 ]; // 1つの単語 FILE *fp = stdin; // 本当はファイル・ポインタを入れる int c, n = 0; printf( "キーボードから入力して下さい。CTRL+Cで終了\n\n" ); while ( (c = fgetc(fp)) != EOF ){ if ( isspace(c) ){ if ( n != 0 ){ token[ n ] = '\0'; printf( "%-20s :%d 個\n", token, (n - 1) ); } n = 0; } else{ token[ n++ ] = (char)c; } } // ここも記述しておく(上と同じなので関数にすべき) if ( n != 0 ){ token[ n ] = '\0'; printf( "%-20s :%d 個\n", token, (n - 1) ); } return 0; } 上記の token を調べれば h-a、a-v、v-e、e-\0となって最後のe-\0は連結なしとして カウントしなければ良い。表示する printf() 部分に次のカウンタ加算を記述。 int i, count[ 26 ] = { 0 }; ←宣言部に追加。 for ( i = 0 ; i < n ; i++ ){ if ( token[i + 1] != '\0' ){ ←最後以外を処理 c = tolower( token[i] ); count[ c - 'a' ] += 1; ←加算 } } とすれば h=1、a=1、v=1、e=0 と加算されていきます。 カウンタ部分と結果表示部分を作れば下のようになります。 結果: a = 2個 b = 1個 c = 0個 d = 0個 : z = 0個
- b03095
- ベストアンサー率43% (7/16)
ほんとすみません。間違えました。 c = tolower(c); i[k]=c-'a'; count[i[k]]++; /*-----------------変更箇所-------------*/ if(k>1){ ren[back][i[k]]++; if((i[k] != ' ') && (!isdigit(i[k])){ back=i[k]; } }else if(k==1){ back=i[k]; } /*-----back は char型で宣言しておく-----*/ k++; }
お礼
すいません。それで実行をしてみましたが、 解決していないようでした・・・
- b03095
- ベストアンサー率43% (7/16)
c = tolower(c); i[k]=c-'a'; count[i[k]]++; /*-----------------変更箇所-------------*/ if(k>1){ ren[back][i[k]]++; back=i[k-1]; }else if(k==1){ back=i[k]; } /*-----back は char型で宣言しておく-----*/ k++; } ってしたらできませんか?動作確認なんてしてませんが。
- asuncion
- ベストアンサー率33% (2127/6289)
> I have a pen. > You have 6 brothers. この入力データから、どういった出力結果を得たいですか? 出力例を示してください。
お礼
出力結果は a=3個 b=1個 <中略> a-a=0個 a-b=0個 <中略> h-a=2個 <中略> z-z=0個 のような結果を得たいのです。 ちなみに入力ファイルの文字数はもっと 膨大です。
お礼
>皆さん ありがとうございました。 解決しました。