LoginSignup
2
4

More than 3 years have passed since last update.

C言語 学生名簿管理プログラムの作成

Last updated at Posted at 2019-08-23

1. 仕様

次の機能を持つ.
1. 学籍番号と氏名を入力(登録)する.データの重複は考慮しない.
2. 登録済みの学籍番号と氏名を表示する.
3. 学籍番号で昇順ソートする.
4. 学籍番号で降順ソートする.
5. 学籍番号を入力し,完全一致したデータを削除する.
6. 学籍番号と氏名のデータを持つテキストファイルを読み込む.今まで登録していたデータは上書きされる.
7. 登録されているデータをテキストファイルに書き込む.
8. 学籍番号を入力し,完全一致するデータを検索する.

2. ソースコード

nameList.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

struct student{
    char number[10];    //学籍番号
    char name[50];      //氏名
};

void data_in(struct student *std);                          //入力
void data_out(struct student *std);                         //出力
void data_asc(struct student *std,int ninzu);               //昇順
void data_desc(struct student *std,int ninzu);              //降順
int data_delete(struct student *std,int ninzu,int search);  //削除
int file_read(struct student *std,int ninzu);               //読み込み
void file_write(struct student *std,int ninzu);             //書き込み
int check(struct student *std,int ninzu);                   //検索

int main(void)
{
    struct student std[20];         //生徒人数
    int ninzu=0,i,search;           //n:人数(データ数), i:繰り返し用, search:検索配列値格納用
    int menu,end=0;                 //menu:処理選択用, end:終了用

    while(1)
    {
        printf("メニュー\n");
        printf("1:データ入力\n");
        printf("2:データ出力\n");
        printf("3:小さい順に整列\n");
        printf("4:大きい順に整列\n");
        printf("5:データ削除\n");
        printf("6:ファイルからデータ読み込み\n");
        printf("7:ファイルへのデータ書き込み\n");
        printf("8:データ検索\n");
        printf("9:終了\n");
        printf("実行する処理の番号-->");
        scanf("%d%*c", &menu);  //%*c:改行を読み飛ばす

        switch(menu)
        {
          case 1:           //入力
            if(ninzu>=20){  //既に20名のデータが存在する時
                printf("データ数が上限に達しています\n\n");
                break;
            }
            data_in(&std[ninzu]);
            ninzu++;                //人数を1人分増やす
            printf("データを入力しました\n\n");
            break;
          case 2:                   //表示
            for(i=0;i<ninzu;i++)    //入力した人数分
                data_out(&std[i]);
            if(ninzu==0)            //データが存在しない時
                printf("表示するデータがありません\n");
            printf("\n");
            break;
          case 3:           //昇順ソート
            if(ninzu==0){   //データが存在しない時
                printf("整列させるデータが存在しません\n\n");
                break;
            }
            data_asc(&std[0],ninzu);
            break;
          case 4:           //降順ソート
            if(ninzu==0){   //データが存在しない時
                printf("整列させるデータが存在しません\n\n");
                break;
            }
            data_desc(&std[0],ninzu);
            break;
          case 5:                           //削除
            search=check(&std[0],ninzu);    //検索した値の配列の中身を格納
            if(search>=0){                  //検索したデータと同じデータが見つかった場合
                data_out(&std[search]);
                ninzu=data_delete(&std[0],ninzu,search);
                printf("上記のデータを削除しました\n\n");
            }
            else{
                printf("データが存在しません\n\n");
            }
            break;
          case 6:                           //ファイル読み込み
            ninzu=file_read(&std[0],ninzu); //読み込んだ時のデータ数を格納
            break;
          case 7:           //ファイル書き込み
            if(ninzu==0){   //データが存在しない時
                printf("書き込むデータが存在しません\n\n");
                break;
            }
            file_write(&std[0],ninzu);
            break;
          case 8:                           //検索
            search=check(&std[0],ninzu);    //検索した値の配列の中身を格納
            if(search>=0){                  //検索したデータと同じデータが見つかった場合
                printf("検索結果\n");
                data_out(&std[search]);
                printf("\n");
            }
            else{
                printf("データが存在しません\n\n");
            }
            break;
          case 9:   //終了
            end=1;  //終了条件の値を代入
            break;
          default:  //エラー
            printf("入力番号がありません\n\n");
        }
        if(end==1)  //終了条件の値が入っている時
            break;
    }
    return 0;
}
void data_in(struct student *std)   //入力
{
    printf("学籍番号---->");
    scanf("%s",std->number);                //学籍番号のデータ読み込み
    printf("名前---->");
    scanf("%s",std->name);              //氏名のデータ読み込み
}
void data_out(struct student *std)              //出力
{
    printf("%s\t%s\n", std->number, std->name); //既存のデータ表示
}
void data_asc(struct student *std,int ninzu)                //昇順
{
    int i,j;
    struct student temp;

    //学籍番号を昇順にソート
    for(i=0;i<ninzu;i++){                                   //i番目のカウント
        for(j=i;j<ninzu;j++){                               //j番目のカウント
            if(strcmp((std+i)->number,(std+j)->number)>0){  //i番目の方が大きい時
                temp=*(std+i);                              //i番目のデータを退避
                *(std+i)=*(std+j);                          //j番目のデータを格納
                *(std+j)=temp;                              //i番目のデータを格納
            }
        }
    }

    printf("小さい順に並べかえました\n\n");
}
void data_desc(struct student *std,int ninzu)               //降順
{
    int i,j;
    struct student temp;

    //学籍番号を降順にソート
    for(i=0;i<ninzu;i++){                                   //i番目のカウント
        for(j=i;j<ninzu;j++){                               //j番目のカウント
            if(strcmp((std+i)->number, (std+j)->number)<0){ //i番目の方が小さい時
                temp=*(std+i);                              //i番目のデータを退避
                *(std+i)=*(std+j);                          //j番目のデータを格納
                *(std+j)=temp;                              //i番目のデータを格納
            }
        }
    }

    printf("大きい順に並べかえました\n\n");
}
int data_delete(struct student *std,int ninzu,int search)   //削除
{
    int i;

    for(i=search;i<ninzu;i++){  //検索した位置から人数を最後尾まで
        std[i]=std[i+1];        //削除してできた空き要素を詰める
    }
    ninzu--;                    //削除した分の人数を減ずる

    return ninzu;               //人数をmain関数に返す
}
int file_read(struct student *std,int ninzu)                                    //読み込み
{
    FILE *fin;
    char in_filename[20];
    int i=0;

    printf("入力ファイル名---->");
    gets(in_filename);                                                          //ファイル名の読み込み

    if((fin = fopen(in_filename,"r")) == NULL){                                 //ファイルが開けない時
        printf("ファイルが開けません\n\n");
        return ninzu;                                                           //人数をmain関数に返す
    }
    while(fscanf(fin,"%s\t%s",(std+i)->number,(std+i)->name) != EOF){           //ファイルのデータを読み込む
        i++;                                                                    //ファイルのデータ数をカウント
    }

    if(i==0)
        printf("ファイルにデータが存在しません\n\n");
    else
        printf("ファイルを読み込みました\n\n");

    fclose(fin);                                                                //ファイルを閉じる

    return i;
}
void file_write(struct student *std,int ninzu)                  //書き込み
{
    FILE *fout;
    char out_filename[20];
    int i;

    printf("出力ファイル名---->");
    gets(out_filename);                                         //ファイル名の読み込み

    if((fout = fopen(out_filename, "w")) == NULL){              //書き込み用ファイルを開けなかった時
        printf("ファイルが開けません\n");
        fclose(fout);                                           //ファイルを閉じる
    }

    for(i=0;i<ninzu;i++){                                       //人数分
        fprintf(fout,"%s\t%s\n",(std+i)->number,(std+i)->name); //ファイルへ書き込む
    }

    printf("ファイルへ書き込みました\n\n");

    fclose(fout);                                               //ファイルを閉じる
}

