C語言系列 : 以鏈結串列實現成績管理程式

複習Linked List,並以此來實現成績管理程式的存檔、讀檔、自動排序、新增、刪除、修改成績功能。

 

完整程式碼:

/* 一個以Linked list方式,儲存學生期末考成績的資料:
	具有下述功能:
		1.儲存單筆時會自動排序
		2.可以新增,顯示,修改,刪除及學生的成績
		3.資料格式為  |學生名稱|期末考成績|
		4.可輸出及讀入資料,資料格式為.bin
*/ 

#include "pch.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

void add(void);//新增的涵式
void insert(void);//插入的函式
void delet(void);//刪除的涵式
void read(void);//讀檔的涵式
void write(void);//存檔的涵式
void display(void);//顯示的涵式
void modify(void);//修正成績的涵式
void introdu(void);//介紹功能

int set = 0;//鏈結串列總數

struct student{
	char name[20];
	int score;
	struct student *next;
};
struct student  *current, *inser, *previous;
//inser是要插入進去鏈結中的資料,previous是指向當前所參照的前一個鏈結處
struct student *head = (struct student *)malloc(sizeof(struct student));//宣告head
//head是第一個標頭,current是當前所參照的鏈結處


int main() 
{
	char key;
	introdu();//介紹功能
	printf("是否需要讀取已儲存資料:(Y/N)");
	scanf_s("%c", &key);
	if (key == 'Y' || key == 'y') {
		read();
	}
	while (1) {//具有表單讓使用者選擇功能
		printf("\n Please enter your choose:");
		scanf_s("\n%c",&key); //輸入選擇且避免前次輸入score時的\n導致影響此次輸入。
		switch (key) {
			case '1'://Inset the new student score
				add();
				set++;//紀錄linked list total numbers
				break;
			case '2'://2.Delete the student score
				delet();//由於不確定是否使用者輸入正確要刪除名稱,因此得看情況更新total numbers
				break;
			case '3'://3.Display all student scores
				display();
				break;
			case '4'://4.Modify the student score
				modify();
				break;
			case '5'://5.Save the data
				write();
				break;
			case '6'://6.Exit
				return 0;
				break;
			default://Error
				printf("Please enter the corrent key!\n");
				break;
		}
	}

}

void add(void) {//新增的涵式
	int score;
	inser = (struct student *) malloc(sizeof(struct student));
	//輸入學生姓名及成績
	printf("請輸入學生姓名:");
	scanf_s("%s",inser->name);
	printf("請輸入學生期末考成績:");
	scanf_s("%d", &score);
	inser->score = score;
	if (set == 0) {
		head->next = inser;//將head的next指向inser的位址
		printf("student name :%s  score:%d",inser->name, inser->score);
	}else insert();//插入
}
void insert(void) {//插入的函式
	int i = 0;
	previous = head;
	current = previous->next;
	while (current != NULL) {
		if (current->score != NULL) {
			if (current->score > inser->score) {
				previous = current; //紀錄原本的當前連結位置
				current = current->next; //依照當前鏈結往後尋找下一個鏈結
			}else if(i >= set) {
				break;
			}
			i++;
		}
		else break;
	}
	previous->next = inser;//將previous的next指向inser的位址
	inser->next = current;//然後將inser的next指向current的位址
}
void delet(){//刪除的涵式
	char delet_name[20] = {};
	bool exist = false;
	printf("請輸入欲刪除的學生姓名:");
	scanf_s("\n%s",delet_name);//輸入欲刪除學生姓名並避免前次輸入的\n影響輸入。
	previous = head;
	current = previous->next;
	for(int i = 0;i<set;i++){
		if (strcmp(delet_name, current->name) ==0) { //成功找到需要刪除的串列
			//strcmp(const char*, const char*) 若兩個字串相符,回傳0
			previous->next = current->next;
			free(current);//釋放掉刪除的串列
			exist = true; 
			printf("\n已找到學生資料並刪除\n");
			break;
		}
		previous = current;
		current = current->next;
		
	}
	if(exist)set--;//若成功找到相同學生名字,則此鏈結串列總數減一
	else printf("\n並未找到此學生資料,無法刪除\n");
}
void read(){//讀檔的涵式
	
	previous = head;
	char name[20];
	int score=0;
	FILE *fp;
	if ((fp = fopen("final test.bin", "rb")) != NULL) {
		while (fscanf(fp, "%s %d\n", name, &score) != EOF) {
			inser = (struct student*)malloc(sizeof(struct student));
			strcpy(inser->name, name);
			inser->score = score;
			if (set == 0) {
				head->next = inser;
				current = inser;
			}
			else {
				current->next = inser;
				current = inser;
			}
			set++;
		}
	}
	fclose(fp);
}
void write() {//存檔的涵式
	previous = head; 
	current = previous->next;
	FILE *fp;
	errno_t err;
	err= fopen_s(&fp,"final test.bin", "wb+");
	for (int i = 0; i < set;i++) {
		//_itoa_s(current->score,str_score,10); //將數字轉為字串
		fprintf(fp,"%s %d\n",current->name,current->score);//將資料存入檔案中
		current = current->next;
	}
	fclose(fp);
}
void display() {//顯示的涵式
	previous = head;
	current = head->next;
	printf("-----------------------------------\n");
	printf("  NAME                     SCORE  \n");
	printf("-----------------------------------\n");
	for(int i = 0 ; i < set;i++){
		printf("%-20s      %3d\n",current->name, current->score);
		current = current->next;
	}
	
}
void modify(){//修正成績的涵式
	char modify_name[20] = {};
	bool exist = false;
	int score=0;
	printf("請輸入欲修正成績的學生姓名:");
	scanf_s("\n%s", modify_name);//輸入輸入欲修正成績的學生姓名
	previous = head;
	current = previous->next;
	for (int i = 0; i < set; i++) {
		if (strcmp(modify_name, current->name) == 0) { //成功找到需要欲修正成績的串列
			//strcmp(const char*, const char*) 若兩個字串相符,回傳0
			printf("學生姓名:%-20s    期末考成績:%d分\n", current->name, current->score);
			printf("請輸入修正的成績:");
			scanf_s("%d", &score);
			current->score = score;
			exist = true;
			break;
			
		}
		previous = current;
		current = current->next;
	}
	if (exist==false)printf("\n並未找到此學生資料,無法修正\n");
}
void introdu() {//介紹功能
	printf("The program can save the student final exam scores. \n");
	printf("You can enter the number which choose the function:\n");
	printf("---------------------------------------\n");
	printf("    1.Inset the new student score \n");
	printf("    2.Delete the student score \n");
	printf("    3.Display all student scores \n");
	printf("    4.Modify the student score \n");
	printf("    5.Save the data\n");
	printf("    6.Exit\n");
	printf("---------------------------------------\n");
}

執行結果:

_______________________________________________

我們透過閱讀,拼湊出真實世界的面貌,
並在反覆的探索及思維中,打破由自我無知與偏見所建立的籓籬。