• ベストアンサー

再検索プログラムについて

再びすみません。 先ほどは別の問題で質問させていただきました。 今回は、address2.txtに保存してあるアドレスを検索するプログラム(下記)なのですが、 (1)アドレスが一致しないときに、再び検索できるようにしたいのですが、うまくできません。 (2)address2.txtに登録してあるアドレスの7行目以降は検索されなくなってしまいます。 これらの問題解決のご指摘をお願いします。 #define FNAME "address2.txt" #define RECORDLEN 16 #include <stdio.h> #include <stdlib.h> #include <string.h> char *format = "%-15s\n"; int main() { FILE *fp; char search[16], address[16],ans[8]; int no = 0, find = 0; 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", address) == EOF) break; if (strstr(address, search) != NULL) { find++; printf("アドレス: %s\n", address); } } if(find>=1){ printf("アドレスが一致しました。" ); } else { printf("アドレスが一致しません。\n"); printf("再度検索し直しますか?(Y/N)\n"); gets(ans); if(ans[0]=='y'||ans[0]=='Y') continue; else break; } fclose(fp); return 0; }

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

  • ベストアンサー
  • Senna_FF
  • ベストアンサー率45% (153/334)
回答No.3

たびたびごめんなさい。 提示したソースは、あくまでプロトですよ(~_~;) テストケースは洗いだして、おかしいところは修正してくださいね。 それから、ファイルの中身を固定長にされているようなので、 fscanf()関数でなく、fgets()の方がお勧めです。

noname#89227
質問者

お礼

 ほんとに何度も回答していただいてどうもありがとございました。Senna_FFさんのおかげで無事にプログラムが実行できました。

その他の回答 (3)

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.4

仕様がいまいちはっきりしないのですが、少なくともバッファーオーバーフローの危険がある、gets(3)は使わないほうが良いでしょう。定義したRECORDLENや、format が使われていないのも気になります。固定長レコードのしたわけは何かあるのでしょうか?などなど… 見つからなかったときにはレコードを追加できる仕様にして書き直してみました。 #define FNAME "address2.txt" #define RECORDLEN 16 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> char *format = "%-15s\n"; int main() { FILE *fp; char search[RECORDLEN], address[RECORDLEN], ans[8]; char *p; int find = 0; fp = fopen(FNAME, "a+"); if (fp == NULL) { perror("ファイルエラー"); return(errno); } while (1) { printf("アドレスの入力-- "); if (fgets(search, RECORDLEN, stdin) == 0) { break; } if ((p = strchr(search, '\n')) != NULL) *p = '\0'; fseek(fp, 0L, SEEK_SET); find = 0; while (1) { if (fgets(address, RECORDLEN, fp) == 0) break; if (strstr(address, search) != NULL) { find++; printf("アドレス: %s\n", address); } } if (find != 0) { printf("アドレスが一致しました。\n"); } else { printf("アドレスが一致しません。\n"); printf("登録しますか?(Y/N)\n"); fgets(ans, 7, stdin); if (ans[0] == 'y' || ans[0] == 'Y') { fseek(fp, 0L, SEEK_END); fprintf(fp, format, search); fflush(fp); continue; } } printf("終了しますか?(Y/N)\n"); fgets(ans, 7, stdin); if (ans[0] == 'y' || ans[0] == 'Y') break; } fclose(fp); return 0; }

noname#89227
質問者

お礼

 私が作りたかったプログラムよりも更に素晴らしいプログラムソースを載せて頂いて嬉しい限りです。期待以上の回答どうもありがとうございました。

  • Senna_FF
  • ベストアンサー率45% (153/334)
回答No.2

とりあえず、前回指摘分のループ階層、及び変数初期化を入れてみました。 更に気づいたところを、ちょこっと修正!! (久しぶりに自宅で環境使った。意外と燃えてしまいますね。) これで動確済みです。ソースを比較してみてください。 iint main(int argc, char* argv[]) {   FILE *fp;   char search[16], address[16],ans[8];   int no = 0, find = 0;     // File Open   fp = fopen(FNAME, "r+");   if(fp==NULL){     perror("ファイルエラー\n");     return -1;   }     // Main Loop Start   while(1) {     // Initialize     no = 0;     find = 0;       // Get Console     printf("アドレスの入力-- ");     gets(search);       // String Search Loop     while (1) {       fseek(fp, RECORDLEN * no++, SEEK_SET);       if (fscanf(fp, "%s", address) == EOF)         // Not Found!!         break;       if (strstr(address, search) != NULL) {         // Get String!! Do break!!         find++;         printf("アドレス: %s\n", address);         break;       }     }       if(find>=1){       printf("アドレスが一致しました。" );     }     else {       printf("アドレスが一致しません。\n");       printf("再度検索し直しますか?(Y/N)\n");       gets(ans);       if(ans[0]=='y'||ans[0]=='Y')         // Retry         continue;       else         // Loop End         break;     }   }   fclose(fp);   return 0; } ※ちなみにstrstr()関数では部分一致になるけど、それでいいのかな?  完全一致をおこなうならmemcmp(),strcmp()系関数を使用してください。 ※今後は「うまくいきません。」でなく、「XXXXXになってしまいます」とか、「XXXXエラーが出ます」のように書かれると、  レスがつきやすくなると思います。  内容知っているのは、masaved19831109さんだけですからね。  こういうのも慣れだと思いますので、くじけずがんばってください。

  • Senna_FF
  • ベストアンサー率45% (153/334)
回答No.1

7行目以降というのがよくわからないのですが・・・ 再検索後に、変数noを初期化しないとシーク位置が先頭に戻らないのでは? ちなみにデータってどんなものなのでしょう。 "address2.txt"の内容を貼り付けてもらうと、また違った観点から検証 することができると思いますが・・・ (もちろん、実データは伏せていただいてかまいません。書式を見てみたいです。改行位置とか桁数とか。)

noname#89227
質問者

補足

"address2.txt"の中身はIPアドレスを保存していて、 例えば「X.X.X.X」と保存して次の行に改行しますが、その前に次の先頭の行が16(n-1)バイト目にくるようにスペースキーと改行で設定しているはずなのですが、 どうもうまくいきません。保存の仕方に問題があるのでしょうか?

関連するQ&A

専門家に質問してみよう