• ベストアンサー

電話番号を読み込むプログラムについて教えてください

こちらには初めての質問です、よろしくお願いします。 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); }

noname#220054
noname#220054

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★『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) ); ・以上。上記のを今後の参考に。

参考URL:
http://www9.plala.or.jp/sgwr-t/lib/memset.html
noname#220054
質問者

お礼

アドバイスありがとうございました。詳しいアドバイスをしてもらったのですが、知識不足のせいでまだ解決していません。いろいろな原因を考えながらもう少しがんばって見ます。

noname#220054
質問者

補足

貴重なアドバイスありがとうございます。ご指摘の方法を参考にして、実行してみます。

その他の回答 (4)

  • 1839cc
  • ベストアンサー率54% (12/22)
回答No.5

おぉ、そういえば'\n'までついてしまうんでしたね。 けれど、'\n'が必ずつくとは限らないことを考えると、ANo3さんのようにstrchrを使うべきですね。 > 全データを表示させるには、(printf()関数) を利用すればいいのでしょうか? そうですね。 実際は様々なテクニックがありますが、 初めのうちはprintfやputsで十分だと思いますよ。 例えばこのような感じで・・・   for(loop = 0; loop < 10; loop++) {     puts(name[loop]);     puts(phone[loop]);   } もし仕事であれば・・・ デバッグコードを消し忘れる可能性もあるので、 このような手抜きは許されません(笑)

noname#220054
質問者

お礼

アドバイスありがとうございました。まだ原因が分からず、解決していませんが、デバッグのやり方を参考にしてもう少しがんばってみます。

noname#220054
質問者

補足

度々のアドバイスありがとうございます。今の私のレベルは、まだまだ初歩の段階です。アドバイスしていただいた方法を参考にしたいと思います。

回答No.4

> それから、そもそも'\0'を付加するためにstrlenを使用するのは矛盾しています。 > (strlenが動作するためには文字列が'\0'で終端している必要がある) > しかもstrlenの結果に-1すると、最後の文字を上書きしてしまいますよ。 fgets()で読み取った文字列の最後に付いている(通常は余分な)'\n'を 取り除くための、ごく一般的な方法です。 fgets()で文字列を読み取ったとき、例えば 'a', 'b', 'c', '\n', '\0' のように格納します。このとき、strlen()で求まる文字列長は'\n'までの4です。 でもって、'\n'を取り除いて'a', 'b', 'c', '\0'という状態にするには、 質問者の方が書かれたような方法で行なうのです。

noname#220054
質問者

お礼

アドバイスありがとうございました。まだ解決していませんが、ほかの原因を考えながらもう少しがんばって見ます。

noname#220054
質問者

補足

詳しいアドバイスありがとうございます。今回の間違いは、fgets()での代入が'0'と'\0'の間違いのようです。ここを書き換えてもう一度実行してみます。

  • 1839cc
  • ベストアンサー率54% (12/22)
回答No.2

> 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すると、最後の文字を上書きしてしまいますよ。 あとは、データ入力が終わったら、一度全データを表示させてみてはいかがですか? そうすれば、ある程度原因も見当がついていたはずです。 必要なくなれば、そのデバッグコードは無効にしてしまえばよいのですから。

noname#220054
質問者

お礼

アドバイスありがとうございました。いろいろ試してみたのですが、まだ解決していません。ほかの原因も考えて見ます。

noname#220054
質問者

補足

詳しいアドバイスありがとうございます。参考にしている本には書いてない事ばかりなので、大変参考になります。 追加の質問になってしまうのですが、全データを表示させるには、(printf()関数) を利用すればいいのでしょうか? こちらに質問をする前に、exit()関数で、デバッグをしてみたのですが 使い方が理解できませんでした。もしprintf()関数を使うのでしたら、今後の参考にしたいのですが教えていただけますか。

noname#26650
noname#26650
回答No.1

