質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

1回答

1764閲覧

c言語を使った音素のユニグラムの作成についてアドバイスお願いします

straycat

総合スコア11

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2016/11/30 13:34


出張+シュッチョー+17 [出張+シュッチョー+17] sh u q ch o:
出張所+シュッチョー{ショ/ジョ}+2 [出張所+シュッチョーショ+2] sh u q ch o: sh o
出張所+シュッチョー{ショ/ジョ}+2 [出張所+シュッチョージョ+2] sh u q ch o: j o
出超+シュッチョー+2 [出超+シュッチョー+2] sh u q ch o:
出直し+デナオシ+2 [出直し+デナオシ+2] d e n a o sh i
出直し+デナオシ+出直す+44/12/6 [出直し+デナオシ+出直す+44/12/6] d e n a o sh i
出直す+デナオス+44/12/2 [出直す+デナオス+44/12/2] d e n a o s u
出廷+シュッテイ+17 [出廷+シュッテイ+17] sh u q t e i
出典+シュッテン+2 [出典+シュッテン+2] sh u q t e N
出展+シュッテン+17 [出展+シュッテン+17] sh u q t e N
出店+シュッテン+17 [出店+シュッテン+17] sh u q t e N
出土+シュツド+17 [出土+シュツド+17] sh u ts u d o


上のように各行に「表記+読み+品詞コード+音素列」が示されているデータ群を音素列の発生頻度から発生確率を求めたいのです。

少し前に作った文字カウントのソースコードに改良して作り、下のようなところまでできたのですが、少し積んでしまいました。

そこで、

  • 現在単語を区切る文字をスペースにしているのですが、それだとローマ字表記の部分まで区切られてしまうので、ファイル からの行の読み込みを"sscanf"を利用してそれぞれの行の書式付きで読み込みカウントしたい
  • カウントされた結果を高い順に回数とともに出力したい

の2点についてアドバイスお願いします。

#include <stdio.h> #include <stdlib.h> #include <string.h> #define FILENAME "data.txt" /*入力するファイル名*/ #define SEPARATOR " " /*単語を区切る文字*/ #define TABLESIZE 100000 /*word_tableの大きさ*/ struct word_count { char *word; /*単語*/ int count; /*頻度*/ }; int main() { FILE *fp; struct word_count word_table[TABLESIZE]; /*単語と頻度を格納する配列*/ char line[256], *token; int i, table_size, find; table_size = 0; /*ファイル入力にエラーが生じた場合*/ if ((fp = fopen(FILENAME, "r")) == NULL) { printf("file open error!!\n"); exit(1); } while(fgets(line, 256, fp) != NULL) { token = strtok(line, SEPARATOR); for(;token!= NULL;token = strtok(NULL, SEPARATOR)){ find = 0; /*word_tableとの照合*/ for (i = 0; i < table_size; i++) { /*一致する単語を見つけた場合*/ if (strcmp(token, word_table[i].word) == 0) { word_table[i].count++; find = 1; break; } } /*word_table中に一致する単語がなかった場合*/ if (find == 0) { word_table[table_size].word = malloc((strlen(token)+1)*sizeof(char)); strcpy(word_table[table_size].word,token); word_table[table_size].count = 1; table_size++; } } } fclose(fp); /*word_tableを出力*/ for (i = 0; i < table_size; i++) { printf("word=%5s count=%d\n", word_table[i].word, word_table[i].count); } return(0); }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ローマ字表記の部分まで区切られてしまうので

もし1行を「出張+シュッチョー+17」「[出張+シュッチョー+17]」「sh u q ch o: 」の3つの文字列として読みたいのであれば、三つ目の文字列をsscanfで読み込むのはうまくいかないようです。よって例えば次のような方法が考えられます。

  • lineの行末にある改行文字'\n'を削除しておく
  • 2つ目まではsscanf(line, "%s %s ", token1, token2);のようにして読み込む
  • 3つ目は2つ目までの文字列の長さから先頭位置を計算する

token3 = line + strlen(token1) + strlen(token2) + 8;

カウントされた結果を高い順に回数とともに出力したい

word_tableをソートしてその結果を表示してください。自分で単純なアルゴリズムでソートしてもいいですし、stdlib.hに定義されているqsortを使ってもよいと思います。例えば・・・

C

1int comparator(const void *ppa, const void *ppb) 2{ 3 struct word_count *pa = *(struct word_count**)ppa; 4 struct word_count *pb = *(struct word_count**)ppb; 5 return pb->count - pa->count; 6} 7struct word_count word_table[TABLESIZE] 8struct word_count *wtp[TABLESIZE]; 9 10int main() 11{ 12 ... 13 for (i = 0; i < table_size; i++) { 14 wtp[i] = workd_table + i; 15 } 16 qsort(wtp, table_size, sizeof(wtp[0]), comparator); 17 for (i = 0; i < table_size; i++) { 18 struct word_count *wp = wtp[i]; 19 printf("word=%5s count=%d\n", wp->word, wp->count); 20 } 21}

上の例では配列word_table, wtpをローカル変数にしてませんが、理由はあまりに巨大な配列をローカル変数として定義するのはスタックオーバーフローの原因になりかねないからです。このような巨大な配列はグローバル変数にするかmallocでヒープに確保したほうがよいと思います。(グローバル変数にしてもunix系OSであればbss領域になるのでexecutable fileが不当に巨大にはならないはずです。その他のOSでどうなるかはわかりません)
本件には関係ないですが、一々struct word_countと書くのは面倒に感じました。typedefした方がいいと思います。

投稿2016/12/02 14:32

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問