リダイレクト機能を使って任意のテキストファイルを読み込み、すべての異なる英単語を取得し、それらを出現頻度順(降順)に並び替えるプログラムがわかりません。
条件として、必ず構造体を使うこと、英文字は大文字と小文字を分けること、FILE構造体を使ったファイル処理は使ってはいけないこと、があります。
構造体の問題
Re: 構造体の問題
今、下のようなプログラムまで書いたのですが、エラーは出ませんがSegmentation faultになってしまいます。as_468 さんが書きました:リダイレクト機能を使って任意のテキストファイルを読み込み、すべての異なる英単語を取得し、それらを出現頻度順(降順)に並び替えるプログラムがわかりません。
条件として、必ず構造体を使うこと、英文字は大文字と小文字を分けること、FILE構造体を使ったファイル処理は使ってはいけないこと、があります。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX_WORD 2048
/*構造体*/
typedef struct {
int cnt[MAX_WORD];
char read[MAX_WORD][MAX_WORD];
}English;
/*新しい単語をセットする*/
void set_word(int total, int i, int cnt_word[], char *EngWord[])
{
int j;
for(j = 0; j <= total - 2; j++) {
if (strcmp(EngWord, EngWord[j]) == 0) {
cnt_word[j]++; /*既出の単語だった場合、単語のカウントをインクリメント*/
i--;
total--;
}
}
}
/*カウントした要素を降順で並び替え*/
void bsort(int total, int cword[], char *EngWord[])
{
int i, j;
for (i = 0; i < total; i++) {
for (j = 1; j < total + 1; j++) {
if (cword > cword[j]) {
int temp1 = cword;
char *temp2 = EngWord;
cword = cword[j];
EngWord = EngWord[j];
cword[j] = temp1;
EngWord[j] = temp2;
}
}
}
}
void print_result(int total, int cnt_word[], char *EngWord[])
{
int i;
for(i = 1; i <= total; i++){
printf("%s: %5d times\n", EngWord, cnt_word);
}
}
int main(void)
{
English word;
int c;
int i = 0;
int j = 0;
int f = 1;
int total = 0;
char *EngWord[MAX_WORD];
while ((c = getchar()) != EOF) {
if (isalnum(c)) {
f = 0;
word.read[j] = c;
j++;
} else {
if (f == 0) {
f = 1;
word.read[j] = '\0';
EngWord[i] = &word.read[i][0];
word.cnt[i] = 1;
i++;
j = 0;
total++;
if (total >= 2) {
set_word(total, i, word.cnt ,EngWord);
}
}
}
}
bsort(total, word.cnt, EngWord);
print_result(total, word.cnt, EngWord);
return 0;
}
Re: 構造体の問題
"Segmentation fault"のエラー自体は単純なもので二次配列の形で大変大きな領域を確保しようとした場合に発生します。
#define MAX_WORD 100 //2048
で直ると思うけど、構造体自体の設計が間違っていると思われます。(構造体配列の動的領域確保mallocにするといいと思います)
#define MAX_WORD 100 //2048
で直ると思うけど、構造体自体の設計が間違っていると思われます。(構造体配列の動的領域確保mallocにするといいと思います)
Re: 構造体の問題
ソースコードを提示する際は、BBCodeが有効な(無効にしない)状態でBBCodeのcodeタグで囲んでいただけると、見やすくてありがたいです。
未初期化の自動変数の値は不定であり、それを用いた計算をすると未定義動作になります。
特に、デタラメなポインタをprintfの%sに渡すと、デタラメな場所を読み込もうとしてSegmentation Faultを起こすかもしれません。
また、set_word関数で仮引数のiやtotalの値を変更していますが、この変更によってmain関数のローカル変数のiやtotalの値が変わることはありません。
呼び出した関数に呼び出し元のデータを書き換えてもらいたい場合は、書き換えてもらいたいデータのポインタを渡す必要があります。
スタックオーバーフローによるSegmentation Faultの場合、二次配列かどうかは関係なく大きすぎる領域を(通常スタック上に確保される)自動変数として確保しようとすると発生します。metaphor さんが書きました:"Segmentation fault"のエラー自体は単純なもので二次配列の形で大変大きな領域を確保しようとした場合に発生します。
デバッガなどで確かめてはいませんが、bsort関数やprint_result関数で初期化されていないEngWord[total]の値を使っているように見えます。as_468 さんが書きました:今、下のようなプログラムまで書いたのですが、エラーは出ませんがSegmentation faultになってしまいます。
未初期化の自動変数の値は不定であり、それを用いた計算をすると未定義動作になります。
特に、デタラメなポインタをprintfの%sに渡すと、デタラメな場所を読み込もうとしてSegmentation Faultを起こすかもしれません。
また、set_word関数で仮引数のiやtotalの値を変更していますが、この変更によってmain関数のローカル変数のiやtotalの値が変わることはありません。
呼び出した関数に呼び出し元のデータを書き換えてもらいたい場合は、書き換えてもらいたいデータのポインタを渡す必要があります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 構造体の問題
みたいな感じにするとよさそうだと思います。as_468 さんが書きました:条件として、必ず構造体を使うこと
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 構造体の問題
やってみます!metaphor さんが書きました:"Segmentation fault"のエラー自体は単純なもので二次配列の形で大変大きな領域を確保しようとした場合に発生します。
#define MAX_WORD 100 //2048
で直ると思うけど、構造体自体の設計が間違っていると思われます。(構造体配列の動的領域確保mallocにするといいと思います)