> name[loop][strlen(name[loop]) -1] = '0'; > phone[loop][strlen(phone[loop]) -1] = '0'; '0'を代入してはまずいです。 文字列終端用の'\0'を代入してください。

noname#220054
質問者

お礼

アドバイスありがとうございました。0と\0を入れ替えてみたのですが、解決できませんでした。ほかの原因を探して見ます。

noname#220054
質問者

補足

アドバイスありがとうございます。ご指摘のとおり、'0'では無く '\0'ですね。学習したのですが、'0'と'\0'についてきちんと理解してなかったです。

関連するQ&A

  • 分割

    下記のプログラミングを Makefileを利用して分割コンパイルしたいのですが、 分割の仕方からコンパイルまで全くわからなくて手が付けられません。 どなたかよろしくお願いします。 #include <stdio.h> #include <string.h> void write_profile(FILE *fp) { double height, weight; char name[100]; printf("名前を入力してください:"); scanf("%s", name); printf("身長を入力してください:"); scanf("%lf", &height); printf("体重を入力してください:"); scanf("%lf", &weight); fprintf(fp, "Name:%s, Height:%f, Weight:%f\n", name, height, weight); printf("ファイルに書き込みました。\n"); } int main(void) { FILE *fp; fp = fopen("profile", "a"); while(1){ write_profile(fp); fclose(fp); } return(0); }

  • プログラムの異常終了

    TEST2とコマンドプロンプトに表示された後、異常終了します。 以下が実行したプログラムです。 #include<stdio.h> void get_name(char **f_name2){ printf("ファイル名を入力"); scanf("%s",*f_name2); } int count_num(FILE *fp){ int ch =0; int count=0; while((ch=fgetc(fp))!=EOF){ if(ch>0&&ch<9){ count++; } } return(count); } int main (void){ char *fname; FILE *fp; get_name(&fname); if((fp=fopen(fname,"r"))==NULL){ printf("ファイルオープンエラー"); }else{ printf("%d\n",count_num(fp)); } fclose(fp); printf("TEST2\n"); return(0); } textc13-7.exeは動作を停止しました。と表示があります。正常に終了したいので、 御指摘お願いします。

  • ファイルから一文字ずつ読み込む

    ファイルを読み込むfgetc()関数のところでプログラムが停止します。 以下が実行したプログラムです。 #include<stdio.h> void get_name(char name[],int a){ printf("ファイル名を入力してください。\n"); scanf("%s",name); } void open(FILE *fp2,char name[]){ if((fp2=fopen(name,"r"))==NULL){ printf("ファイルオープンエラー"); } } int count(FILE *fp3){ int ch=0; int count=0; if(fp3==NULL){ printf("error"); } while((ch=fgetc(fp3))!=EOF){ if(ch=='\n'){ count++; } } printf("TEST"); fclose(fp3); return(count); } int main (void){ FILE *fp; char fname[30]; get_name(fname,30); open(fp,fname); printf("%d",count(fp)); return(0);} ファイル名を入力してください。ファイル名を入力、プログラム停止です。 '\n'を数えれるようにしてください。御指摘お願いします。

  • 入力ファイルのデフォルトの設定

    下のソースは入力ファイルの内容が例えば、 1 2 3 4 5 6 7 8 の時にその内容を出力するものです。 入力ファイル名がinput.datの場合、プログラム実行後にinput.datと入力し、Enterを押します。 このプログラムにinput.datをデフォルトとし、空Enterで入力を実行できるようにしたいと考えています。 入力ファイル名がinput.datでない場合は従来通りファイル名を入力してEnterを押すようにします。 この場合、どのようにソースを変更すればよいでしょうか。お手数ですが、教えてください。よろしくお願いします。 #include <stdio.h> #include <stdlib.h> int main(){ int i,N=0,data[10]; char ifile[20]; FILE *fp; printf("input file name: "); scanf("%s",ifile); if((fp=fopen(ifile,"r"))==NULL){ fprintf(stderr,"input file error\n"); exit(1); } while(fscanf(fp,"%d",&data[N])!=EOF && N<10){ N++; } printf("Total Number of Data = %d\n",N); for(i=0;i<N;i++){ printf("%d\n",data[i]); } fclose(fp); return 0; }

  • プログラムの実行

    このプログラム(下)なんですが、実行はできますが、実行結果が自分が思っているのとは異なる結果がでてしまいます。 'database.txt'には、1~100までの半角数字で入力した数字が1あがるごとに改行して保存しています。 僕は、例えばこのプログラムで2を入力すると、「一致しました」と表示されて、登録されていない数字345とかを入力すると「検索されませんでした」と表示されるようにしたいのですが、適当な数字を入れても「一致しました」と表示される場合があるのでこれを改善する方法を教えてください。 #define FNAME "database.txt" #define RECORDLEN 88 #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE *fp; char search[8],num[2]; int no = 0, find = 0, ip; fp = fopen(FNAME, "r"); if (fp == NULL) { perror("ファイルがオープンできません\n"); return -1; } printf("検索する番号の入力-- "); gets(search); while (1) { fseek(fp, RECORDLEN * no++, SEEK_SET); if (fscanf(fp, "%s", num) == EOF) break; if (strstr(num, search) != NULL) { find++; fscanf(fp, "%d", &ip); printf("番号結果: %d\n", ip); break; } } if(find==0){ printf("検索されませんでした\n"); } else{ printf("一致しました。\n"); } fclose(fp); return 0; }

  • fatal error LNK1120: 外部参照 1 が未解決です

    またわからないことが・・・ 教えて下さい。 以下をVC++2005でコンパイルすると、 MSVCRTD.lib(crtexew.obj) : error LNK2019: 未解決の外部シンボル _WinMain@16 が関数 ___tmainCRTStartup で参照されました。 C:\Documents and Settings\tomato\My Documents\Visual Studio 2005\Projects\a\Debug\a.exe : fatal error LNK1120: 外部参照 1 が未解決です。 と警告がでて通りません。 何のことでしょうか。 #include<stdio.h> #include<process.h> struct meibo{   char name[20];   char tel[20];   char address[20]; }; void message( void ); void input( FILE *fp, int cnt , struct meibo *a, int *end ); void main( void ) {   struct meibo a[20];   FILE *fp;   int cnt, end;   if( (fp=fopen( "meibo.dat", "w" ) ) == NULL ){     printf( "Can not open the meibo.dat.\n" );     exit( 1 );   }   message();   fprintf( fp, "番号, 名前, TEL, 住所\n" );   fflush( fp );   cnt = 0;   end = 0;   while( end == 0 ){     input( fp, cnt, &a[cnt], &end );     cnt++;     fflush( fp );     if( cnt == 20 ){       printf( "人数が一杯です.終了します.\n" );       end = 1;     }   }   fclose( fp ); } void message( void ) {   printf( "名前, TEL, 住所, endを入力してください.\n" );   printf( "継続の時はend=0," );   printf( "中止の時は,end=1と入力してください.\n" ); } void input( FILE *fp, int cnt, struct meibo *a, int *end ) {   printf( "名前-->" );   scanf( "%s", a->name );   printf( "TEL -->" );   scanf( "%s", a->tel );   printf( "住所-->" );   scanf( "%s", a->address );   printf( "Exit? Continue:0 Exit:1 -->" );   scanf( "%d", end );   printf( "\n" );   fprintf( fp, "%2d, %s, %s, %s\n",     cnt+1, a->name, a->tel, a->address ); }

  • C言語のプログラム組んだのですが完成させてください

    C言語のプログラムを断片的に作成したのでつなげて完成させて頂けないでしょうか? このサイトでコンパイルなど出来ます http://ideone.com/ 以下の問題を解きました また問題文の指示には必ずしたがってください。また、この文章の条件でなく、人数が4人とかそれ以外の時でも出来るようなプログラムでお願いします。 http://i.imgur.com/nuzJv2v.png http://i.imgur.com/c7f3Vh2.png http://i.imgur.com/5aCqDO0.png http://i.imgur.com/9u8hHIM.png 問題は画像になっています #include<stdio.h> #include<string.h> /*構造体型struct Dataの宣言*/ struct Data{ char name[20]; int height; double weight; } data[100]; int cnt; int main(void) { int a; do { printf("**************身長・体重の表示***************\n\n"); printf(" データファイルの読み込み・・・・・(1)\n"); printf(" 全てのデータを表示・・・・・・・・(2)\n"); printf(" 特定のデータを表示・・・・・・・・(3)\n"); printf(" 終わり・・・・・・・・・・・・・・(4)\n\n"); printf("処理番号を入力してください\n"); scanf("%d",&a); } while(a<1 || a>4); return a; } /*read_file関数の宣言*/ int read_file(void) { FILE *fp; char filename[20]; cnt=0; printf("読み込むファイルの名前を入力してください。\n"); scanf("%s",filename); fp=fopen(filename,"r"); if(fp==NULL){ printf("ファイルをオープンできませんでした。\n"); return 1; } while(fscanf(fp,"%c %d %lf",data[cnt].name,data[cnt].height,data[cnt].weight)!=EOF){ cnt++; fclose(fp); printf("ファイルを読み込みました。\n"); } return 0; } /*p_all関数の宣言*/ int p_all(void) { int i; printf("名前 身長(cm) 体重(kg)\n"); for(i=0;i<cnt;i++) { printf("%-2s %5d %.2f\n",data[i].name,data[i].height,data[i].weight); } } 最初の処理番号を入力した所で終わってしまいます、何とか改変してくださいお願いします 補足

  • [動的配列]C言語の勉強で簡単な単語帳プログラム

    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言語のファイルシステム関数。ファイルの現在位置をファイルの先頭に置くことができる。

  • ポインタと配列

    次のソースで、結果表示でポインタを使いたいのですが、うまくいきません。1件しか表示されないのです。 ポインタの扱いがおかしいのだと思いますが、どうしたらよいでしょうか? #include <stdio.h> #include <string.h> int search(char key[256],FILE *fp,char *result[256][256]); main(void) { FILE *fp; int rep,n,i; char x[256],key[256],*result[256][256]; printf("検索キーワードを入力してください。\n" "キーワード>"); gets(key); if((fp=fopen("personal.txt","r"))==NULL) { printf("ファイルをオープンできません\n"); exit(1); } printf("=====検索結果=====\n"); n=search(key,fp,result); for(i=0;i<n;i++) { printf("%s\n",result[i]); } printf("検索結果:%d件です。\n",n); fclose(fp); } int search(char key[256],FILE *fp,char *result[256][256]) { int n=0; char *p,word[256],*name; while((p=fgets(word,256,fp))!=NULL) { if(strstr(word,key)!=NULL) { name=strtok(p," "); strcpy(result[n],name); n++; } } return n; } 実行すると、下の警告がでます。 illegal pointer combination(param)

  • プログラムの添削

    以下のようなプログラムを作りました.よりよい書き方,アドバイスなどお願いします. /*文字列の入力を繰り返し受け取るプログラムを作成しなさい.*/ #include<stdio.h> #include<string.h> int main(void) { char bigstr[101],str[31]; printf("文字列の入力を繰り返し受け取るプログラムです.\n"); strcpy(str,""); strcpy(bigstr,""); for(;;) { printf("文字列を入力してください.\n"); gets(str); if(strlen(str)>30) { printf("入力できる文字数の上限(20字)を超えました.\n"); return 0; } else if(strcmp(str,"quit")) { strcat(bigstr,str); if(strlen(bigstr)>100) { printf("入力できる文字数の上限(合計100字)を超えました.\n"); return 0; } } else break; } printf("%s\n",bigstr); return 0; }