![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
『指定された辞書を配列に読み込み、表記または読みまたは品詞を指定すると、その単語の情報(表記、読み、品詞)を標準出力に出力するプログラムを作成せよ。』
という問題なんですが、
アルゴリズムは
1.単語の個数を数える
2.メモリを確保する
3.辞書を読み込む
4.検索する情報を入力する
5.配列の先頭から順番に、入力された情報が読み、標記にある単語を検索し、出力する。
だと思うんです。
しかし単語数を表示してメモリを確保するところまではできたのですが、辞書の読み込みがうまくいきません。
どこがおかしいのか教えてください。
辞書は
学校,ガッコウ,0010
資格,シカク,0011
のように「表記,読み,品詞」順で
カンマで区切られているファイルです。
struct JISYO {
char *hyouki,*yomi;
int hinsi;
};
main(int argc, char *argv[])
{
fp = fopen(argv[1],"r");
while(f=fgetc(fp))
{
if(f==EOF)break;
while(f!=',')
{
jisyo[count2].hyouki[count3]=f;
printf("%d\n",jisyo[count2].hyouki[count3]);
count3++;
f=fgetc(fp);
}
jisyo[count2].hyouki[count3]=0;
f=fgetc(fp);
count3=0;
while(f!=',')
{
f=jisyo[count2].yomi[count3];
count3++;
f=fgetc(fp);
}
jisyo[count2].yomi[count3]=0;
count3=0;
f=fgetc(fp);
fscanf(fp,"%d",&hin);
jisyo[count2].hinsi=hin;
count2++;
}
fclose(fp);
}
No.5ベストアンサー
- 回答日時:
struct JISYO {
char *hyouki,*yomi;
int hinsi;
};
jisyo=(struct JISYO *)malloc(sizeof(struct JISYO)*count);
という構造体の配列の確保は確認しました。
で、肝心のhyoukiとyomiはどこで確保してるんですか。
このままでは、hyoukiとyomiにはゴミが入っていてどこともいえないところのメモリを指しています。間違いなくランタイムエラー(アクセス違反)で落ちます。
したがって、この構造体が問題の方で指定されていたのであれば、一回fread+2回メモリスキャンという形式を想定していたのではないでしょうか。
ということで、擬似コード
#include <stdio.h> // printf/fopen/ etc...
#include <string.h> // strtok/strcpy/ etc...
#include <stdlib.h> // malloc/atoi etc...
struct JISYO {
char *hyouki;
char **yomi;
int hinsi;
};
main(int argc, char *argv[])
{
// 1.辞書ファイルをオープンし、サイズを確認する。
// 1-1.辞書ファイルをバイナリでオープン
// 1-2.ファイルの最後にシーク
// 1-3.ファイル位置を取得=ファイルサイズ
// 2.辞書を全部読み込めるメモリを確保する。*1
// 3.行単位でメモリへ読み込み、単語数をカウントする。
// 3-1.実際には一括読みの方がよい。間違えにくい。
// 4.読み込みが終わったらファイルはさっさとクローズ。
// 3-2.読み込んだメモリをスキャンして(forループ)
// 3-3.改行があったらカウントして、'\0'(終端記号)に置き換え。*2
// 5.カウントした行数から、構造体のメモリを確保
// 6.メモリをもう一度スキャンし、以下の処理をする。
// 6-1.辞書のメモリ内から、表記と読みへのポインタを
// struct JISYOにセットしていく。その際、カンマを
// '\0'に置き換えることで文字終端をセットする。
// 行末が'\0'で終わっているわけなので、strtokで分割
// してもよい。*3
// 6-2.表記と読みへのポインタを取得したら次は品詞が
// 文字列で入っているので、数値にする。
// 6-3.くりかえす
// 7.検索する情報を読み込む
// 8.配列をチェックし、該当の単語があれば出力する。
}
*1 ココでは、実は+1バイトして、そこには'\0'をしておいたほうが後々便利。詳細は「C言語 文字列 番兵」でweb検索。
*2 ファイル末尾が'\n'で終わっていることは必要条件です。
*3 というか、strtokの元の文字列を'\0'で分割するという特性から、ここではお勧め。実際のところ、strtokはもともとはコマンドラインをargv(charポインタ配列)に指定するために作られた関数なので、こういう使い方が想定どおりの使い方。
No.4
- 回答日時:
問題は
>struct JISYO {
>char *hyouki,*yomi;
>int hinsi;
>};
と、
>jisyo[count2].hyouki[count3]=f;
とかですね。
jisyo[count2]で、count2が1の場合、確保したメモリの何バイト目を指定していると思っていますか?
1行目の文字列を格納したあとを指していると考えているかと思いますが。
が、実際には先頭から12バイト後ろを(32bitOSの場合)指しています。
char*4バイト*2、intで4バイトです。sizeofで確認可能です。
で、
>f=jisyo[count2].yomi[count3];
これは読みを格納するつもりなんですから
jisyo[count2].yomi[count3] = f;
ですよね(^^;;という前提で。
もう気づいたかもしれませんが、
jisyo[count2].yomi[count3]で、count2=0、count3=1のときは、先頭から4バイト目を指しています。つまり、せっかく格納したhyoukiが3バイト以上あったら上書きしちゃってますよね。
といったことが問題になります。あくまでもchar*はアドレスを指すものであって、実体を指すものではありません。
こういった場合なのですが、まず、ファイルの内容をすべて読み込んでバッファに書き込んでしまいます。
で、その読み込んだバッファの中の、どの場所に目的の文字列の先頭があるか?という情報を別の領域を準備し、格納していくのがいいと思います。
もちろん他にも方法は考えられますが。
順序としては、
1.ファイルサイズと、単語の数を調べる。
単語の数は、改行の数でわかりますよね。
#最後の行が改行で終わってるかは確認でいてくださいね。
2.ファイルサイズ分のバッファを確保
3.辞書の管理をする構造体(struct JISYO)のサイズ*単語の数のサイズのメモリを確保
あとは、カンマと改行の位置をファイル内容のバッファを前から調べていき、辞書の構造体の配列に、それぞれの文字列の先頭アドレスを構造体のメンバに格納していってください。
改行、カンマの領域に'\0'を入れていくのを忘れずに。
No.3
- 回答日時:
まさかとはおもいますが、fseekかまたはrewindでファイルポインタを戻してないからうまくいってないとかそういうことではないでしょうね?
それなら、先の回答は無視してください。
No.2
- 回答日時:
あなたの期待している構造体の形式では、多分期待した動作はできないでしょう。
なぜなら、単語のサイズをどうするのか、余った領域は無駄ではないのか、ということを考えると、以下のようなアルゴリズムを検討してみてください。
1.辞書ファイルをオープンし、サイズを確認する。
2.辞書を全部読み込めるメモリを確保する。
3.行単位でメモリへ読み込み、単語数をカウントする。
4.ファイルをクローズする
5.単語数分のstruct JISYOの配列を確保する。
6.メモリをスキャンし、以下の処理をする。
6-1.辞書のメモリ内から、表記と読みへのポインタをstruct JISYOにセットしていく。その際、カンマを0に置き換えることで文字終端をセットする。
6-2.品詞をstruct JISYOにintにして保存する。
6-3.くりかえす。
7.検索する情報を読み込む
8.配列をチェックし、該当の単語があれば出力する。
No.1
- 回答日時:
まず、コンパイルが通るソースを載せてください。
変数の宣言がぜんぜんありません。
>しかし単語数を表示してメモリを確保するところまではできたのですが、辞書の読み込みがうまくいきません。
動的にメモリ確保してるところが無いんですけど。どこですか?
この回答への補足
申し訳ありません。字数制限のため『単語の個数,メモリの確保』を省いたんですが一緒に変数の宣言まで消してしまいました。
以下が『単語の個数を数え,メモリを確保』までのソースです。
struct JISYO {
char *hyouki,*yomi;
int hinsi;
};
main(int argc, char *argv[])
{
int c,count=0,count2=0,count3=0,hin=0;
char f;
FILE *fp;
struct JISYO *jisyo;
fp = fopen(argv[1],"r");
while(c=fgetc(fp))
{
if(c==EOF)break;
if(c=='\n')count++;
}
fclose(fp);
printf("tangosuu = %d",count);
jisyo=(struct JISYO *)malloc(sizeof(struct JISYO)*count);
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- Visual Basic(VBA) 1つの入力フォルダの値を読み込み、3分割をして新しい変数に代入する方法を教えていただきたいです。 読 4 2022/10/17 20:52
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- Ruby 【JAVA】数字をひし形に出力するプログラムについて 2 2022/07/11 23:32
- UNIX・Linux 次の要件を満たすにはどのように修正したらよろしいでしょうか 1 2022/11/24 20:57
- PHP PHPでCookieを使った訪問回数について 1 2023/05/28 14:10
- PHP ランキングを表示する際の画像の大きさを固定することは可能でしょうか? <?php if ( has_ 1 2022/07/21 14:55
- C言語・C++・C# C言語 3 2022/11/09 13:27
- PHP htmlで複数の個数入力欄を表示させるには 1 2022/09/20 03:11
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
c言語のポインタへの文字列入力...
-
sprintf()の使い方について
-
入れ子になった構造体について
-
malloc呼び出し時のセグメンテ...
-
プログラムが途中で強制終了し...
-
newでrealloc?
-
free関数で動作が止まる
-
fread関数および動的なメモリ確...
-
allocってなんですか?
-
malloc()関数内でセングメント...
-
仮想メモリでない環境でのmallo...
-
char*型が0x0を含む場合
-
Win32APIでのメモリ管理について
-
LPTSTR型の変数に文字を格納
-
構造体を使ったファイルの読み込み
-
アセンブラでのメモリの動的確...
-
stringの最大サイズ
-
win32APIのHeapAlloc()の使い方...
-
ビットをローテートするプログ...
-
#include <stdio.h> int main(v...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
c言語のポインタへの文字列入力...
-
mallocについて
-
newしないオブジェクトについて
-
allocってなんですか?
-
配列の添え字の最大数とは?
-
ヒープメモリの解放について
-
プログラムが途中で強制終了し...
-
Accessで、メモリを開放するタ...
-
malloc呼び出し時のセグメンテ...
-
ビットをローテートするプログ...
-
C++で、メンバもヒープに確保さ...
-
void*型のデータサイズ
-
入れ子になった構造体について
-
C言語に関する質問
-
スタック破壊の上手な見つけ方...
-
mallocで確保するメモリの領域...
-
C++のnewで確保したメモリーの...
-
指定したメモリアドレスの値の...
-
ヒープ領域の限界値設定
-
構造体でchar name[]と*nameの...
おすすめ情報