- ベストアンサー
電話番号を読み込むプログラムについて教えてください
こちらには初めての質問です、よろしくお願いします。 C言語の基礎を独学で学習中の初心者です。 テキストファイルに、名前と電話番号をあらかじめ書き込んでおき、 検索したい人の名前を入力すると、電話番号が表示されるというプログラムについて教えてください。 1、名前は漢字で入力 (山野 桜) 2、電話番号は、半角で入力 (001234567\n) この様にして10人分のデータが、入力してあります。 実行時に名前を入力しても電話番号が表示されません。 エラーメッセージも出ません、プログラムに問題があるのか、作成したテキストファイルに問題があるのか判断できません。 アドバイスをお願いします。 #include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char name[10][22]; char phone[10][13]; char input[21]; int loop; FILE *FP; if((FP = fopen("address.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return(1); } /*ファイルからデータを読み込む*/ for(loop = 0; loop < 10; loop++) { fgets(name[loop], 22, FP); name[loop][strlen(name[loop]) -1] = '0'; fgets(phone[loop], 13, FP); phone[loop][strlen(phone[loop]) -1] = '0'; } printf("電話番号を検索したい名前を入力してください\n"); gets(input); /*検索と表示*/ for(loop = 0; loop < 10; loop++) { if(strcmp(name[loop], input) == 0) { printf("%sさんの電話番号は : %s\n", input, phone[loop]); } } return (0); }
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
★『fgets』関数の戻り値をチェックするようにしましょう。 ・あと改行コードを『\0』の終端文字に置き換えたいようですが、この場合は『strchr』の 関数で検索して見つかったらば『\0』に書き換えるようにすれば良い。 ・下にループ部のみを記述します。 ループ部: char *find; ←宣言部に追加 /*ファイルからデータを読み込む*/ for ( loop = 0 ; loop < 10 ; loop++ ){ if ( fgets(name[loop],sizeof(name[0]),FP) != NULL ){ if ( (find = strchr(name[loop],'\n')) != NULL ){ *find = '\0'; ←『0』ではなくて『\0』です。注意! } } if ( fgets(phone[loop],sizeof(phone[0]),FP) != NULL ){ if ( (find = strchr(name[loop],'\n')) != NULL ){ *find = '\0'; ←ここも『\0』です。 } } } その他: ・最後の方で『検索と表示』を行っていますが、データが 10 人以下の場合はデタラメな データが name、phone に入っているため『strcmp』関数で上手く比較できないと思います。 ・そこで、 name、phone の2つの変数を初期化しておきます。 宣言部を次のようにします。 (1)初期化方法1…『static』を付ける static char name[10][22]; static char phone[10][13]; (2)初期化方法2…『{ 0 }』を付ける char name[10][22] = { 0 }; char phone[10][13] = { 0 }; (3)初期化方法3…宣言部ではなくて『fopen』関数の前に実行 memset( name, '\0', sizeof(name) ); memset( phone, '\0', sizeof(phone) ); ・以上。上記のを今後の参考に。
その他の回答 (4)
- 1839cc
- ベストアンサー率54% (12/22)
おぉ、そういえば'\n'までついてしまうんでしたね。 けれど、'\n'が必ずつくとは限らないことを考えると、ANo3さんのようにstrchrを使うべきですね。 > 全データを表示させるには、(printf()関数) を利用すればいいのでしょうか? そうですね。 実際は様々なテクニックがありますが、 初めのうちはprintfやputsで十分だと思いますよ。 例えばこのような感じで・・・ for(loop = 0; loop < 10; loop++) { puts(name[loop]); puts(phone[loop]); } もし仕事であれば・・・ デバッグコードを消し忘れる可能性もあるので、 このような手抜きは許されません(笑)
お礼
アドバイスありがとうございました。まだ原因が分からず、解決していませんが、デバッグのやり方を参考にしてもう少しがんばってみます。
補足
度々のアドバイスありがとうございます。今の私のレベルは、まだまだ初歩の段階です。アドバイスしていただいた方法を参考にしたいと思います。
- totsugiino
- ベストアンサー率37% (6/16)
> それから、そもそも'\0'を付加するためにstrlenを使用するのは矛盾しています。 > (strlenが動作するためには文字列が'\0'で終端している必要がある) > しかもstrlenの結果に-1すると、最後の文字を上書きしてしまいますよ。 fgets()で読み取った文字列の最後に付いている(通常は余分な)'\n'を 取り除くための、ごく一般的な方法です。 fgets()で文字列を読み取ったとき、例えば 'a', 'b', 'c', '\n', '\0' のように格納します。このとき、strlen()で求まる文字列長は'\n'までの4です。 でもって、'\n'を取り除いて'a', 'b', 'c', '\0'という状態にするには、 質問者の方が書かれたような方法で行なうのです。
お礼
アドバイスありがとうございました。まだ解決していませんが、ほかの原因を考えながらもう少しがんばって見ます。
補足
詳しいアドバイスありがとうございます。今回の間違いは、fgets()での代入が'0'と'\0'の間違いのようです。ここを書き換えてもう一度実行してみます。
- 1839cc
- ベストアンサー率54% (12/22)
> name[loop][strlen(name[loop]) -1] = '0'; > phone[loop][strlen(phone[loop]) -1] = '0'; '0'ではまずいというか、この2行は入れないほうがよいですね。 strncpyなどは'\0'が入らないことがあるので、 このような処理が必要になってきます。 しかし、fgetsでは'\0'が保障されますので必要ないでしょう。 それから、そもそも'\0'を付加するためにstrlenを使用するのは矛盾しています。 (strlenが動作するためには文字列が'\0'で終端している必要がある) しかもstrlenの結果に-1すると、最後の文字を上書きしてしまいますよ。 あとは、データ入力が終わったら、一度全データを表示させてみてはいかがですか? そうすれば、ある程度原因も見当がついていたはずです。 必要なくなれば、そのデバッグコードは無効にしてしまえばよいのですから。
お礼
アドバイスありがとうございました。いろいろ試してみたのですが、まだ解決していません。ほかの原因も考えて見ます。
補足
詳しいアドバイスありがとうございます。参考にしている本には書いてない事ばかりなので、大変参考になります。 追加の質問になってしまうのですが、全データを表示させるには、(printf()関数) を利用すればいいのでしょうか? こちらに質問をする前に、exit()関数で、デバッグをしてみたのですが 使い方が理解できませんでした。もしprintf()関数を使うのでしたら、今後の参考にしたいのですが教えていただけますか。
> name[loop][strlen(name[loop]) -1] = '0'; > phone[loop][strlen(phone[loop]) -1] = '0'; '0'を代入してはまずいです。 文字列終端用の'\0'を代入してください。
お礼
アドバイスありがとうございました。0と\0を入れ替えてみたのですが、解決できませんでした。ほかの原因を探して見ます。
補足
アドバイスありがとうございます。ご指摘のとおり、'0'では無く '\0'ですね。学習したのですが、'0'と'\0'についてきちんと理解してなかったです。
お礼
アドバイスありがとうございました。詳しいアドバイスをしてもらったのですが、知識不足のせいでまだ解決していません。いろいろな原因を考えながらもう少しがんばって見ます。
補足
貴重なアドバイスありがとうございます。ご指摘の方法を参考にして、実行してみます。