int check(struct student *std,int ninzu)            //検索
{
    char number[10];
    int i;

    if(ninzu>0){                                    //データが存在する時
        printf("学籍番号を入力---->");
        gets(number);
        for(i=0;i<ninzu;i++){                       //人数分のデータを順番に
            if(strcmp(number,(std+i)->number) == 0) //一致する文字列(学籍番号)があった時
                return i;                           //データの位置をmain関数に返す
        }
    }

    return -1;                                      //見つけられなかったときに返す
}

3. 注意事項

学籍番号のソートはchar型配列である.
数値型(int型等)ではなく,学籍番号を数字のみにしても,数値の大小比較にならないことに注意すること.
そのため,以下のような実行結果になっても間違いではない.

昇順ソートした後出力した時の例は下記の通り.なお,途中経過は省略する.
学籍番号が1の次に10となり,2,3,・・・と続く.
1,2,・・・,10のような数値の昇順にはならない.

昇順ソート実行結果例
(省略)

実行する処理の番号-->3
小さい順に並べかえました

メニュー
1:データ入力
2:データ出力
3:小さい順に整列
4:大きい順に整列
5:データ削除
6:ファイルからデータ読み込み
7:ファイルへのデータ書き込み
8:データ検索
9:終了
実行する処理の番号-->2

1       aaa
10      jjj
2       bbb
3       ccc
4       ddd
5       eee
6       fff
7       ggg
8       hhh
9       iii

(省略)

これについては,
01,10,・・・
または
001,010,・・・
のように,上位桁を0詰めして桁合わせしたり,数値型にすることで,期待値通りになる.

2
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4