ページ 11

名簿から頭文字で範囲検索するプログラム

Posted: 2015年1月08日(木) 16:15
by ririri
課題で名簿から頭文字で範囲検索をするプログラムが出題されました。
ローマ字名、ローマ字名の漢字名、住所、電話番号(ここはカンタンでいい)の四行の中のローマ字の頭文字を判定して、辞書のように頭文字で範囲検索するプログラムなんですが・・・。
名簿には

aoki
青木
東京
03-29
takagi
高木
神奈川
09-81
doi
土井
石川
87-8

のようなテキストファイルを用意し、このアルファベットの一番上を判定するものだと思ってプログラムを書きました。
でもうまくいかず・・・。
今のことろここまでできています。

コード:

 
#include<stdio.h>
#include<string.h>
main()
{FILE *fp;
 int i,k,n;
 struct{
 char name[100],shimei[100],jusho[100],f[100],e[100],tel;
 }data[100];
 char fname[80];
 printf("ファイル名\n");
 scanf("%s",&fname);
 fp=fopen(fname,"r");
 i=1;
 while(fscanf(fp,"%s",&data[i].name)!=EOF){
       fscanf(fp,"%s",&data[i].shimei);
       fscanf(fp,"%s",&data[i].jusho);
       fscanf(fp,"%s",&data[i].tel);
       i=i+1;
       } 
 printf("検索範囲\n");
 printf("始まり="); 
 scanf("%s",data[i].f);
 printf("終わり="); 
 scanf("%s",data[i].e);
 k=0;
 for(i=1;i<=5;i++){
 if(strcmp(data[i].name,data[i].f)&&(data[i].name<data[i].e)==0){
    printf("ローマ字名%s\n",data[i].name);
    printf("氏名%s\n",data[i].shimei);
    printf("住所%s\n",data[i].jusho);
    printf("電話番号%s\n",data[i].tel);
    k=k+1;
    }}
 if(k==0){printf("該当者いない\n");}
 
 fclose(fp);
 }
 

Re: 名簿から頭文字で範囲検索するプログラム

Posted: 2015年1月08日(木) 16:49
by usao
>ローマ字の頭文字を判定して、辞書のように頭文字で範囲検索する

これ,もうちょっとわかりやすく説明できませんか?
どのような入力を行ったらどうのような結果が出てくることになるのでしょうか?
関連して,28行目のif文はどういった判定を行っているのでしょうか.
(あと,27行目のforが i=1~5 という固定範囲を対象にしているのも不自然に感じます.)


7~9行目の構造体のメンバについて,
・name[100] が ローマ字名用
・shimei[100] が 漢字名用
・jusho[100] が住所用
なのだと思いますが,
e[100]とf[100]は何のための物なのでしょう?
また,telは電話番号用なのだと思いますが,その宣言で大丈夫ですか?(18行目の使い方に合っていないと思います)

Re: 名簿から頭文字で範囲検索するプログラム

Posted: 2015年1月08日(木) 18:53
by ririri
アルファベットを一文字ずつ入力して、その範囲で検索する・・・というものです。
例えば、
始まり=d
終わり=s
と入力したらd〜sからはじまるローマ字名の人物の情報が並べてでてくる、といった感じです。
fは始まりで入力した文字らeは終わりに入力した文字に対応させるつもりでした。
でも、自分のやり方が間違っているのかうまく動かないので別のやり方をするべきなんでしょうね。

Re: 名簿から頭文字で範囲検索するプログラム

Posted: 2015年1月08日(木) 21:51
by みけCAT
ririri さんが書きました:

コード:

