英文テキストファイルを読み込み、分割した単語の頻出頻度を表示するプログラムを作成しています。
現時点では、分割した単語の表示しかできていません。
どなたか良きアドバイスをお願いします。
#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;
}
No.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"と表示され、ファイルを読み込むことができません。
自分なりに試行錯誤してみましたがどうも上手くいきません。何か特別な実行方法があるのでしょうか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- その他(プログラミング・Web制作) pythonにおける単方向リストの実装について 4 2022/07/13 12:34
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- Visual Basic(VBA) VBAコードが作動せず、どこに問題があるのか教えて下さい。 3 2023/06/13 13:20
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
charでの計算?
-
文字列から空白を取り除きたい...
-
c++ 文字列を入力して、一文字...
-
C言語のfor文です。 繰り返しの...
-
enumの記述について。
-
プログラムを作成(c言語)
-
'const char *' 型は 'char *' ...
-
下記のプログラムがコンパイラ...
-
int main()の・・・
-
Linuxでフォルダ内全ファイル名...
-
C言語の入力した文字を反転させ...
-
charからLPTSTRへの変換方法
-
【C言語】文字型と整数型の違い
-
pingの結果を取得する方法
-
strlen関数と同じ働きをする関...
-
sprintf関数の作り方
-
atoi( ) の反対をやりたい
-
C言語 共用体について コマンド...
-
3桁区切(コンマ)記号をつけ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
charからLPTSTRへの変換方法
-
charでの計算?
-
配列をnビットシフトする
-
'const char *' 型は 'char *' ...
-
型変換
-
テキストデータをそのままバイ...
-
文字列から空白を取り除きたい...
-
CStringをwchar_tに変換したい
-
絶対パスからのファイル名の切...
-
fgetsなどのときのstdinのバッ...
-
ネットワークにつながっている...
-
str系関数を使わずに二つの文字...
-
3桁区切(コンマ)記号をつけ...
-
atoi( ) の反対をやりたい
-
double型の値をchar配列に変換...
-
C言語のfor文です。 繰り返しの...
-
switch文で文字を比較すること...
-
ファイル名である文字列からbas...
-
c++ 文字列を入力して、一文字...
-
strncpyと_tcsncpy_sのヌルの扱...
おすすめ情報