- ベストアンサー
助けてください。困っています
初めまして 課題でメイン関数(メインメニュー)から呼び出されるサブシステムの「かな氏名検索」を作っているのですが、 自分なりに頑張ってみたものの全くの初心者のため完全に行き詰ってしまい、どこが悪いのかもわからない状態です。 なので、皆さんに教えて頂きたいと思い、 お願いにまいりました。 100人分のデータから「ふりがな」を部分一致で検索して、一致した人のデータを表示させるもので、 探すデータ(社員データ)はカンマ区切りテキストで 社員番号 名前 ふりがな 郵便番号 住所 電話番号 生年月日 入社年月日 役職コード 所属コード 性別 の順に 0523,鈴木一郎,すずきいちろう,105-0000,東京都どこどこ, ,19830101,20090404,01,01,M のように入っています。空白部には半角スペースが入ってます。 現在の自分で作ったソースは #include <stdio.h> #include <string.h> #include "CFUNC.h" #include "display.h" #define NUM 200 typedef struct shain{ char id[5]; char name[21]; char hurigana[31]; char yubin[9]; char jusyo[101]; char tel[14]; int birth; int nyusya; char yakusyokucode[3]; char syozokucode[3]; char seibetsu[2]; }shain; int main(void) { int j; int i; int cnt = 0; shain data[100]; FILE *fp; char *token; char s[NUM]; char mes[25] = "該当する結果がありません"; char mes2[30] = "該当するメニューがありません"; char str[30]; fp = fopen("shain.txt","r"); if(fp==NULL){ printf("ファイルオープンに失敗しました。\n"); return 1; } for(i=0; i<100; ++i){ fgets(s,NUM-1,fp); token= strtok(s, ","); /* str1の分割(1回目) */ strcpy(data[i].id,token); token = strtok(NULL, ","); strcpy(data[i].name,token); token = strtok(NULL, ","); strcpy(data[i].hurigana,token); token = strtok(NULL, ","); strcpy(data[i].yubin,token); token = strtok(NULL, ","); strcpy(data[i].jusyo,token); token = strtok(NULL, ","); strcpy(data[i].tel,token); token = strtok(NULL, ","); data[i].birth =(int)token; token = strtok(NULL, ","); data[i].nyusya=(int)token; token = strtok(NULL, ","); strcpy(data[i].yakusyokucode,token); token = strtok(NULL, ","); strcpy(data[i].syozokucode,token); token = strtok(NULL, "\n"); strcpy(data[i].seibetsu,token); } cls(); /*検索画面*/ printf("*****************************************************\n"); printf("[かな氏名検索]\n"); printf("かなを入力してください:\n"); printf(" \n"); printf(" \n"); printf(" 0:メニューに戻る\n"); printf("*****************************************************\n"); printf("メッセージ:\n"); for(;;){ setLocate(24,3); scanf("%s",str); if(strcmp(str,"0")==0){ break; } for(i=0; i<100; ++i){ if(strncmp(str,data[i].hurigana,5)==0){ cnt++; if(cnt==1){ /*検索結果画面*/ printf("*****************************************************\n"); printf("[かな氏名検索結果]\n"); printf("社員番号 氏名 ふりがな 入社年度 所属 性別 役職\n"); printf(" %s %s %5s %d %s %s %s %s\n", data[i].id,data[i].name,data[i].hurigana,data[i].nyusya, data[i].syozokucode,data[i].seibetsu,data[i].yakusyokucode); } else{ printf(" %s %s %5s %d %s %s %s %s\n", data[i].id,data[i].name,data[i].hurigana,data[i].nyusya, data[i].syozokucode,data[i].seibetsu,data[i].yakusyokucode); } } //見たつからなかった時 if (cnt==0){ setLocate(12,8); printf("%s\n",mes); } //メッセージ setLocate(24,3); scanf("%s",str); setLocate(12,8); printf("%s\n",mes); } } printf("\n"); fclose(fp); return 0; } 所々変なところもあり見にくいと思いますが、 とりあえず単独で検索だけしっかり出来るようにしたいです。 検索は1回だけでなく、何回も出来るようにしたいです。 下手な文章のうえ長文でまことにすいませんが、よろしくお願いします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
(行頭が「・」のものが主な不具合の修正です) >for(i=0; i<100; ++i){ ぴったし100人のときだけの設計になっています。 現実的ではありません、というか当方もデバッグに苦労するので・・。 ・while( NULL != fgets( s, NUM-1, fp ) ){ >data[i].birth =(int)token; 「キャスト」では、文字列を整数にできません。 ・data[ i ].birth = atoi( token ); >「ふりがな」を部分一致で検索して、 >if(strncmp(str,data[i].hurigana,5)==0){ ・部分一致では、strstr( data[i].hurigana, str ) がよいのでは・・。 http://www.bohyoh.com/CandCPP/C/Library/index.html >現状は、自分自身まだC言語だけでなく、プログミング自体勉強を始めて2週間くらいで、 ☆一歩一歩、まずは、「かなを入力し表示」するだけのプログラムを作ってみるのがよろしいかと。 天から和尚という言葉もありますよ。 でも、超初心者なのに、なぜ「困り度」がMAXなんだろう? ☆以下に、修正を投稿します。 質問主旨に直接関係しないものは省略しています(「画面制御」関連)。 windows2000(BorlandC++5.5.1)で動作を確認しました。 なお、出力「列」をそろえたい場合、フォーマット指定子で調整すればと・・。 http://www.k-cube.co.jp/wakaba/server/format.html #include <stdio.h> #include <stdlib.h> #include <string.h> #define RECL 200 // 最大レコード長 typedef struct{ int iBirth; int iNysya; char cIDno[ 8 ]; char cName[ 16 ]; char cFrgn[ 32 ]; char cYbin[ 16 ]; char cJysy[ 128 ]; char cTelN[ 16 ]; char cYkuC[ 8 ]; char cSzkC[ 8 ]; char cSbtu[ 4 ]; }SHAIN; int KouzoutaiKakunou( SHAIN sData[] ) { int iNinzu = 0, kk; FILE *fp; char *token, *Top; char cBuf[ RECL ], cWork[ 11 ][ 128 ]; fp = fopen( "Z:\\SHAIN.txt", "r" ); if( fp == NULL ){ printf( "ファイルオープンに失敗しました。\n" ); return( 0 ); } while( NULL != fgets( cBuf, RECL, fp ) ){ // 1人分読み込み Top = token = cBuf; kk = 0; while( *token ){ while( ',' != *token ){ if( '\n' == *token ) break; if( '\0' == *token ) break; token++; } *token = '\0'; strcpy( cWork[ kk++ ], Top ); token++; Top = token; // 次の項目の先頭 } if( 11 != kk ){ // 全項目切り分けられたか printf( "%d レコード異常 %s\n", kk, cWork[ 0 ] ); return( 0 ); } strcpy( sData[ iNinzu ].cIDno, cWork[ 0 ] ); strcpy( sData[ iNinzu ].cName, cWork[ 1 ] ); strcpy( sData[ iNinzu ].cFrgn, cWork[ 2 ] ); strcpy( sData[ iNinzu ].cYbin, cWork[ 3 ] ); strcpy( sData[ iNinzu ].cJysy, cWork[ 4 ] ); strcpy( sData[ iNinzu ].cTelN, cWork[ 5 ] ); sData[ iNinzu ].iBirth = atoi( cWork[ 6 ] ); sData[ iNinzu ].iNysya = atoi( cWork[ 7 ] ); strcpy( sData[ iNinzu ].cYkuC, cWork[ 8 ] ); strcpy( sData[ iNinzu ].cSzkC, cWork[ 9 ] ); strcpy( sData[ iNinzu ].cSbtu, cWork[ 10 ] ); iNinzu++; } fclose( fp ); return( iNinzu ); } int main( void ) { int i, iNinzu, iCnt; SHAIN sData[ 100 ]; char cKana[ 32 ]; iNinzu = KouzoutaiKakunou( sData ); // 社員データ読み込み while( iNinzu ){ printf( "*****************************************************\n" ); printf( "[かな氏名検索]\n" ); printf( "かなを入力してください\n" ); printf( " 0:終了\n" ); printf( "*****************************************************\n" ); iCnt = 0; scanf( "%s", &cKana ); if( strstr( cKana, "0" ) ) break; // 終了 printf( "[かな氏名検索結果(検索文字「%s」)] \n\n", cKana ); for( i = 0; i < iNinzu; ++i ){ if( NULL == strstr( sData[i].cFrgn, cKana ) ) continue; // 不一致 printf( "%s ", sData[ i ].cIDno ); printf( "%s ", sData[ i ].cName ); printf( "%s ", sData[ i ].cFrgn ); printf( "%s ", sData[ i ].cYbin ); printf( "%s ", sData[ i ].cJysy ); printf( "%s ", sData[ i ].cTelN ); printf( "%d ", sData[ i ].iBirth ); printf( "%d ", sData[ i ].iNysya ); printf( "%s ", sData[ i ].cYkuC ); printf( "%s ", sData[ i ].cSzkC ); printf( "%s ", sData[ i ].cSbtu ); printf( "\n" ); iCnt++; } if( 0 == iCnt ) printf( "「%s」では該当する結果がありませんでした\n", cKana ); } return( 0 ); } 注:インデントに全角空白を用いています。コピペ後、タブに一括変換して下さい。
その他の回答 (4)
- 1108435
- ベストアンサー率43% (94/217)
#3です。補足します。ループから抜けられないのはstrが前の入力を保持しているからですね。PCからしたら”あ”という入力の後に”0”を入力されても”あ0”になるだけで”0”が入力されたとは思わないからです。一度strをクリアしないとループから脱出できません。
お礼
アドバイスありがとうございます。 細かいテストなどは行っていませんでした(汗) 少しずつ確かめながらやってみます。
- 1108435
- ベストアンサー率43% (94/217)
結構突っ込みどころがたくさんありますね。for(;;)文ですが、do~while文で置き換えられます。それからmesは定義では2つ設定されていますが(mesとmes2)使われているのはmesだけです。またfor(100)ループの下に必ず見つけられなかったメッセージが出るようになっていますよね。 また、データの格納の状態をテストしてみましたか?自分だったらCSVのままにしないで一度struct型のファイルに落とすプログラムを作ってCが持つ強力なファイル検索機能を使いますけど、それは置いて置いて、無限ループをコメントアウトしてcnt==1からの部分だけ独立して、百人分のデータがちゃんと思ったとおりに格納されているのか表示してみる手だと思います。 細かいテストは行ったのでしょうか?
- asuncion
- ベストアンサー率33% (2127/6289)
>(例えば「あ」だけ入力したら、ふりがなに「あ」が含まれる人全て) この仕様と >if(strncmp(str,data[i].hurigana,5)==0){ この実装は合致していますか? strncmpの第2引数に指定している5という値の根拠は何ですか?
補足
>>if(strncmp(str,data[i].hurigana,5)==0){ >この実装は合致していますか? >strncmpの第2引数に指定している5という値の根拠は何ですか? これに関しましては、はじめに書いたものがうまくいかなかったので 適当に試してみる感覚で書いたものです。 なので、特に根拠はないです。 すいません。 その部分ははじめ、 if(strcmp(str,data[i].hurigana)==0){ というふうにしていました。
- asuncion
- ベストアンサー率33% (2127/6289)
>自分なりに頑張ってみたものの全くの初心者のため完全に行き詰ってしまい 想定する結果は、何ですか? それが想定と違ってどうなるために、行き詰まっているのですか? うまくいかない、ということは、ご自身が予想されている結果があって、実際にはそれと食い違っているのですよね。 それらを説明してください、というお願いです。
補足
説明不足ですいません。 最終的に結果は、「かな」を入力して部分一致(例えば「あ」だけ入力したら、ふりがなに「あ」が含まれる人全て) 検索して、該当結果を結果表示画面で一覧で表示させたいです。 その後、再度検索、または0押しでプログラム終了。 また、「かな」入力時にも0押しでプログラムを終了させるようにしたいです。 しかし、自分の作ったものでは検索がうまくいきません。 該当がない場合、エラーメッセージを表示させるようにしてあるのですが、 データにある文字を入力しても、エラーメッセージが表示されてしまいます。 なので結果も上手く表示させることが出来るのかもわかりません。 また、プログラム起動時の初回の入力で0を押すと、プログラムを終了させる ことが出来るのですが、2回目以降の入力で0を押しても終了させることができません。 現状は、自分自身まだC言語だけでなく、プログミング自体勉強を始めて2週間くらいで、 なんとか参考書などを見てやっていますが、 どこが間違っているのかもわからず、手をつけられない状態です。 この説明でご理解頂けるでしょうか?
お礼
わざわざソースの修正までありがとうございます! 自分も少しずつやってみようと思っているのですが、 課題で出されてしまい、期日も迫っているので焦っていました。 とりあえず修正して頂いたソースの処理を一つ一つ理解しながら、 やっていこうと思います。