#1. 仕様
次の機能を持つ.
- 学籍番号と氏名を入力(登録)する.データの重複は考慮しない.
- 登録済みの学籍番号と氏名を表示する.
- 学籍番号で昇順ソートする.
- 学籍番号で降順ソートする.
- 学籍番号を入力し,完全一致したデータを削除する.
- 学籍番号と氏名のデータを持つテキストファイルを読み込む.今まで登録していたデータは上書きされる.
- 登録されているデータをテキストファイルに書き込む.
- 学籍番号を入力し,完全一致するデータを検索する.
#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詰めして桁合わせしたり,数値型にすることで,期待値通りになる.