C語言學生管理系統
前言
很多學校都選擇C語言作爲學生編程入門語言,許多老師都會佈置C語言期末大作業,作業題目很多就是學生信息管理系統,以前都是練習小題目,幾十行代碼就能搞定,而完整的寫完這個系統我用了差不多400行代碼。完整寫完這個系統,是對一個學期所學知識的進一步深入瞭解於學習,還能擴充一些課外知識。篇幅很長,收藏起來,慢慢看!
題目詳情
一、學生信息管理程序 基本要求:
1.要求實現學生信息的 使用幫助、添加、查找、刪除、修改、瀏覽、保存、刷新、退出等9個功能,每個功能模塊均能實現從模塊中退出,從而完成一個學生管理系統所需功能。
2.要使用結構體來實現對學生信息的存儲。
3.學生信息需至少包括:學號,姓名,性別,年齡, 成績信息至少包括三科以上成績:C語言、高數、英語…
4.使用文件完成數據的存儲與讀取,要求每次運行某個功能模塊時將數據讀入結構體中,並給用戶提供保存選項,可以將結構體中的數據保存在文件中。
5.系統製作完成後應實現類似下圖所示界面:
入坑全過程
整體思路
可以利用一個switch函數,加上代碼模塊化的思想,一個函數實現一個功能,分別實現題目要求的9個功能,爲了讓代碼更加的模塊化,額外增加一個菜單函數用於輸出菜單界面,一共10個函數。
每個模塊的具體實現方法
結構體的創建
題目要求需要使用結構體來對學生信息進行儲存,所以需要創建一個結構體,同時也要注意結構體中需要包含學生的那些信息。
代碼展示:
struct student
{
char StuID[LEN];//學生學號
char Stuname[LEN];
int Stuage;
char Stusex;
float score[3]; //三科成績
}stu[N];//N是學生人數,具體可以在代碼開頭進行更改
main函數
- 返回菜單界面以及exit(退出)函數的實現:
由於每次執行完函數後,都要返回主菜單界面,所以用到一個while函數來控制循環,我們知道,當while的循環條件爲 1(真)時,循環繼續,否則(爲0,就是假時)結束循環,利用這個特性,只需要用一個全局變量(我用的是 t)來控制循環即可,在定義時賦值爲真(1),當執行exit函數(退出函數)時,將其值改爲假(0)即可結束循環,實現退出。此思路後續exit函數的描述部分將不再說明。 - 除此之,就是switch函數實現菜單函數的選擇執行,詳細請看代碼:
int main()
{
int num;//num是菜單選項
while(t)//t是全局變量,用exit函數改變t的值來控制循環是否繼續
{
menu();//輸出主菜單界面
printf("您好,請輸入菜單編號:");
scanf("%d",&num);
switch(num)
{
case 1: help(); break;
case 2: increase(); break;
case 3: seek(); break;
case 4: de(); break;
case 5: save(); break;
case 6: present(); break;
case 7: modify(); break;
case 8: flush(); break;
case 9: exit(); break;
default:printf("輸入有誤,請重新輸入!");
}
}
menu函數
menu函數就只有一個功能,輸出菜單界面,界面的美化與格式的控制相信都比我強,哈哈,廢話不多說,上代碼:
void menu()
{
printf("\n\n");
printf("*****************************************************\n");
printf("*----------------------duoduo------------------------\n");
printf("* 學生信息管理系統 *\n");
printf("*****************************************************\n");
printf("********************系統功能菜單*********************\n");
printf("---------------------- --------------------------\n");
printf("*****************************************************\n");
printf("** 1、使用幫助 * 2、增加學生信息 **\n");
printf("*****************************************************\n");
printf("** 3、查詢學生信息 * 4、刪除學生信息 **\n");
printf("*****************************************************\n");
printf("** 5、保存當前信息 * 6、顯示當前信息 **\n");
printf("*****************************************************\n");
printf("** 7、修改學生信息 * 8、刷新學生信息 **\n");
printf("*****************************************************\n");
printf("** 9、退出系統 * **\n");
printf("************************* \n");
printf("---------------------- --------------------------\n");
}
help函數
help函數是給用戶的提示,也不做多的解釋,直接上代碼:
void help()
{
printf("\n這是一個學生信息管理系統,爲了幫助您更快的瞭解使用它,請先仔細閱讀以下注意事項:\n");
printf("\n 注意事項: \n ");
printf("\n 1、請根據提示進行操作!\n");
printf("\n 2、初次使用請先選擇增加學生信息!\n");
printf("\n 3、修改或者增加學生信息後切記保存!\n");
printf("\n 4、如果數據有錯誤,請先修改再保存!\n");
printf("\n 5、若您之前使用過,下次進入系統請先刷新學生信息!\n");
printf("\n 6、在添加學生時,用兩個字符代表不同的性別,比如男用‘M’代替,女用‘W’代替!\n");
printf("\n 7、保存或者刷新時,輸入的文件名後綴請使用.txt,比如: stu.txt,系統會在源程序\n");
printf("\n “學生管理系統.exe”的相同目錄建立一個.txt文件來保存學生信息,您可以查看\n");
printf("\n 該文件,但非專業人員不要輕易改動,否則會造成刷新數據異常或刷新失敗!\n");
printf("\n 8、學生信息包括:姓名、學號、性別、年齡、C語言成績、高數成績、英語成績等!\n");
printf("\n 9、使用遇到任何問題請與我們聯繫,郵箱:[email protected]\n");
printf("\n 10、最後感謝您的使用!\n");
system("pause");
}
這裏解釋一下system("pause");
因爲課堂上以及平時做題我們都很少用它,實際上它的作用就是讓系統暫停,方便我們閱讀或者是觀察程序,在執行程序時就是下面這樣的:
很熟悉吧,沒錯,就是請按任意鍵繼續,讓系統暫停。下面還會
多次用到,將不再解釋了喲。
increase函數
increase函數算是該系統的核心函數之一,其函數思想用到了循環的嵌套使用,還有flag的運用也與前面main函數中用 t 控制循環有異曲同工之處。主要分爲兩大步驟來完成:
- 判斷新加入的學生學號是否已經存在,這一步用到了一個flag來作爲標誌,如果存在就要重新輸入,讓flag=1,即可讓循環繼續,不存在flag=0,結束循環,進入下一步。
- 添加學生信息,這一步就是簡單的輸入賦值,需要注意的是利用getchar()函數來處理換行符這個小技巧。
其餘的細節代碼中我已經詳細的解釋,可以看看代碼,
代碼:
void increase()
{
int i=n,j,flag,m=0;//i代表增加學生信息過程中任意時刻的學生人數
printf("\n請輸入待增加的學生人數:\n");
scanf("%d",&m);
if(m>0){
do{
flag=1;
while(flag)
{
flag=0;
printf("請輸入第%d位學生的學號:\n",i+1);//第幾位學生從1開始計數,而stu[]從零開始,需要加1
scanf("%s",stu[i].StuID);
//判斷學號是否重複
for(j=0;j<i;j++){
if(strcmp(stu[i].StuID,stu[j].StuID)==0){
printf("該學號已經存在,請重新輸入!\n");
flag=1;
break;
}
}
}
printf("請輸入第%d位學生姓名:\n",i+1);
scanf("%s",stu[i].Stuname);
printf("請輸入第%d位學生年齡:\n",i+1);
scanf("%d",&stu[i].Stuage);
getchar();//處理上面輸入的換行符,不然系統會把換行符當做一個字符賦值給性別
printf("請輸入第%d位學生性別:\n",i+1);
scanf("%c",&stu[i].Stusex);
printf("請輸入第%d位學生的C語言成績:\n",i+1);
scanf("%f",&stu[i].score[0]);
printf("請輸入第%d位學生的高數成績:\n",i+1);
scanf("%f",&stu[i].score[1]);
printf("請輸入第%d位學生的大學英語成績:\n",i+1);
scanf("%f",&stu[i].score[2]);
i++;
}while(i<n+m);//只要當前學生人數還沒到達添加後的總人數,就得繼續添加
}
n+=m;// 添加完成,系統人數n的值也要增加
printf("添加完成!!!\n");
system("pause");
}
seek 函數
seek查找函數,調用此函數,可以實現按姓名或者學號查找某一學生的信息。其核心思路也是用到了switch函數輸入子菜單的方式來實現的,同時又用flag作爲標誌來判斷是否已經查找到該學生信息。考慮到需要查找學生信息的次數不止一次,就需要用到while函數來實現循環,可以看到循環條件是1(永遠爲真),有人可能會說:那這不就是死循環嗎?實際上除了讓循環條件爲假,還可以用其它方式結束循環,比如用return語句,代碼後面介紹。
代碼:
void seek()
{
int i,num,flag;
char s1[LEN+1];
printf("*****************************\n");
printf("**-------1.按學號查詢------**\n");
printf("**-------2.按姓名查詢------**\n");
printf("**-------3.退出本菜單------**\n");
printf("*****************************\n");
while(1)
{
flag=0;
printf("請輸入子菜單:");
scanf("%d",&num);
switch(num)
{
case 1:
printf("請輸入需要查找學生的學號:\n");
scanf("%s",s1);
for(i=0;i<n;i++)
{
if(strcmp(stu[i].StuID,s1)==0)
{
flag=1;
printf("學號\t\t姓名\t\t性別\t\t年齡\t\tC語言\t\t高數\t\t英語\n");
printf("%s\t\t%s\t\t%c\t\t%d\t\t%.2f\t\t%.2f\t\t%.2f\n",stu[i].StuID,stu[i].Stuname,stu[i].Stusex,stu[i].Stuage,stu[i].score[0],stu[i].score[1],stu[i].score[2]);
}
}break;
case 2:
printf("請輸入需要查找學生的姓名:\n");
scanf("%s",s1);
for(i=0;i<n;i++)
{
if(strcmp(stu[i].Stuname,s1)==0)
{
flag=1;
printf("學號\t\t姓名\t\t性別\t\t年齡\t\tC語言\t\t高數\t\t英語\n");
printf("%s\t\t%s\t\t%c\t\t%d\t\t%.2f\t\t%.2f\t\t%.2f\n",stu[i].StuID,stu[i].Stuname,stu[i].Stusex,stu[i].Stuage,stu[i].score[0],stu[i].score[1],stu[i].score[2]);
}
}break;
case 3: return;
default: printf("請在1--3之間輸入\n");
}
if(flag==0)
printf("找不到該學生!\n請重新輸入!");
}
}
這裏解釋一下子菜單三:
可以看到,後面我直接用了一個return語句來實現退出,是因爲return函數具有把程序流程從被調用函數轉向主函數的作用,一旦遇到return就會立即結束正在執行的函數,平時用的return語句後面都是跟參數返回值的,實際上也可以不跟參數,僅僅代表結束此函數。
後面的修改學生信息的modify函數也用到這種思想,將不再解釋,嘿嘿。
de函數
de函數是刪除學生信息的函數,調用此函數,可以按照學號刪除學生信息,核心思想:
- 找到該學生的位置
- 接着把該名學生後面的學生往前移動一位,學生總人數再減去一
- flag的應用,用於判斷是否已經找到該學號的學生,方便結束循環,以及給用戶的提示。
代碼:
void de()
{
int i,j,flag;
char s1[LEN];
printf("請輸入需要刪除的學生學號:\n");
scanf("%s",s1);
flag=0;
for(i=0;i<n;i++)
{
if(strcmp(s1,stu[i].StuID)==0)
{
flag=1;
for(j=i;j<n-1;j++)
{
stu[j]=stu[j+1];//直接把後面的學生都往前移動一位
}
}
if(flag==1) break;//說明已經找到了需要刪除的學生,結束循環
}
if(0==flag)
{
printf("該學號不存在!!!\n");
}
if(1==flag)
{
printf("刪除成功\n");
n--;
}
system("pause");
}
save函數
save有保存的意思,哈哈,平時用的ctrl+s應該就是它,我也是寫了這個才知道的,如果你和我一樣,那就記住了哦!扯遠了,進入正題。
一旦調用save函數,就只有一個作用,就是把程序中結構體中現有的信息輸出到文件保存起來,該部分算是我寫這個程序的難點之一,因爲關於文件的知識需要自己看書查資料,先看代碼再解釋其中的難點。
代碼:
void save()//把學生信息保存到文件
{
int i;
FILE *fp;
char filename[LEN+1];
printf("請輸入要保存的文件名:\n");
scanf("%s",filename);
if((fp=fopen(filename,"w"))==NULL)
{
printf("打開文件失敗!\n");
exit(0);
}
for(i=0;i<n;i++)
if(fwrite(&stu[i],sizeof(struct student),1,fp)!=1)
printf("保存失敗!!\n");
printf("保存成功!!!\n");
fclose(fp);
system("pause");
}
這裏需要解釋的主要有兩個部分:
第一部分:
if((fp=fopen(filename,"w"))==NULL)
{
printf("打開文件失敗!\n");
exit(0);
}
- fopen是打開文件的函數,它的形式參數中的filename是需要我們提前輸入的一個字符型數組,代表文件名,"w"是指以只寫(只寫就是隻向文件輸出信息,不讀取)的方式打開文件。
- fopen函數首先會在.exe源程序的相同目錄查找之前輸入的文件名,如果不存在該文件名,就會新建一個;如果存在,就會刪除原文件,重新建立一個新的文件。
- fopen函數的返回值是指向該文件的指針的指針,此處用使fp指向它的返回值。
第二部分:
for(i=0;i<n;i++)
if(fwrite(&stu[i],sizeof(struct student),1,fp)!=1)
printf("保存失敗!!\n");
printf("保存成功!!!\n");
for循環不多作解釋,重點說一下fwrite函數與後面flush函數中需要用到的fread函數,後面flush函數用到將不在解釋。
其一般調用形式爲:
fwrite(buffer,size,count,fp); 將buffer中的數據每次輸出"size x count "字節長度的數據到fp所指的文件中。
fread(buffer,size,count,fp); 從fp所指的文件中每次讀入"size x count "字節長度的數據到buffer對應的地址中。
下面依次解釋每個參數:
- buffer:是一個地址,是用來存放從文件讀入的數據(對fread函數來說)或者輸出到文件的數據的來源(對fwrite函數來說)。
- size:要讀寫的字節數
- count:要讀寫多少個數據項(每個數據項長度爲size)。
- fp:FILE類型的指針。
對於兩個函數來說,只要其成功執行,就會返回count的值,程序中爲1。
present函數
一旦調用present函數,就顯示當前所有的學生信息,用簡單的for循環輸出即可,需要注意結構體中的數據類型不要弄錯了,同時注意控制格式,"\t" 就是tab健的那個空格,這裏用兩個 “\t” 是爲了解決學生姓名或者學號太長而引起的上下格式不對應的問題.
代碼:
void present()
{
int i;
if(n==0)
{
printf("您好,現在沒有學生信息,請先增加學生信息或者刷新再來試試!\n");
}
else
{
printf("現在共有%d名學生:\n",n);
printf("學號\t\t姓名\t\t性別\t\t年齡\t\tC語言\t\t高數\t\t英語\n");
for(i=0;i<n;i++)
{
printf("%s\t\t%s\t\t%c\t\t%d\t\t%.2f\t\t%.2f\t\t%.2f\n",stu[i].StuID,stu[i].Stuname,stu[i].Stusex,stu[i].Stuage,stu[i].score[0],stu[i].score[1],stu[i].score[2]);
}
}
system("pause");
}
如果只用一個 “\t” ,當名字或者學號過長時,就會出現下面這種情況:
可以發現,由於姓名太長,性別的位置已經被姓名佔據了,後面就會出現錯位的情況。
modify函數
調用該函數即可修改任意學生的任意信息,考慮到可能需要修改學生的多向信息,所以用到while函數,且循環條件永遠爲真,相同的思路前面seek函數中已經說過,不再解釋。也同樣用到flag作爲是否找到學生的標誌,方便於沒有找到的情況下重新輸入姓名,以及對用戶的提示。核心思路還是switch語句,子菜單實現修改,具體請看代碼:
void modify()
{
int i,flag;
char ID[LEN],name[LEN],sex;
int age;
float score;//以上命名顧名思義,不作解釋
printf("請輸入需要修改的學生姓名:\n");
getchar();
gets(name);
while(1)
{
flag=0;
for(i=0;i<n;i++)
{
if(strcmp(name,stu[i].Stuname)==0)
{
flag=1;
int num;//用於switch函數的子菜單
printf("***************************************************\n");
printf("*----1.修改學號-------- - -----2.修改性別-------*\n");
printf("*----3.修改年齡-------- - -----4.修改C語言成績--*\n");
printf("*----5.修改高數成績---- - -----6.修改英語成績---*\n");
printf("*-------------------7.退出本菜單------------------*\n");
printf("***************************************************\n\n");
printf("請輸入子菜單:");
scanf("%d",&num);
switch(num)
{
case 1:
printf("請輸入新的學號:\n");
getchar();
gets(ID);
strcpy(stu[i].StuID,ID);break;
case 2:
getchar();
printf("請輸入新的性別:\n");
scanf("%c",&sex);
stu[i].Stusex=sex;break;
case 3:
printf("請輸入新的年齡:\n");
scanf("%d",&age);
stu[i].Stuage=age;break;
case 4:
printf("請輸入新的C語言成績:\n");
scanf("%f",&score);
stu[i].score[0]=score;break;
case 5:
printf("請輸入新的高數成績:\n");
scanf("%f",&score);
stu[i].score[1]=score;break;
case 6:
printf("請輸入新的英語成績:\n");
scanf("%f",&score);
stu[i].score[2]=score;break;
case 7:
return;break;
default:
printf("請在1--7之間選擇!\n");
}
if(num>0&&num<7)
printf("修改成功,記得保存喲!!!\n");
break;//找到學生,結束循環;
}
}
if(flag==0)
{
printf("沒有找到該學生,請重新輸入需要修改信息的學生姓名:\n");
gets(name);
}
}
system("pause");
}
flush函數
調用flush函數,即可將之前文件中的數據讀入結構體中來進行操作。需要注意的兩個地方,一個是fread() 函數的使用,前面save函數已經介紹過,不再解釋;還有就是
if((fp=fopen(filename,"r"))==NULL)//打開文件
中的 “r” 代表以只讀(只從文件讀取數據)的方式打開文件。
代碼:
void flush()
{
int i,k=0;//k代表刷新過程中學生人數
FILE *fp;
char filename[LEN+1];
printf("請輸入需要刷新的文件名:\n");
getchar();
gets(filename);
if((fp=fopen(filename,"r"))==NULL)//打開文件
{
printf("打開文件失敗!\n");
exit(0);
}
for(i=0;i<N;i++)//N是最大的學生人數,可在程序開頭進行更改
{
if(fread(&stu[i],sizeof(struct student),1,fp)==1)
k++;//記錄學生人數
}
n=k;// 把k的值給n
if(k==0)
printf("刷新失敗!!!\n");
else
printf("刷新成功!!!\n");
fclose(fp);
system("pause");
}
exit函數
main函數中已經簡單介紹過,就是通過改變main函數中的循環條件 “t” 的值來實現程序的結束與否。
代碼:
void exit()
{
int h;//控制是否確認退出
printf("即將退出,確認請按1,取消請按0\n");
scanf("%d",&h);
if(h==1)
{
t=0;//t是main函數中while函數是否繼續執行的控制條件,是一個全局變量,程序開頭已經定義並且賦值位 1
printf("成功退出,感謝使用!\n");
}
if(h==0)
{
printf("退出已取消!\n");
system("pause");
}
}
整個程序代碼
#include<stdio.h>
#include<stdlib.h>
#include<string.h>//需要用到strcmp函數
#define LEN 15//姓名和學號的最大字符數
#define N 50//最大學生人數
int n=0,t=1;//n代表當前學生人數,t用來控制整個程序的執行,以及程序的退出;
//函數聲明
void menu();//主菜單函數
void help();//使用幫助
void increase();//增加學生信息
void seek();//查找學生信息
void de();//刪除學生信息
void save();//保存文件
void present();//顯示當前信息
void modify();//修改學生信息
void flush();//刷新學生成績
void exit();//退出函數
struct student
{
char StuID[LEN];//學生學號
char Stuname[LEN];
int Stuage;
char Stusex;
float score[3]; //各科成績
}stu[N];
int main()
{
int num;//num是菜單選項
while(t)//t是全局變量,用exit函數來控制循環是否繼續
{
menu();//輸出主菜單界面
printf("您好,請輸入菜單編號:");
scanf("%d",&num);
switch(num)
{
case 1: help(); break;
case 2: increase(); break;
case 3: seek(); break;
case 4: de(); break;
case 5: save(); break;
case 6: present(); break;
case 7: modify(); break;
case 8: flush(); break;
case 9: exit(); break;
default:printf("輸入有誤,請重新輸入!");
}
}
system("pause");
return 0;
}
void menu()
{
printf("\n\n");
printf("*****************************************************\n");
printf("*----------------------duoduo------------------------\n");
printf("* 學生信息管理系統 *\n");
printf("*****************************************************\n");
printf("********************系統功能菜單*********************\n");
printf("---------------------- --------------------------\n");
printf("*****************************************************\n");
printf("** 1、使用幫助 * 2、增加學生信息 **\n");
printf("*****************************************************\n");
printf("** 3、查詢學生信息 * 4、刪除學生信息 **\n");
printf("*****************************************************\n");
printf("** 5、保存當前信息 * 6、顯示當前信息 **\n");
printf("*****************************************************\n");
printf("** 7、修改學生信息 * 8、刷新學生信息 **\n");
printf("*****************************************************\n");
printf("** 9、退出系統 * **\n");
printf("************************* \n");
printf("---------------------- --------------------------\n");
}
void help()
{
printf("\n這是一個學生信息管理系統,爲了幫助您更快的瞭解使用它,請先仔細閱讀以下注意事項:\n");
printf("\n 注意事項: \n ");
printf("\n 1、請根據提示進行操作!\n");
printf("\n 2、初次使用請先選擇增加學生信息!\n");
printf("\n 3、修改或者增加學生信息後切記保存!\n");
printf("\n 4、如果數據有錯誤,請先修改再保存!\n");
printf("\n 5、若您之前使用過,下次進入系統請先刷新學生信息!\n");
printf("\n 6、在添加學生時,用兩個字符代表不同的性別,比如男用‘M’代替,女用‘W’代替!\n");
printf("\n 7、保存或者刷新時,輸入的文件名後綴請使用.txt,比如: stu.txt,系統會在源程序\n");
printf("\n “學生管理系統.exe”的相同目錄建立一個.txt文件來保存學生信息,您可以查看\n");
printf("\n 該文件,但非專業人員不要輕易改動,否則會造成刷新數據異常或刷新失敗!\n");
printf("\n 8、學生信息包括:姓名、學號、性別、年齡、C語言成績、高數成績、英語成績等!\n");
printf("\n 9、使用遇到任何問題請與我們聯繫,郵箱:[email protected]\n");
printf("\n 10、最後感謝您的使用!\n");
system("pause");
}
void increase()
{
int i=n,j,flag,m=0;//i代表增加學生信息過程中任意時刻的學生人數
printf("\n請輸入待增加的學生人數:\n");
scanf("%d",&m);
if(m>0){
do{
flag=1;
while(flag)
{
flag=0;
printf("請輸入第%d位學生的學號:\n",i+1);//第幾位學生從1開始計數,而stu[]從零開始,需要加1
scanf("%s",stu[i].StuID);
//判斷學號是否重複
for(j=0;j<i;j++){
if(strcmp(stu[i].StuID,stu[j].StuID)==0){
printf("該學號已經存在,請重新輸入!\n");
flag=1;
break;
}
}
}
printf("請輸入第%d位學生姓名:\n",i+1);
scanf("%s",stu[i].Stuname);
printf("請輸入第%d位學生年齡:\n",i+1);
scanf("%d",&stu[i].Stuage);
getchar();//處理上面輸入的換行符,不然系統會把換行符當做一個字符賦值給性別
printf("請輸入第%d位學生性別:\n",i+1);
scanf("%c",&stu[i].Stusex);
printf("請輸入第%d位學生的C語言成績:\n",i+1);
scanf("%f",&stu[i].score[0]);
printf("請輸入第%d位學生的高數成績:\n",i+1);
scanf("%f",&stu[i].score[1]);
printf("請輸入第%d位學生的大學英語成績:\n",i+1);
scanf("%f",&stu[i].score[2]);
i++;
}while(i<n+m);//只要當前學生人數還沒到達添加後的總人數,就得繼續添加
}
n+=m;// 添加完成,系統人數n的值也要增加
printf("添加完成!!!\n");
system("pause");
}
void seek()
{
int i,num,flag;
char s1[LEN+1];
printf("*****************************\n");
printf("**-------1.按學號查詢------**\n");
printf("**-------2.按姓名查詢------**\n");
printf("**-------3.退出本菜單------**\n");
printf("*****************************\n");
while(1)
{
flag=0;
printf("請輸入子菜單:");
scanf("%d",&num);
switch(num)
{
case 1:
printf("請輸入需要查找學生的學號:\n");
scanf("%s",s1);
for(i=0;i<n;i++)
{
if(strcmp(stu[i].StuID,s1)==0)
{
flag=1;
printf("學號\t\t姓名\t\t性別\t\t年齡\t\tC語言\t\t高數\t\t英語\n");
printf("%s\t\t%s\t\t%c\t\t%d\t\t%.2f\t\t%.2f\t\t%.2f\n",stu[i].StuID,stu[i].Stuname,stu[i].Stusex,stu[i].Stuage,stu[i].score[0],stu[i].score[1],stu[i].score[2]);
}
}break;
case 2:
printf("請輸入需要查找學生的姓名:\n");
scanf("%s",s1);
for(i=0;i<n;i++)
{
if(strcmp(stu[i].Stuname,s1)==0)
{
flag=1;
printf("學號\t\t姓名\t\t性別\t\t年齡\t\tC語言\t\t高數\t\t英語\n");
printf("%s\t\t%s\t\t%c\t\t%d\t\t%.2f\t\t%.2f\t\t%.2f\n",stu[i].StuID,stu[i].Stuname,stu[i].Stusex,stu[i].Stuage,stu[i].score[0],stu[i].score[1],stu[i].score[2]);
}
}break;
case 3: return;
default: printf("請在1--3之間輸入\n");
}
if(flag==0)
printf("找不到該學生!\n請重新輸入!");
}
}
void de()
{
int i,j,flag;
char s1[LEN];
printf("請輸入需要刪除的學生學號:\n");
scanf("%s",s1);
flag=0;
for(i=0;i<n;i++)
{
if(strcmp(s1,stu[i].StuID)==0)
{
flag=1;
for(j=i;j<n-1;j++)
{
stu[j]=stu[j+1];//直接把後面的學生都往前移動一位
}
}
if(flag==1) break;//說明已經找到了需要刪除的學生,結束循環
}
if(0==flag)
{
printf("該學號不存在!!!\n");
}
if(1==flag)
{
printf("刪除成功\n");
n--;
}
system("pause");
}
void save()//把學生信息保存到文件
{
int i;
FILE *fp;
char filename[LEN+1];
printf("請輸入要保存的文件名:\n");
scanf("%s",filename);
if((fp=fopen(filename,"w"))==NULL)
{
printf("打開文件失敗!\n");
exit(0);
}
for(i=0;i<n;i++)
if(fwrite(&stu[i],sizeof(struct student),1,fp)!=1)
printf("保存失敗!!\n");
printf("保存成功!!!\n");
fclose(fp);
system("pause");
}
void present()
{
int i;
if(n==0)
{
printf("您好,現在沒有學生信息,請先增加學生信息或者刷新再來試試!\n");
}
else
{
printf("現在共有%d名學生:\n",n);
printf("學號\t\t姓名\t\t性別\t\t年齡\t\tC語言\t\t高數\t\t英語\n");
for(i=0;i<n;i++)
{
printf("%s\t\t%s\t\t%c\t\t%d\t\t%.2f\t\t%.2f\t\t%.2f\n",stu[i].StuID,stu[i].Stuname,stu[i].Stusex,stu[i].Stuage,stu[i].score[0],stu[i].score[1],stu[i].score[2]);
}
}
system("pause");
}
void modify()
{
int i,flag;
char ID[LEN],name[LEN],sex;
int age;
float score;
printf("請輸入需要修改的學生姓名:\n");
getchar();
gets(name);
while(1)
{
flag=0;
for(i=0;i<n;i++)
{
if(strcmp(name,stu[i].Stuname)==0)
{
flag=1;
int num;//用於switch函數的子菜單
printf("***************************************************\n");
printf("*----1.修改學號-------- - -----2.修改性別-------*\n");
printf("*----3.修改年齡-------- - -----4.修改C語言成績--*\n");
printf("*----5.修改高數成績---- - -----6.修改英語成績---*\n");
printf("*-------------------7.退出本菜單------------------*\n");
printf("***************************************************\n\n");
printf("請輸入子菜單:");
scanf("%d",&num);
switch(num)
{
case 1:
printf("請輸入新的學號:\n");
getchar();
gets(ID);
strcpy(stu[i].StuID,ID);break;
case 2:
getchar();
printf("請輸入新的性別:\n");
scanf("%c",&sex);
stu[i].Stusex=sex;break;
case 3:
printf("請輸入新的年齡:\n");
scanf("%d",&age);
stu[i].Stuage=age;break;
case 4:
printf("請輸入新的C語言成績:\n");
scanf("%f",&score);
stu[i].score[0]=score;break;
case 5:
printf("請輸入新的高數成績:\n");
scanf("%f",&score);
stu[i].score[1]=score;break;
case 6:
printf("請輸入新的英語成績:\n");
scanf("%f",&score);
stu[i].score[2]=score;break;
case 7:
return;break;
default:
printf("請在1--7之間選擇!\n");
}
if(num>0&&num<7)
printf("修改成功,記得保存喲!!!\n");
break;//找到學生,結束循環;
}
}
if(flag==0)
{
printf("沒有找到該學生,請重新輸入需要修改信息的學生姓名:\n");
gets(name);
}
}
system("pause");
}
void flush()
{
int i,k=0;//k代表刷新過程中學生人數
FILE *fp;
char filename[LEN+1];
printf("請輸入需要刷新的文件名:\n");
getchar();
gets(filename);
if((fp=fopen(filename,"r"))==NULL)//打開文件
{
printf("打開文件失敗!\n");
exit(0);
}
for(i=0;i<N;i++)//N是最大的學生人數,可在程序開頭進行更改
{
if(fread(&stu[i],sizeof(struct student),1,fp)==1)
k++;//記錄學生人數
}
n=k;// 把k的值給n
if(k==0)
printf("刷新失敗!!!\n");
else
printf("刷新成功!!!\n");
fclose(fp);
system("pause");
}
void exit()
{
int h;//控制是否確認退出
printf("即將退出,確認請按1,取消請按0\n");
scanf("%d",&h);
if(h==1)
{
t=0;//t是main函數中while函數是否繼續執行的控制條件,是一個全局變量,程序開頭已經定義並且賦值位 1
printf("成功退出,感謝使用!\n");
}
if(h==0)
{
printf("退出已取消!\n");
system("pause");
}
}
運行結果展示
-
menu函數
-
help函數
-
increase函數
-
seek函數
-
de函數
-
save函數
-
present函數
-
modify函數
-
flush函數
-
exit函數