【最大10000ポイント】当たる!!質問投稿キャンペーン!

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

このQ&Aに関連する最新のQ&A

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

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

お礼日時:2008/02/24 20:08

★アドバイス


>もし、ソース自体をもっと
>スマートにできるのであれば
>それもご教授ください。
 文字列をトークン(単語)ごとに切り出してから処理すれば分かりやすくなります。
 サンプルを載せると下のようになります。

サンプル:
#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個
    • good
    • 0

ほんとすみません。

間違えました。

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

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

お礼日時:2008/02/21 23:46

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

ってしたらできませんか?動作確認なんてしてませんが。
    • good
    • 0

> I have a pen.


> You have 6 brothers.

この入力データから、どういった出力結果を得たいですか?
出力例を示してください。
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/02/21 23:46

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


人気Q&Aランキング