

データ数を読み込み、そのデーター分だけIDと名前を入力させ、IDで昇順にするか、または名前でアルファベット順にするかを入力させ、その結果を出力するプログラムを作成したいのですが、入力の仕方によって結果がおかしくなってしまいます。

というのも、先に実行結果を示してしまいますが、例えば以下のような時は

[code]

    $ ./a.out
    データ数: 3
    a[0]
      ID  :  1
      名前: suzuki
    a[1]
      ID  : 2
      名前: kato
    a[2]
      ID  : 3
      名前: sano
    1) ID, 2) 名前: 2
    
    要素  ID  名前
    a[0]:  2  kato           
    a[1]:  3  sano           
    a[2]:  1  suzuki         
    探索鍵(名前): sano
    探索鍵(名前) sano, ID 3 が a[1] に見つかりました
    
[/code]

このように名前もアルファベット順になり、それが存在するIDも表示しますが、  
以下のようなとき、

[code]

    $ ./a.out
    データ数: 3
    a[0]
      ID  : 2
      名前: kato
    a[1]
      ID  : 1
      名前: sano
    a[2]
      ID  : 4
      名前: suzuki
    1) ID, 2) 名前: 2
    
    要素  ID  名前
    a[0]:  2  kato           
    a[1]:  1  sano           
    a[2]:  4  suzuki         
    探索鍵(名前): suzuki
    探索鍵(名前) �U は見つかりませんでした
    
[/code]

実行結果が変になってしまいます。

自分は以下のようにプログラムを作成したのですが、どこがおかしいのかがわからなかったので  
よろしくお願いします。

[code]

    #include <stdio.h>
    #include <string.h>
    #define MAX_SIZE 100
    
    struct student{
        int id;
        char name[20];
    };
    typedef struct student Student;
    
    /* 二つのポインタ引数で示される Student型の値を入れかえる */
    void swap_student( struct student *a,struct student *b )
    {
        struct student t=*a;
        *a=*b;
        *b=t;
    }
    
    /* 長さ size のStudent型配列 a[] の各要素を
       選択ソートでid順（昇順）に並べかえる */
    void ssort_id( Student a[],int n )
    {
        int i,j;
        for(i=n-1;i>=1;i--){
         for(j=0;j<i;j++){
            if(a[j].id>a[j+1].id){
                 swap_student(&a[j],&a[j+1]);
            }
          }
        }
    }
    
    /* 長さ size のStudent型配列 a[] の各要素を
       選択ソートで名前順（昇順）に並べかえる */
    void ssort_name( Student a[],int size )
    {
        int i,j;
        for(i=0;i<size;i++){
         for(j=size-1;j>i;j--){
          if(strcmp(a[j-1].name,a[j].name)>0){
           swap_student(&a[j-1],&a[j]);
          }
        }
      } 
    }
    
    /* 配列 a[] のメンバ id に探索鍵(ID) x があるかどうかを二分探索で判定する */
    int bsearch_id( Student a[],int p,int q,int x )
    {
        int t=(p+q)/2;
        if(p>q){
          return -1;
        }
        if(a[t].id==x){
          return t;
        }
        if(a[t].id>x){
          q=t-1;
        } else{
          p=q+1;
        }
        return bsearch_id(a,p,q,x);
    }
    
    /* 配列 a[] のメンバ name に探索鍵(名前) x があるかどうかを二分探索で判定する */
    int bsearch_name( Student a[],int p,int q,char x[] )
    {
        int t=(p+q)/2;
        if(p>q){
          return -1;
        }
        if (!strcmp(a[t].name,x)){
          return t;
        }
        if(strcmp(a[t].name,x)>0){
          q=t-1;
        } else{
          p=q+1;
        }
        return bsearch_name(a,p,q,x);
    }
    
    /* 長さ size の配列 a[] の各要素にユーザからの入力値を格納する */
    void get_students(Student a[], int size)
    {
        int i;
        for (i = 0; i < size; i++) {
            printf("a[%d]\n", i);
            printf("  ID  : ");  scanf("%d", &a[i].id );
            printf("  名前: ");  scanf("%s", a[i].name );
        }
    }
    
    /* 長さ size の配列 a[] を表示する */
    void put_students(Student a[], int size)
    {
        int i;
    
        printf("\n要素  ID  名前\n");
        for (i = 0; i < size; i++) {
            printf("a[%d]: %2d  %-15s\n", i, a[i].id, a[i].name);
        }
    }
    
    int main(void)
    {
        int size,horw,pos,key;
        char keystr[20];
        Student a[MAX_SIZE];
    
        printf("データ数: ");  scanf("%d", &size);
        get_students(a, size);
        printf("1) ID, 2) 名前: ");
        scanf("%d", &horw);
    
        switch (horw) {
        case 1:
            ssort_id( a,size ); /* ID番号で昇順に並べ替え */
            put_students(a, size);
            printf("探索鍵(ID): ");  scanf("%d", &key);
            pos = bsearch_id(a,0,size-1,key);
            if (pos >= 0) {
                printf("探索鍵(ID) %d, 名前 %s が a[%d] に見つかりました\n", key,a[pos].name,pos );
            } else {
                printf("探索鍵(ID) %d は見つかりませんでした\n", key );
            }
            break;
        case 2:
            ssort_name(a,size); /* 名前で昇順に並べ替え */
            put_students(a, size);
            printf("探索鍵(名前): ");  scanf("%s", keystr);
            pos = bsearch_name(a,0,size-1,keystr);
            if (pos >= 0) {
                printf("探索鍵(名前) %s, ID %d が a[%d] に見つかりました\n", keystr,a[pos].id,pos );
            } else {
                printf("探索鍵(名前) %s は見つかりませんでした\n", a[pos].name );
            }
            break;
        }
    
        return 0;
    }
    
    
    
[/code]


CC BY-SA 4.0
2021-01-22T08:07:28.860
73495
2021-01-23T06:33:23.173
41837
question
c
ID番号または名前を探索鍵として二分探索で調べて結果を表示するプログラム


これなら、動くかもです。  
未検証ですが

[code]

    int bsearch_name( Student a[],int p,int q,char x[] )
    {
        int t=(p+q)/2;
        if(p>q){
          return -1;
        }
        if (!strcmp(a[t].name,x)){
          return t;
        }
        if(strcmp(a[t].name,x)>0){
          q=t;
        } else{
          p=t;
        }
        return bsearch_name(a,p,q,x);
    }
    
[/code]


CC BY-SA 4.0
2021-01-22T21:47:22.690
73507
2021-01-23T06:33:23.173
2021-01-23T06:33:23.173
3060
43624
73495
answer