• ベストアンサー

文字列の入力

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); } です。 もし、ソース自体をもっと スマートにできるのであれば それもご教授ください。

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

  • ベストアンサー
回答No.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; }

pop-bomb
質問者

お礼

>皆さん ありがとうございました。 解決しました。

その他の回答 (4)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★アドバイス >もし、ソース自体をもっと >スマートにできるのであれば >それもご教授ください。  文字列をトークン(単語)ごとに切り出してから処理すれば分かりやすくなります。  サンプルを載せると下のようになります。 サンプル: #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)
回答No.3

ほんとすみません。間違えました。   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++;    }

pop-bomb
質問者

お礼

すいません。それで実行をしてみましたが、 解決していないようでした・・・

  • b03095
  • ベストアンサー率43% (7/16)
回答No.2

   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)
回答No.1

> I have a pen. > You have 6 brothers. この入力データから、どういった出力結果を得たいですか? 出力例を示してください。

pop-bomb
質問者

お礼

出力結果は a=3個 b=1個 <中略> a-a=0個 a-b=0個 <中略> h-a=2個 <中略> z-z=0個 のような結果を得たいのです。 ちなみに入力ファイルの文字数はもっと 膨大です。

関連するQ&A