プロが教える店舗&オフィスのセキュリティ対策術

英文テキストファイルを読み込み、分割した単語の頻出頻度を表示するプログラムを作成しています。

現時点では、分割した単語の表示しかできていません。
どなたか良きアドバイスをお願いします。

#include <stdio.h>

int main()
{
int i,key,len,num ;
int sp=0;

char str[100000],*ptr[100000] ;

FILE *fp;
if ((fp=fopen("test.txt","r"))==NULL) {
return -1;
}

num = 0 ;
len = 0 ;
ptr[0] = str ;
do {
key = fgetc(fp);
str[len] = (char)key ;


if ( (key==' ' && sp==0) || key == '.' || key == ',' || key == '!' || key == '?' || key == '"' || key == 0x0a || key == 0x0d ){

str[len] = '\0' ;


if ( str+len-ptr[num] ){
num ++ ;
}
ptr[num] = str+len+1 ;


if( key==',' || key=='.' || key== '!' || key=='?' || key=='"'){
str[++len]=(char)key;
str[++len]='\0';
ptr[++num]=&str[len+1];
}
}

sp= (key== ' ')?1:0;
len ++ ;
} while ( key != EOF && len < 255 );

str[255] = '\0' ;
for (i=0 ;i<num ;i++){
printf("%s\n",ptr[i]);
}

fclose(fp);

return i;
}

A 回答 (2件)

まず頻度用の表を作っておき、分割した単語を登録するときに、登録済みの単語と比較して同じものがあれば該当の頻度を+1、なければ単語を登録して該当の頻度を1にセットすればいいように思います。



参考まで。(単語切り出しの仕様がいまいち分かってません)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define WORD_MAX 1000 /* 単語帳の登録数 */
#define WORD_SIZE 100 /* 単語の最大長 */
char *word[WORD_MAX]; /* 単語帳 */
int freq[WORD_MAX]; /* 頻度表 */
int wordp=0; /* 単語帳の最後 */
/******************************************/
/* 単語登録(すでに登録済みなら頻度+1) */
/******************************************/
void add_word(char *s) {
 int i;
 if (strlen(s)==0) return; /* 長さ0は登録しない */
 for (i=0; i<wordp; i++) { /* 登録済みかどうか調べる */
  if (strcmp(word[i],s)==0) {
   freq[i]++;
   break;
  }
 }
 if (i==wordp) { /* 登録されてなければ追加する */
  if ((word[wordp]=malloc(strlen(s)))==NULL) exit(1);
  strcpy(word[wordp],s);
  freq[wordp]=1;
  if (wordp<WORD_MAX-1) wordp++;
 }
}
/******************************/
/* ファイルから単語を切り出す */
/******************************/
void split_word(FILE *fp) {
 char buf[WORD_SIZE];
 int bufp=0;
 int key;
 int sp=0; /* 空白チェック用フラグ */
 while((key=fgetc(fp))!=EOF) {
  if (key==' ' && sp==0) { /* 空白の1個目は単語区切り文字とする */
   buf[bufp]='\0'; bufp=0; add_word(buf); sp=1;
  } else {
   if( key=='.' || key== '!' || key=='?' || key=='"'){ /* 特定の区切り文字は単語登録する */
    if (sp==1) { /* 空白に続く場合は空白含めて登録する */
     buf[bufp]=key; if (bufp<WORD_SIZE-1) bufp++;
     buf[bufp]='\0'; bufp=0; add_word(buf); sp=0;
    } else {
     buf[bufp]='\0'; bufp=0; add_word(buf);
     buf[0]=key; buf[1]='\0'; add_word(buf);
    }
   } else {
    if (key == ',' || key == 0x0a || key == 0x0d ){ /* 普通の区切り文字 */
     buf[bufp]='\0'; bufp=0; add_word(buf); sp=0;
    } else { /* 区切り文字ではない文字(空白の2個目以降は区切り文字としない) */
     buf[bufp]=key; if (bufp<WORD_SIZE-1) bufp++;
     if (key != ' ') sp=0;
    }
   }
  }
 }
 if (bufp>0) { /* 単語直後にEOFがきた場合 */
  buf[bufp]='\0'; add_word(buf);
 }
}
/******************/
/* 単語を表示する */
/******************/
void print_word(void) {
 int i;
 for (i=0; i<wordp; i++) {
  printf("%d [%s] %d\n",i,word[i],freq[i]);
 }
}
/************************************/
/* 単語用に確保したメモリを解放する */
/************************************/
void free_word(void) {
 int i;
 for (i=0; i<wordp; i++) {
  free(word[i]);
 }
}
/**********/
/* メイン */
/**********/
int main(int argc, char **argv) {
 FILE *fp;
 if (argc!=2) return -1; /* コマンドラインでファイル名指定 */
 if ((fp=fopen(argv[1],"r"))==NULL) return -1; /* ファイル開けない */
 split_word(fp); fclose(fp); /* 単語切り出し */
 print_word(); /* 単語表示 */
 free_word(); /* メモリ解放 */
 return 0;
}

この回答への補足

具体例を出していただき有難うございます。
プログラムを実行したところ23行目
if ((word[wordp]=malloc(strlen(s)))==NULL) exit(1);がエラーだったので

if ((word[wordp]=(char*)malloc(strlen(s)))==NULL) exit(1);としたところ、エラーは0になりましたが実行すると
"Press any key to continue"と表示され、ファイルを読み込むことができません。

自分なりに試行錯誤してみましたがどうも上手くいきません。何か特別な実行方法があるのでしょうか。

補足日時:2004/12/13 15:39
    • good
    • 0

とりあえず、いまあるプログラムは捨てて新しく作りましょう♪



空白文字(スペースやタブ)ピリオドやカンマ、感嘆符、疑問符などで単語を切り出すプログラムを作りましょう。
切り出した文字を登録する「辞書(頻度が記録できる)」を実現するプログラムを作りましょう。

とりあえずの辞書ができたら、検索、更新、登録なんかが素早くできるように、ブラッシュアップしましょう。

プログラムの練習でそういうのを作っているのでないなら、Perlなどを使うのが吉
    • good
    • 0
この回答へのお礼

うーん。1から作り直すとなると難しいですね

お礼日時:2004/12/13 16:11

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