- ベストアンサー
検索の方法を教えて頂きたいです。
現在、テキストファイルの検索プログラムを課題で行っているのですが、どう処理すればよいか、苦悩しています。先生には、構造体を利用するよう言われています。どなたか、アドバイスを頂けないでしょうか?テキストファイルの内容は自分で適当に作りました。このようにしています。 →ファイル名(soccer.txt)ファイルの中身→ 例「 番号,名前,年齢 」 1 ,川口 能活,33 38,楢崎 正剛,40 20,川島 永嗣,22 10,中澤 佑二,35 51,駒野 友一,19 9 ,中村 俊輔,29 22,遠藤 保仁,17 15,鈴木 啓太,32 19,本田 圭佑,51 28,家長 昭博,25 30,高原 直泰,18 7 ,播戸 竜二,44 問題の流れは、 (1)条件を選択して下さい[1~4] 1:全部表示 2:番号で検索 3:名前で検索 4:年齢で検索 99:終了 (2) 1番を選んだら、その名の通りファイルの中身を全部表示する。 (3) 2番を選んだら、さらに、番号の条件を選んで入力[1~4] 1: 1~9 , 2: 10~19 , 3: 20~29 , 4: 30以上 とし、条件にヒットするとその行を表示するよう、考えています。 一応、全部表示は、ソースはめちゃくちゃかもしれませんが、全部表示できたので、全部の検索方法をと言うと、図々しいと思うので、番号で検索だけでも、なにかアドバイス頂けたらと思っています。 どうぞ、宜しくお願いします。(泣) #include<stdio.h> #include <stdlib.h> #include <string.h> struct data{ int no; // 番号 char name[20]; // 氏名 int age; // 年齢 }; int search_all(struct data *lis); void search_no(int number); int main() { int a; int number; data list1[12]; while(a){ printf("条件を選択して下さい[1~4]\n"); printf(" 1:全部表示\n"); printf(" 2:番号で検索\n"); printf(" 3:名前で検索\n"); printf(" 4:年齢で検索\n"); printf(" 99:終了\n"); scanf("%d", &a); if(a == 1){ // 全部表示 printf("全部表示\n"); search_all(list1); } //番号で検索 else if(a == 2){ printf("番号の条件を選んで入力して下さい[1~4]\n"); printf(" 1: 1~9\n 2: 10~19\n 3: 20~29\n 4: 30以上\n"); scanf("%d", &number); search_no(number); } } return 0; } //ファイルの情報を取得する int search_all(struct data *lis) { FILE *fp; char s[20]; char str1[20]; //番号を格納 char str2[20]; //名前を格納 char str3[20]; //年齢を格納 fp = fopen("soccer.txt", "r"); //1行単位で読込み while(fp != NULL){ fgets(s, 20, fp); if (feof(fp)){ break; } //番号を取得する strncpy(str1, s, 2); //NULL文字追加 str1[2] = '\0'; lis->no = (int)str1; //名前を取得する strncpy(str2, &s[3], 9); //NULL文字追加 str2[9] = '\0'; strcpy(lis->name, str2); //年齢を取得する strncpy(str3, &s[13], 2); //NULL文字追加 str3[2] = '\0'; lis->age = (int)str3; printf("%s %s %s \n", lis->no, lis->name, lis->age); } fclose(fp); return 0; } //番号検索 void search_no(int number) { printf("該当の番号%dの行を表示\n", number); }
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
★アドバイス ・まずはテキストデータをすべて読み込んで struct data 構造体にセットする関数を きちんと作成して下さい。回答者 No.1 さんのアドバイスにある >⇒ read_data(FILE* fp, struct data* target, size_t size); のように data型の配列にファイル……を別途作成する ↑ このような関数を作成しましょう。 内容は search_all() 関数で記述しているのを構造体の配列にセットできるように編集します。 まずは下のような関数を作って下さい。→main() 関数はサービスで作りました。残りは自分で。 サンプル: // 最大のデータ数 #define MAX_LIST (100) // 関数のプロトタイプ宣言 void read_data( FILE *fp, struct data list[], size_t size ); void print_data( struct data list[], size_t size ); void search_num( struct data list[], size_t size ); void search_name( struct data list[], size_t size ); void search_age( struct data list[], size_t size ); // メイン関数 int main( void ) { struct data list[ MAX_LIST ]; ←テキストのデータが 100 行以内と限定 FILE *fp; int menu; if ( (fp = fopen("soccer.txt","r")) != NULL ){ read_data( fp, list, MAX_LIST ); ←ここで読み込む fclose( fp ); do { printf( "条件を選択して下さい[1~4]\n" ); printf( " 1:全部表示\n" ); printf( " 2:番号で検索\n" ); printf( " 3:名前で検索\n" ); printf( " 4:年齢で検索\n" ); printf( "99:終了\n" ); scanf( "%d", &menu ); switch ( menu ){ case 1: print_data( list, MAX_LIST ); break; case 2: search_num( list, MAX_LIST ); break; case 3: search_name( list, MAX_LIST );break; case 4: search_age( list, MAX_LIST ); break; default: break; } } while ( menu != 99 ); ←これで終了 return 0; } printf( "soccer.txt - ファイルが見つかりません。\n" ); return 1; } // テキストデータを読み込む専用関数 void read_data( FILE *fp, struct data list[], size_t size ) { /* 記述 */ } // 構造体の内容を表示する専用関数 void print_data( struct data list[], size_t size ) { /* 記述 */ } // 番号で検索 void search_num( struct data list[], size_t size ) { /* 記述 */ } // 名前で検索 void search_name( struct data list[], size_t size ) { /* 記述 */ } // 年齢で検索 void search_age( struct data list[], size_t size ) { /* 記述 */ }
その他の回答 (2)
構造体を使わない場合は、 (使わないとだめなんですよね…?) 共有ループを使ってみてはどうでしょうか? 3カラムCSV形式とみなして、 //a=選択NO,p=テキストファイル先頭ポインタ for (i=0;i<12;i++){ ret=Cell(a-2,p,i)//自作関数 switch (a-2) { case 0: atoi(ret)の番号値を参照・・・ break; case 1: retの文字列を参照・・・ break; case 2: atoi(ret)の年齢値を参照・・・ } char* Cell(int a,char* p,int i) { int c=0,z=0; for (j=0;j<i;j++){ while (*p-'\r' | *(p+1)-'\n') c++;c+=2;} while (z-a) {while (*p-',') c++;z++} return p+z; } とシンプルにやっても良いと思います。
- koko_u_
- ベストアンサー率18% (459/2509)
あんまり役に立たないアドバイスらしきものを。 最も注意すべき点は、「正しい関数名を付けること」です。 search_all() で「全てを表示」と言いながら、ファイルからデータを読み込んでいるのでこれを止めましょう。 ⇒ read_data(FILE* fp, struct data* target, size_t size); のように data型の配列にファイルを読み込む処理を別途作成する ⇒ search_all() ではなく、print_data(struct data* target, size_t size) のように、作成した data 配列を印字する関数とする 最初に data 配列にファイル内容を格納すれば、後は「適当な」関数を定義して、その結果を印字できるでしょう。 しかし、print_data() をせっかく作ったので、検索関数の方は search_somehow(struct data* target, ..., struct data* result); のように結果を配列に格納するようにして、印字はすべて print_data() にさせるのが良いでしょう。
お礼
お礼の返事が遅くなり申し訳ありません。アドバイスありがとうございました。超がつく初心者なので、全てのことが役に立っています。 また質問する機会があると思いますので、お暇があるときはまた宜しくお願いします。
お礼
お礼が遅くなり申し訳ありません。サンプルまで作って頂いて、超初心者の自分には、大変、参考になりました。まだまだ理解できない部分があるのですが、少しずつクリアできるようがんばって行きます。また機会があればアドバイスして頂けたらと、思ってます。ありがとうございました。