C語言學生管理系統(期末作業,超詳細喲,拿走不謝!!!)

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函數

  1. 返回菜單界面以及exit(退出)函數的實現:
    由於每次執行完函數後,都要返回主菜單界面,所以用到一個while函數來控制循環,我們知道,當while的循環條件爲 1(真)時,循環繼續,否則(爲0,就是假時)結束循環,利用這個特性,只需要用一個全局變量(我用的是 t)來控制循環即可,在定義時賦值爲真(1),當執行exit函數(退出函數)時,將其值改爲假(0)即可結束循環,實現退出。此思路後續exit函數的描述部分將不再說明。
  2. 除此之,就是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 控制循環有異曲同工之處。主要分爲兩大步驟來完成:

  1. 判斷新加入的學生學號是否已經存在,這一步用到了一個flag來作爲標誌,如果存在就要重新輸入,讓flag=1,即可讓循環繼續,不存在flag=0,結束循環,進入下一步。
  2. 添加學生信息,這一步就是簡單的輸入賦值,需要注意的是利用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函數是刪除學生信息的函數,調用此函數,可以按照學號刪除學生信息,核心思想:

  1. 找到該學生的位置
  2. 接着把該名學生後面的學生往前移動一位,學生總人數再減去一
  3. 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函數
    在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章