if(strcmp(data[i].name,data[i].f)&&(data[i].name<data[i].e)==0){
この部分の条件文がわかりにくいですね。
とりあえず二重否定を消して

コード:

if(strcmp(data[i].name, data[i].f) != 0 && data[i].name>=data[i].e){
配列の先頭要素のポインタを比較しても意味が無さそうなので、
なぜか前半のみで用いられているstrcmpを後半でも用いて

コード:

if(strcmp(data[i].name, data[i].f) != 0 && strcmp(data[i].name, data[i].e) >= 0){
条件がおかしい気がするので適切に修正してみました。

コード:

if(strncmp(data[i].f, data[i].name, 1) <= 0 && strncmp(data[i].name, data[i].e, 1) <= 0){
さらに、ほかの部分も修正してみました。
  • main関数の型を適切に修正した
  • ファイルが開けたかのチェックを追加した
  • main関数がきちんと戻り値を返すようにした
  • telをchar型からchar[100]型にした
  • scanfとfscanfで用いられている余計な&を消した
  • f,eを構造体のメンバではなく、普通のローカル変数にした
  • 使用されていない変数nを消した

コード:

#include<stdio.h>
#include<string.h>
int main(void)
{FILE *fp;
 int i,k;
 struct{
 char name[100],shimei[100],jusho[100],tel[100];
 }data[100];
 char f[100],e[100];
 char fname[80];
 printf("ファイル名\n");
 scanf("%s",fname);
 fp=fopen(fname,"r");
 if(fp==NULL){puts("file open error");return 1;}
 i=1;
 while(fscanf(fp,"%s",data[i].name)!=EOF){
       fscanf(fp,"%s",data[i].shimei);
       fscanf(fp,"%s",data[i].jusho);
       fscanf(fp,"%s",data[i].tel);
       i=i+1;
       } 
 printf("検索範囲\n");
 printf("始まり=");
 scanf("%s",f);
 printf("終わり=");
 scanf("%s",e);
 k=0;
 for(i=1;i<=5;i++){
 if(strncmp(f,data[i].name,1)<=0&&strncmp(data[i].name,e,1)<=0){
    printf("ローマ字名%s\n",data[i].name);
    printf("氏名%s\n",data[i].shimei);
    printf("住所%s\n",data[i].jusho);
    printf("電話番号%s\n",data[i].tel);
    k=k+1;
    }}
 if(k==0){printf("該当者いない\n");}
 
 fclose(fp);
 return 0;
 }

Re: 名簿から頭文字で範囲検索するプログラム

Posted: 2015年1月09日(金) 10:06
by ririri
mainの関数なんですが、これをなんとか
main()の状態で作れないでしょうか?
voidという関数は扱っていなくてつかってはいけないようなので・・・。

条件の指定はなるほどと納得できました。
こうすればうまく動くんですね。

Re: 名簿から頭文字で範囲検索するプログラム

Posted: 2015年1月09日(金) 10:22
by ririri
5については解決しました。
ありがとうございました。
うまくできそうです。

Re: 名簿から頭文字で範囲検索するプログラム

Posted: 2015年1月09日(金) 22:03
by みけCAT
ririri さんが書きました:mainの関数なんですが、これをなんとか
main()の状態で作れないでしょうか?
voidという関数は扱っていなくてつかってはいけないようなので・・・。
「voidという関数」は使っていません。
C++ならint main()と書いてもいいです。

Re: 名簿から頭文字で範囲検索するプログラム

Posted: 2015年1月12日(月) 10:11
by かずま
ririri さんが書きました: 条件の指定はなるほどと納得できました。
こうすればうまく動くんですね。
1文字の比較に strcmp を使う必要はありません。

コード:

#include <stdio.h>

int main()
{
    FILE *fp;
    char fname[80], name[100], shimei[100], jusho[100], tel[100], f, e;
    int k = 0;

    printf("ファイル名\n"), scanf("%79s", fname);
    fp = fopen(fname, "r");
    if (!fp) return 1;

    printf("検索範囲\n" "始まり="), scanf(" %c", &f);
    printf("終わり="), scanf(" %c", &e);

    while (fscanf(fp,"%99s%99s%99s%99s", name, shimei, jusho, tel) == 4)
        if (name[0] >= f && name[0] <= e)
            printf("ローマ字名: %s\n氏名: %s\n住所: %s\n電話番号: %s\n",
                name, shimei, jusho, tel), k++;

    if (k == 0) puts("該当者いない");
    fclose(fp);
    return 0;
}
構造体の配列も不要です。