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

C言語の勉強として以下のような簡単なプログラムを作りました。
テキストファイルからユーザが入力した単語を検索し、ヒットしたものだけ
その単語とその説明を表示するというプログラムです。

正常に動いているようなので、
つぎはループごとに、読み込んだ文字数に合わせて
配列(mean)の要素数を動的に確保するということを
しようと思うのですがどのタイミングでmallocやreallocを入れればよいのか
いまいちよくわかりません。

また、このプログラムの欠点などありましたら教えていただけると助かります。
よろしくお願いします。

---------------------------------------------------------------------
//マイ単語帳プログラム
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

main(){

char input[100];//ユーザが入力した文字列を格納
char tango[200];//ファイルの単語
char mean[1000];//ファイルの説明
char conti;//検索を続けるかどうかの入力
int flag;//検索単語がヒットした場合に立てるフラグ
FILE *fp;

//単語ファイルのopen
if((fp=fopen("tango.txt","r"))==NULL){
printf("ファイルが開けません。");
exit(1);
}

/*******************ファイルからの文字列読み込み****************************/
//Yが入力されるまで検索を続ける
do{
printf("検索する単語を入力してください。\n");
scanf("%s",input);
printf("検索対象:%s\n\n",input);

flag=0;//ヒットしたかどうかのフラグの初期化
while((fscanf(fp," %s %s",tango,mean))!=EOF){//fscan 書式を指定して読み込める。
if(strcmp(tango,input)==0){//strcmpは2つの引数が同じ時0を返す
printf("%s\n%s\n\n\n",tango,mean);
flag=1;//ファイル内に単語があった場合にフラグを立てる。
}
}

rewind(fp);

if(flag==0){
printf("その単語は登録されていません。\n");
}

printf("検索を終了しますか? ==> Y\n");
printf("検索を続けるにはY以外の文字を入力してください。\n");
scanf(" %c",&conti);//scanfの問題点を回避するために読み込み前に半角スペース
}
while(conti!='Y');

/**************************************************************************/
fclose(fp);
return;
}
----------------------------------------------------------------
tango.txt

apple リンゴ
SMTP 電子メールの送信や転送を行うためのプロトコル。
rewind 形式:rewind(ファイルポインタ); C言語のファイルシステム関数。ファイルの現在位置をファイルの先頭に置くことができる。

A 回答 (2件)

>やはりできないのですかね?(^_^;)



meanを読み込む前にmeanのサイズを取得する方法がないと…無理でしょうね。

あるいは…1文字(1バイト)ずつ読み込んで、改行位置に到達しなかったらrealloc()で拡張して、さらに1文字(1バイト)読み込む…とか。
realloc()自体は1バイト単位でやる必要は無いかも知れませんけどね。
# そこらヘンは http://oshiete.goo.ne.jp/qa/6961996.html 辺りでも話題になってますが。

>要するにヒットしたらすぐに抜け出す方が効率がいいということですかね?
>テキストファイルのインデックスは重複しないように作成するつもりです。

仕様次第…です。
 man (成人の)男,男子
 man [無冠詞で総称的に] (女と対比して)男
 man オンラインリファレンスマニュアルのインターフェース
とか、複数の意味があるものを無視するかどうか…でしょう。
最初にヒットしものだけ。重複はない。というのであれば、ヒットした時に読み込みループを抜けた方が動作としては軽い…かと。

>strcmpする前にワンクッションおいて大文字小文字を区別しないような動作を入れるといいということでしょうか?

stricmp()を使う。なんて方法もあります。
input[]に入るのが、ASCIIの場合に限るかも知れませんけど。
# shift-jisが入った場合にstricmp()が正しく動作するかは…ライブラリ次第でしょうな。
    • good
    • 0
この回答へのお礼

前回のアドバイスをいただいてからさっそくstricmp()使っているのですが、
文字コードのことまではまったく考えていませんでした。
というか、文字コード自体についてほとんど理解していないのでそこから
勉強する必要がありそうです(笑)

>最初にヒットしものだけ。重複はない。というのであれば、ヒットした時に読み込みループを抜けた方が動作としては軽い…かと。
もう少し検討してみます!

お礼日時:2011/08/29 23:23

>配列(mean)の要素数を動的に確保するということを


>しようと思うのですがどのタイミングでmallocやreallocを入れればよいのか
>いまいちよくわかりません。

もちろん、実際に読み込む前です。
が、読み込んでみないと長さが判らないので…どうにも出来なさそうですが……。

>また、このプログラムの欠点などありましたら教えていただけると助かります。

お約束ですが、バッファオーバーフローの可能性は残ったまま…でしょう。
input[]とtango[]でサイズが違う。という意図も不明ですが。
input[]に入力したデータがtango.txtの先頭にあったとしても、最後まで読み込みを継続している…とか。
# まぁ、最後まで読んでいるのでtango.txtに同一の単語があった場合に全て表示することになりますが。
strcmp()を使用しているため、例のパターンだと"Apple"はヒットしない…とか。
    • good
    • 0
この回答へのお礼

>どうにも出来なさそうですが……。
やはりできないのですかね?(^_^;)

>input[]とtango[]でサイズが違う。という意図も不明ですが。
ソースをここにペーストしたときに自分も気づきました(笑)
とりあえずそのまま張り付けた方がいいと思い修正しませんでした。
直しておきます。

>input[]に入力したデータがtango.txtの先頭にあったとしても、最後まで読み込みを継続している…とか。
要するにヒットしたらすぐに抜け出す方が効率がいいということですかね?

>まぁ、最後まで読んでいるのでtango.txtに同一の単語があった場合に全て表示することになりますが。
検索するのはスペース前のインデックス(tango)だけなのでmeanの方で重複しても関係ないので気にしていませんでした。
テキストファイルのインデックスは重複しないように作成するつもりです。

>例のパターンだと"Apple"はヒットしない…とか。
strcmpする前にワンクッションおいて大文字小文字を区別しないような動作を入れるといいということでしょうか?

お礼日時:2011/08/28 17:12

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