學生管理系統

NorthSouth_Cat發表於2018-08-28

C++語言實現 學生管理系統

首先,讓我分部分介紹本學生管理系統
本系統分為兩個大板塊,分別是學生版和教師版,學生版又分出三個具體功能,教師版分為七個功能,讓我依次來介紹它們吧!

(一)學生版

1.學生版開始選單

int PrintStudentMenu(void)//學生版選單
{
	printf("\n\n\t━━━━━━━━━━━━━━━━━━━━【歡迎使用學生管理系統|學生版】━━━━━━━━━━━━━━━━━━━━━━━\n");
	printf("\t|選項			功能						*|\n");
	printf("\t|*									*|\n");
	printf("\t|1 			查詢學生資訊					*|\n");
	printf("\t|2 			列出所有的學生資訊 				*|\n");
	printf("\t|3 			回到標題介面					*|\n");
	printf("\t|*									*|\n");
	printf("\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
}

2.查詢學生資訊

STU *SearchNode(STU *head, char keyword[])//通過name或num查詢學生結構體
{
	STU *pr = head;
	if (pr == NULL)//連結串列為空 
	{
		return NULL;
	}
	while (strcmp(pr->name, keyword) && strcmp(pr->num, keyword))//遍歷 
	{
		pr = pr->next;
		if(pr == NULL)
		{
			return NULL; 
		}
	}
	return pr;//返回找到的指向節點的指標 
}

3.列出所有的學生資訊

void PrintNode(STU *head)//在螢幕上列印全部學生資訊
{
	STU *p = head;
	
	if (p == NULL)
	{
		printf("\n\t列表中無資料\n\n"); 
		return;
	}
	printf("\n\t|姓名\t     |學號\t\t|總分\n"); 
	while (p != NULL)
	{
		printf("\t|\t     |\t\t\t|\n");
		printf("\t|%-12s|%-18s|%-12.2f\n", 
		p->name, p->num, p->score);
		
		p = p->next;
	}
	printf("\n"); 
}

4.回到標題介面

(二)教師版

1.教師版開始選單

int PrintTeacherMenu(void)//教師版選單
{
	printf("\n\n\t━━━━━━━━━━━━━━━━━━━━【歡迎使用學生管理系統|教師版】━━━━━━━━━━━━━━━━━━━━━━ \n");
	printf("\t|選項			功能						*|\n");
	printf("\t|*									*|\n");
	printf("\t|1 			輸入學生資訊					*|\n");
	printf("\t|2 			刪除學生資訊					*|\n");
	printf("\t|3 			查詢學生資訊					*|\n");
	printf("\t|4 			排序學生資訊					*|\n");
	printf("\t|5 			列出所有的學生資訊 				*|\n");
	printf("\t|6 			儲存並回到標題介面				*|\n");
	printf("\t|7 			幫助						*|\n");
	printf("\t|*									*|\n");
	printf("\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
}

2.輸入學生資訊

void GetInput(STU *p)//輸入學生資訊
{
	char num[18];													 
	char name[20];													 
	float score;													 
	char words[20];												 
	
	do
	{
		printf("\t請輸入學生姓名:");	
		gets(name);	 	
	}while (!JudgementName(name));	
	strcpy(p->name, name); 
	do
	{
		printf("\t請輸入學生學號:");	
		gets(num);
	}while (isnumber(num)==0);
	strcpy(p->num, num);
	
	do
	{
		printf("\t請輸入學生成績:");	
		gets(words);
	}while (!JudgementScore(words)); 
	score = atof(words);//將字串轉化為浮點數 
	p->score = score;
}

3.刪除學生資訊

int DeleteSpecNode(STU **head, char str[])//刪除節點					
{
	STU *pr = *head, *p = *head;
	int flag = 0; 
	if (p == NULL)//連結串列內無內容 
	{
		return 0; 
	}
	while (p != NULL)//遍歷連結串列 
	{
		if(!strcmp(p->num, str))//找到相應學生資訊 
		{
			flag = 1;
			break;//停止遍歷,進行刪除操作 
		}
		pr = p;
		p = p->next;
	}
	
	if (flag)
	{
		if(p == *head)
		{
			*head = p->next;
			free(p);
		}
		else													
		{
			pr->next = p->next;
			free(p);
		}
	}
	else//如果沒有找到,則返回1 
	{
		return 0; 
	} 
	
	return 1;
	
}

4.查詢學生資訊(見學生版部分)
5.排序學生資訊

STU *SortNode(STU *head, int mode)//給結構體連結串列排序
{
	STU *pr,*pt, temp;
	pr = head;
	pt = NULL; 
	bool condition;//判斷條件 
	
	if(pr == NULL || pr->next == NULL)
	{
		return head;
	}
	
	while(pr != pt)
	{
		while(pr->next != pt)//每輪會把最大或最小的數排到最後 
		{
			switch (mode)
			{
				case 1:// "1"表示按降序降序
					condition = pr->score < pr->next->score;
					break;	
				case 2:// "2"表示按學號排序 
					condition = (strcmp(pr->num, pr->next->num) > 0);
					break;
				case 3:// "3"表示按姓名排序 
					condition = (strcmp(pr->name, pr->next->name) > 0);
					break;
				default://如果mode不正確,則直接返回原連結串列,不進行排序 
					return head;
			} 
			
			if(condition) 
			{
				temp = *(pr->next);
											 
				strcpy(pr->next->name, pr->name);
				strcpy(pr->next->num, pr->num);
				pr->next->score = pr->score;
				
				strcpy(pr->name, temp.name);
				strcpy(pr->num, temp.num);
				pr->score = temp.score;
			}
			pr = pr->next;
		}
		pt = pr;
		pr = head;
	}
	return head;
}

6.列出所有的學生資訊(見學生版部分)
7.儲存並回到標題介面

int WriteToFile(char path[], STU *head)//將連結串列存入檔案
{
	FILE *fp;
	STU *p = head;
	fp = fopen(path, "wb");
	if (fp == NULL)
	{
		printf("\n檔案開啟失敗!\n\n");
		return 0;
	}
	if (head == NULL)
	{ 
		printf("當前沒有學生資訊可寫入!\n");
		return 0;
	}
	while (p != NULL)
	{
		fwrite(p, sizeof(STU), 1, fp);	
		p = p->next;
	}
	
	fclose(fp);
	return 1;
}

8.幫助

char code2[3];
printf("\n\n\t━━━━━━━━━━━━━━━━━━━ 【請問您遇到了哪些問題?】━━━━━━━━━━━━━━━━━━━━━━━━━━━ \n");
printf("\t|選項			功能						*|\n");
printf("\t|*									*|\n");
printf("\t|1			無法查詢學生資訊				*|\n");
//printf("\t|2*			 				*|\n");
//printf("\t|3*							*|\n");
printf("\t|*									*|\n");
printf("\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
printf("\t如遇到更多問題,歡迎聯絡QQ:1872557359反饋\n\n"); 
				
do
	{
		printf("\t請輸入幫助選項程式碼:"); 
		gets(code2);
	}while(!JudgementOptions2(code2));
				
if(!strcmp(code2, "1"))
	{
		printf("\t請確認:\n\t1.已錄入學生資訊\n\t2.本次未錄入資訊但上次開啟程式時已錄入資訊\n\t3.若上次開啟程式後錄入了資訊,但這次仍然無法查詢,則說明上次退出時未選擇[儲存並退出]\n\n");
	}
printf("\n\t按Enter鍵繼續!");
getchar();

(三)主函式及初始選單

1.初始選單

int PrintStartMenu(void)//開始選單
{
	printf("\n\n\t━━━━━━━━━━━━━━━━━━━━【歡迎使用學生管理系統|請選擇模式】━━━━━━━━━━━━━━━━━━ \n");
	printf("\t|選項			功能						*|\n");
	printf("\t|*									*|\n");
	printf("\t|1 			進入學生模式					*|\n");
	printf("\t|2 			進入教師模式	 				*|\n");
	printf("\t|3 			退出管理系統	 				*|\n");
	printf("\t|*									*|\n");
	printf("\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
}

2.主函式

(四)最終成果

最後全覽一下本系統的程式碼,看看最終的成果:

#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h> 

typedef struct students//定義學生結構體 
{
	char name[20];//姓名 
	char num[18];//學號 
	float score;//成績 
	struct students *next; 			
}STU;

int PrintStartMenu(void);//開始選單 
int PrintOverMenu(void);//退出選單
int PrintStudentMenu(void);//學生版選單 
int PrintTeacherMenu(void);//教師版選單 
int JudgementOptions(char words[]);//判斷選項是否合法1,2 
int JudgementOptions2(char words[]);//判斷選項是否合法1
int JudgementOptionsT(char words[]);//判斷選項是否合法1,2,3,4,5,6,7
int JudgementOptionsS(char words[]);//判斷選項是否合法1,2,3
int isnumber(char a[]);//判斷學號是否全為數字 
STU *AppendNode(STU *head);//增加一個新的節點
void GetInput(STU *p);//輸入學生資訊
void PrintNode(STU *head);//在螢幕上列印全部學生資訊
int WriteToFile(char path[], STU *head);//將連結串列存入檔案
STU *ReadFromFile(char path[], STU *head);//從檔案中讀取
STU *SearchNode(STU *head, char keyword[]);//通過name或num查詢學生結構體 
STU *SortNode(STU *head, int mode);//連結串列排序 
int JudgementScore(char words[]);//判斷輸入分數是否合法
void ReleaseList(STU *head);//釋放連結串列 
int JudgementName(char name[]);//判斷輸入姓名是否合法
int DeleteSpecNode(STU **head, char str[]); //刪除節點

int main()
{
	char code[2];
	
	system("color F2");//設定控制檯背景顏色和前景色
	start:
	PrintStartMenu(); 
	
	do
	{
		printf("\t請輸入操作選項:"); 
		gets(code);
	}while (!JudgementOptionsS(code));
	
	if(!strcmp(code, "1"))
	{
		system("cls");//清屏
		char code[2];												 
		STU *head = NULL;//定義頭指標指向空
		PrintStudentMenu();
		
		int KEY = 0;//做標記,方便之後讀取時確定是否錄入過
		
		while(1)
		{
			int miao = 1;
			//printf("\n\t正在讀取學生資訊......");
			if(miao == 1)//操作前載入一次學生資訊
			{ 
				char path[128] = {"students.bin"};
				STU *temp; 
				if (KEY == 1)//已經讀取過了,則直接進入選項階段 
				{
					goto nextone1;
				} 
				temp = ReadFromFile(path, head);//讀取連結串列並儲存在temp中
				if (temp == NULL)//如果讀取到的為空,則直接進入選項階段 
				{
					goto nextone1;
				} 
				head = temp;//將temp置為頭節點,方便之後使用 
				KEY = 1; //讀取完成,將標記設為1;防止重複讀取 
			}
			
			nextone1:
			
			do
			{
				system("cls");
				PrintStudentMenu();
				printf("\t請輸入操作程式碼:"); 
				gets(code);
			}while(!JudgementOptionsS(code));
			
			if (!strcmp(code, "1"))
			{
				char keyword[28];
				STU *p;//宣告結構體指標p 
				printf("\t請輸入要查詢的姓名或學號:");
				gets(keyword); 
				p = SearchNode(head, keyword);//查詢學生資訊,並賦值給p 
				if (p == NULL)//返回值為空,連結串列中沒有找到相應的學生資訊結構體
				{
					printf("\n\t未找到該學生資訊!\n\n");
				}
				else//返回值不為空,則輸出該結構體內學生資訊 
				{
					printf("\n\t%-12s學號:%-18s總分:%-12.2f\n\n", p->name, p->num, p->score);
				}				
				printf("\n\t按Enter鍵繼續!");
				getchar();
			}
			
			if (!strcmp(code, "2"))
			{
				PrintNode(head);//在螢幕上列印全部學生資訊
				printf("\n\t按Enter鍵繼續!");
				getchar();
			}
			
			if (!strcmp(code, "3"))
			{
				ReleaseList(head);
				system("cls");//清空螢幕
				goto start;
			}
		}
	}
	
	if(!strcmp(code, "2"))
	{
		system("cls");//清屏
		char code[6];												 
		STU *head = NULL;//定義頭指標											
		int KEY = 0;	//做標記,方便之後讀取時確定是否錄入過											  
		PrintTeacherMenu();
		
		while(1)
		{
			int miao = 1;
			//printf("\n\t正在讀取學生資訊......");
			if(miao == 1)//操作前載入一次學生資訊
			{ 
				char path[128] = {"students.bin"};//檔名(包括檔案路徑)
				STU *temp; 
				if (KEY == 1)//已經讀取過了,則直接進入選項階段
				{
					goto nextone2;
				} 
				temp = ReadFromFile(path, head);//讀取連結串列並儲存在temp中
				if (temp == NULL)//如果讀取到的為空,則直接進入選項階段
				{
					goto nextone2;
				} 
				head = temp;//將temp置為頭節點,方便之後使用
				KEY = 1;//讀取完成,將標記設為1;防止重複讀取 
			}
			 
			nextone2:
			 
			do
			{
				system("cls");
				PrintTeacherMenu();
				printf("\t請輸入操作程式碼:"); 
				gets(code);
			}while(!JudgementOptionsT(code));
			
			if(!strcmp(code, "1"))				
			{
				char choice[2];
			
				do
				{
					head = AppendNode(head);
					printf("\n\t是否繼續加入學生資訊?(是則輸入大寫字母Y,否則輸入大寫字母N):");
					gets(choice);
				}while (!strcmp(choice, "Y"));
				printf("\n\t按Enter鍵繼續!");
				getchar();
			}
			
			if(!strcmp(code, "2"))
			{
				char str[20];
				int result;//儲存執行後的結果					 
			
				printf("\n\t請輸入學生的學號:");
				gets(str);
				result = DeleteSpecNode(&head, str);
				if (result == 0)
				{
					printf("\n\t未找到該學號!\n\n");
				}
				else
				{
					printf("\n\t刪除成功!\n\n");
				}
				printf("\n\t按Enter鍵繼續!");
				getchar();
			}
			
			if(!strcmp(code, "3"))
			{
				char keyword[28];
				STU *p;
				printf("\t請輸入要查詢的姓名或學號:");
				gets(keyword); 
				p = SearchNode(head, keyword);
				if (p == NULL)
				{
					printf("\n\t未找到該學生資訊!\n\n");
				}
				else
				{
					printf("\n\t%-12s學號:%-18s總分:%-12.2f\n\n", p->name, p->num, p->score);
				}				
				printf("\n\t按Enter鍵繼續!");
				getchar();
			}
			
			if(!strcmp(code, "4"))
			{
				char code2[3];
				printf("\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
				printf("\t|*									*|\n");
				printf("\t|*			1.按學號排序學生資訊				*|\n");
				printf("\t|*			2.按姓名排序學生資訊				*|\n");
				printf("\t|*			3.按總分排序學生資訊				*|\n");
				printf("\t|*									*|\n");
				printf("\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
				do 
				{
					printf("\n\t 輸入您的選擇:");
					gets(code2); 
				}while(!JudgementOptionsS(code2));
				
				if(!strcmp(code2, "1"))
				{
					head = SortNode(head, 2);
					printf("\n\t學號排序成功\n\n");
				}
				if(!strcmp(code2, "2"))
				{	
					head = SortNode(head, 3);
					printf("\n\t字典排序成功\n\n");
				}
				if(!strcmp(code2, "3"))
				{
					head = SortNode(head, 1);
					printf("\n\t總分排序成功\n\n");
				}
				
				printf("\n\t按Enter鍵繼續!");
				getchar();
			}
			
			if(!strcmp(code, "5"))
			{
				PrintNode(head);
				printf("\n\t按Enter鍵繼續!");
				getchar();
			}
			
			if(!strcmp(code, "6"))
			{
				int flag;
				char path[128] = {"students.bin"};
				
				flag = WriteToFile(path, head);
				if (flag)
				{
					printf("\n\t儲存成功\n\n");
					KEY = 1;//之後讀取時方便確定是否錄入過 
				}
				else
				{
					printf("\t檔案載入入失敗或無內容可載入!\n");
				}
				
				ReleaseList(head);
				system("cls");
				goto start;
			}
			
			if(!strcmp(code, "7"))
			{
				char code2[3];
				printf("\n\n\t━━━━━━━━━━━━━━━━━━━ 【請問您遇到了哪些問題?】━━━━━━━━━━━━━━━━━━━━━━━━━━━ \n");
				printf("\t|選項			功能						*|\n");
				printf("\t|*									*|\n");
				printf("\t|1			無法查詢學生資訊				*|\n");
				//printf("\t|2*			 				*|\n");
				//printf("\t|3*							*|\n");
				printf("\t|*									*|\n");
				printf("\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
				printf("\t如遇到更多問題,歡迎聯絡QQ:1872557359反饋\n\n"); 
				
				do
				{
					printf("\t請輸入幫助選項程式碼:"); 
					gets(code2);
				}while(!JudgementOptions2(code2));
				
				if(!strcmp(code2, "1"))
				{
					printf("\t請確認:\n\t1.已錄入學生資訊\n\t2.本次未錄入資訊但上次開啟程式時已錄入資訊\n\t3.若上次開啟程式後錄入了資訊,但這次仍然無法查詢,則說明上次退出時未選擇[儲存並退出]\n\n");
				}
				printf("\n\t按Enter鍵繼續!");
				getchar();
			}
		}
	}
	if(!strcmp(code, "3"))
	{
		system("cls");
		PrintOverMenu();
		exit(0);
	}
}

int PrintStartMenu(void)//開始選單
{
	printf("\n\n\t━━━━━━━━━━━━━━━━━━━━【歡迎使用學生管理系統|請選擇模式】━━━━━━━━━━━━━━━━━━ \n");
	printf("\t|選項			功能						*|\n");
	printf("\t|*									*|\n");
	printf("\t|1 			進入學生模式					*|\n");
	printf("\t|2 			進入教師模式	 				*|\n");
	printf("\t|3 			退出管理系統	 				*|\n");
	printf("\t|*									*|\n");
	printf("\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
}

int PrintOverMenu(void)//退出選單
{
	printf("\n\n\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
	printf("\t|*									*|\n");
	printf("\t|*				#製作by王思淼#				*|\n");
	printf("\t|*				#感謝您的使用#				*|\n");
	printf("\t|*									*|\n");
	printf("\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
	printf("\t使用Enter鍵退出本程式");
	getchar(); 
}

int PrintStudentMenu(void)//學生版選單
{
	printf("\n\n\t━━━━━━━━━━━━━━━━━━━━【歡迎使用學生管理系統|學生版】━━━━━━━━━━━━━━━━━━━━━━━\n");
	printf("\t|選項			功能						*|\n");
	printf("\t|*									*|\n");
	printf("\t|1 			查詢學生資訊					*|\n");
	printf("\t|2 			列出所有的學生資訊 				*|\n");
	printf("\t|3 			回到標題介面					*|\n");
	printf("\t|*									*|\n");
	printf("\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
}

int PrintTeacherMenu(void)//教師版選單
{
	printf("\n\n\t━━━━━━━━━━━━━━━━━━━━【歡迎使用學生管理系統|教師版】━━━━━━━━━━━━━━━━━━━━━━ \n");
	printf("\t|選項			功能						*|\n");
	printf("\t|*									*|\n");
	printf("\t|1 			輸入學生資訊					*|\n");
	printf("\t|2 			刪除學生資訊					*|\n");
	printf("\t|3 			查詢學生資訊					*|\n");
	printf("\t|4 			排序學生資訊					*|\n");
	printf("\t|5 			列出所有的學生資訊 				*|\n");
	printf("\t|6 			儲存並回到標題介面				*|\n");
	printf("\t|7 			幫助						*|\n");
	printf("\t|*									*|\n");
	printf("\t━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
}

int JudgementOptions(char words[])//判斷選項是否合法1,2 
{
	int i; 
	int temp;//用於存入字串轉換成的整數 
	
	for (i = 0; words[i] != '\0'; i++)//遍歷 
	{
		if(!isdigit(words[i]))//檢查其是否為十進位制字元							
		{
			return 0;
		}
	}
	

	temp = atoi(words);
	
	if(temp >= 1 && temp <= 2)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int JudgementOptions2(char words[])//判斷選項是否合法1
{
	int i;
	int temp;//用於存入字串轉換成的整數 
	
	for (i = 0; words[i] != '\0'; i++)//遍歷 
	{
		if(!isdigit(words[i]))//檢查其是否為十進位制字元						
		{
			return 0;
		}
	}
	
	temp = atoi(words);
	
	if(temp >= 1 && temp <= 1)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int JudgementOptionsT(char words[])//判斷選項是否合法1,2,3,4,5,6,7
{
	int i; 
	int temp;//用於存入字串轉換成的整數 
	
	for (i = 0; words[i] != '\0'; i++)//遍歷 
	{
		if(!isdigit(words[i]))//檢查其是否為十進位制字元							
		{
			return 0;
		}
	}
	
	temp = atoi(words); 
	
	if(temp >= 1 && temp <= 7)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int JudgementOptionsS(char words[])//判斷選項是否合法1,2,3
{
	int i; 
	int temp;//用於存入字串轉換成的整數 
	
	for (i = 0; words[i] != '\0'; i++)//遍歷 
	{
		if(!isdigit(words[i]))//檢查其是否為十進位制字元							
		{
			return 0;
		}
	}
	
	temp = atoi(words); 
	
	if(temp >= 1 && temp <= 3)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int isnumber(char a[])//判斷學號是否全為數字
{
	int i;
	int len = strlen(a);
    int j =0;
    for(int i =0;i<len;i++)  //遍歷整個字串
    {
        if(a[i]<=57&&a[i]>=48)  //0~9的ASCII碼是48~57
        {
			j++;
		}  //找到數字了就數量++
    }
    //數字總數和字串長度一樣,則全是數字,總數為0,則都不是數字,在0~len之間則有部分是數字
    if (j==len)
	{   
        i = 1; 
    }
    else 
    {
    	i = 0;
	}
    return i;
}

void GetInput(STU *p)//輸入學生資訊
{
	char num[18];													 
	char name[20];													 
	float score;													 
	char words[20];												 
	
	do
	{
		printf("\t請輸入學生姓名:");	
		gets(name);	 	
	}while (!JudgementName(name));	
	strcpy(p->name, name); 
	do
	{
		printf("\t請輸入學生學號:");	
		gets(num);
	}while (isnumber(num)==0);
	strcpy(p->num, num);
	
	do
	{
		printf("\t請輸入學生成績:");	
		gets(words);
	}while (!JudgementScore(words)); 
	score = atof(words);//將字串轉化為浮點數 
	p->score = score;
}

STU *AppendNode(STU *head)//增加一個新的節點 
{
	STU *p = NULL, *pr = head;//定義末節點和新節點 

	pr = head; 
	p = (STU *)malloc(sizeof(STU));//宣告一個空間來存放 
	if (p == NULL)
	{
		exit(0); 
	}
	GetInput(p);//為新結構體指標賦值 
	p->next = NULL;//新指標尾指向空 
	if (head == NULL)
	{
		head = p; 
	}
	else
	{
		while (pr->next != NULL)//讓pr指向最後一個成員 
		{
			pr = pr->next;	
		}	
		pr->next = p;//讓末節點指向新節點 
	} 
	
	return head;
}

void PrintNode(STU *head)//在螢幕上列印全部學生資訊
{
	STU *p = head;
	
	if (p == NULL)
	{
		printf("\n\t列表中無資料\n\n"); 
		return;
	}
	printf("\n\t|姓名\t     |學號\t\t|總分\n"); 
	while (p != NULL)
	{
		printf("\t|\t     |\t\t\t|\n");
		printf("\t|%-12s|%-18s|%-12.2f\n", 
		p->name, p->num, p->score);
		
		p = p->next;
	}
	printf("\n"); 
}

int WriteToFile(char path[], STU *head)//將連結串列存入檔案
{
	FILE *fp;
	STU *p = head;
	fp = fopen(path, "wb");
	if (fp == NULL)
	{
		printf("\n檔案開啟失敗!\n\n");
		return 0;
	}
	if (head == NULL)
	{ 
		printf("當前沒有學生資訊可寫入!\n");
		return 0;
	}
	while (p != NULL)
	{
		fwrite(p, sizeof(STU), 1, fp);	
		p = p->next;
	}
	
	fclose(fp);
	return 1;
}

STU *ReadFromFile(char path[], STU *head)//從檔案中讀取
{
	FILE *fp;
	STU *pr = head, *p = NULL;
	int flag;														//判斷是否讀到檔案末尾或讀取失敗 
	fp = fopen(path, "rb");
	if (fp == NULL)
	{
		return NULL;												//此處不直接退出是因為,讀取檔案失敗還不足以讓整個程式無法進行 
	}
	
	if (pr == NULL)													//若連結串列為空則加入第一個成員後,進入非空的處理流程 
	{
		p = (STU *)malloc(sizeof(STU));
		flag = fread(p, sizeof(STU), 1, fp);
		if (!flag)													//判斷檔案中是否有內容 
		{
			free(p);
			return NULL;
		}
		head = p;
		p->next = NULL;
		
	}
	pr = head;
	while (pr->next != NULL)										//連結串列非空,遍歷到連結串列末尾,再加入新的成員 
	{
		pr = pr->next;
	}
	
	do
	{
		p = (STU *)malloc(sizeof(STU));							
		flag = fread(p, sizeof(STU), 1, fp);
		if (flag)													//如果讀取成功,則插入連結串列末尾 
		{
			pr->next = p;
			p->next = NULL;	
			pr = p;
		}

	}while (flag);
	
	free(p);														//讀到末尾時,多申請的記憶體實際沒有存放資料,及時釋放 
	fclose(fp);														//關閉檔案 
	return head;	
}

STU *SortNode(STU *head, int mode)//給結構體連結串列排序
{
	STU *pr,*pt, temp;
	pr = head;
	pt = NULL; 
	bool condition;//判斷條件 
	
	if(pr == NULL || pr->next == NULL)
	{
		return head;
	}
	
	while(pr != pt)
	{
		while(pr->next != pt)//每輪會把最大或最小的數排到最後 
		{
			switch (mode)
			{
				case 1:// "1"表示按降序降序
					condition = pr->score < pr->next->score;
					break;	
				case 2:// "2"表示按學號排序 
					condition = (strcmp(pr->num, pr->next->num) > 0);
					break;
				case 3:// "3"表示按姓名排序 
					condition = (strcmp(pr->name, pr->next->name) > 0);
					break;
				default://如果mode不正確,則直接返回原連結串列,不進行排序 
					return head;
			} 
			
			if(condition) 
			{
				temp = *(pr->next);
											 
				strcpy(pr->next->name, pr->name);
				strcpy(pr->next->num, pr->num);
				pr->next->score = pr->score;
				
				strcpy(pr->name, temp.name);
				strcpy(pr->num, temp.num);
				pr->score = temp.score;
			}
			pr = pr->next;
		}
		pt = pr;
		pr = head;
	}
	return head;
}

STU *SearchNode(STU *head, char keyword[])//通過name或num查詢學生結構體
{
	STU *pr = head;
	if (pr == NULL)//連結串列為空 
	{
		return NULL;
	}
	while (strcmp(pr->name, keyword) && strcmp(pr->num, keyword))//遍歷 
	{
		pr = pr->next;
		if(pr == NULL)
		{
			return NULL; 
		}
	}
	return pr;//返回找到的指向節點的指標 
}

int JudgementScore(char words[])//判斷輸入分數是否合法
{
	int i = 0;
	int flag = 1; 
	double temp; 
	
	if (words[i] == '\0')//若輸入為空,則錯誤 
	{
		return 0;
	}
	
	for (i = 0; words[i] != '\0'; i++)//遍歷 
	{
		if (i == 0)//判斷第一個數 
		{
			if(!isdigit(words[i]))// 第一個符號必須是數字 
			{
				return 0;
			}
		}
		else//判斷之後的數 
		{
			if (!isdigit(words[i]))
			{
				if (words[i] == '.')//判斷有沒有小數點
				{
					if (flag)//至多一個小數點 
					{		
						flag = 0; 
						continue;
					}
					else   
					{
						return 0;
					}	
				}	 
			return 0;//如果是其他字元也錯誤 
			}
		}
	}
	temp = atof(words);//把字串轉換成浮點數 
	
	if(temp >= 0 && temp <= 100)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

void ReleaseList(STU *head)//釋放連結串列 
{
	STU *pr = head, *p = NULL;
	
	while (pr != NULL)
	{
		p = pr;
		free(pr);
		pr = p->next;
	} 
}

int DeleteSpecNode(STU **head, char str[])//刪除節點					
{
	STU *pr = *head, *p = *head;
	int flag = 0; 
	if (p == NULL)//連結串列內無內容 
	{
		return 0; 
	}
	while (p != NULL)//遍歷連結串列 
	{
		if(!strcmp(p->num, str))//找到相應學生資訊 
		{
			flag = 1;
			break;//停止遍歷,進行刪除操作 
		}
		pr = p;
		p = p->next;
	}
	
	if (flag)
	{
		if(p == *head)
		{
			*head = p->next;
			free(p);
		}
		else													
		{
			pr->next = p->next;
			free(p);
		}
	}
	else//如果沒有找到,則返回1 
	{
		return 0; 
	} 
	
	return 1;
	
}

int JudgementName(char name[])//判斷輸入姓名是否合法
{
	if (name[0] == '\0')//使用者沒有輸入 
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

相關文章