C語言鏈表實現學生成績管理系統
本文實例為大傢分享瞭C語言基於鏈表實現學生成績管理系統的具體代碼,供大傢參考,具體內容如下
一、課程設計題目及內容
程序名稱:學生成績管理系統
功能要求:錄入學生成績,修改學生成績,統計每個學生的總分及平均分並能根據學生的平均成績排序,查詢學生成績,輸出學生成績單。能夠保存學生成績,實現文件的讀寫。界面簡潔大方,易操作。
二、主要設計思路
以鏈表作為數據結構存儲學生成績等信息,然後圍繞鏈表編寫一堆函數來實現一堆功能
程序開始時會讀取文件數據到鏈表,結束時會把更新後的鏈表中的信息重新寫入到文件中,以實現數據的保存
三、程序源碼及具體註釋
(1)預處理指令
導入<stdlib.h>是因為會用到malloc函數和free函數
導入<string.h>是因為會用到strcmp函數
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_LEN 10
#define FILE_NAME "學生成績.txt"
(2)類型定義
1.student類型定義
一個student變量代表一組學生信息
typedef struct { char name[NAME_LEN + 1];//姓名 int number; //學號 int chinese; //語文 int math; //數學 int english; //英語 int average; //平均分 int sum; //總分 } student; //用於存儲單個學生的信息
2. studentNode類型定義
一個studentNode變量代表一個學生節點
typedef struct node { student stu; //數據域,存儲學生信息 struct node *next; //指針域,指向下一個節點 } studentNode; //學生節點
3. studentList類型定義
一個studentList變量代表一個學生鏈表
typedef struct { studentNode *head; //頭指針 studentNode *tail; //尾指針 int count; //學生節點總數 } studentList; //學生鏈表
(3)函數原型
void initialize(studentList *L);//初始化鏈表,創建頭節點 void enter(studentList *L); //錄入鏈表 void display(studentList *L); //輸出鏈表 void find(studentList *L); //查找某節點 void modify(studentList *L); //修改某節點 void sort(studentList *L); //降序重新建表並輸出 void write(studentList *L); //寫入文件,邊寫邊釋放空間 void read(studentList *L); //讀取文件,邊讀邊建表
(4)main函數定義
開頭會創建並初始化一個鏈表,然後把文件的信息讀到鏈表中
通過一個無限循環裡面套一個switch來實現與用戶互動
結尾會把鏈表中的信息寫到文件中,然後銷毀鏈表
int main() { //互動界面 printf(" **************學生成績管理系統**************\n"); printf(" * 1.錄入新的學生成績 *\n"); printf(" * 2.按姓名修改學生成績 *\n"); printf(" * 3.按姓名查詢學生成績 *\n"); printf(" * 4.輸出全部學生的成績 *\n"); printf(" * 5.按平均分輸出學生成績 *\n"); printf(" * 6.退出學生成績管理系統 *\n"); printf(" ********************************************\n"); printf(" \n"); //創建學生鏈表 studentList *L = (studentList *)malloc(sizeof(studentList)); //初始化學生鏈表 initialize(L); //從文件裡讀取數據到鏈表 read(L); //互動界面是用一個無限循環和一個switch寫的 while (1) { int code; printf("請輸入你想進行的操作對應的數字: "); scanf("%d", &code); switch (code) { case 1: enter(L); break; case 2: modify(L); break; case 3: find(L); break; case 4: display(L); break; case 5: sort(L); break; case 6: write(L); free(L->head); //頭節點被銷毀 free(L); //鏈表被銷毀 return 0; default: printf("%d是無效的數字,請重新輸入!\n\n", code); break; } } return 0; }
(5)其他函數定義
1.initialize函數定義
接收一個鏈表指針作為參數
創建一個頭節點,不存儲任何信息,讓鏈表的頭尾指針都指向它
鏈表的初始長度設為0
void initialize(studentList *L) { //創建頭節點 studentNode *s = (studentNode *)malloc(sizeof(studentNode)); s->next = NULL; //初始化鏈表: //頭尾指針均指向頭節點,初始長度為零 L->head = s; L->tail = s; L->count = 0; }
2.enter函數定義
接收一個鏈表指針作為參數
讓用戶鍵入信息並存到新節點中
把新節點插進鏈表中
void enter(studentList *L) { //創建新節點 studentNode *s = (studentNode *)malloc(sizeof(studentNode)); //鍵入信息並存到新節點中 printf("請輸入學生姓名:"); scanf("%s", s->stu.name); printf("請輸入學生學號:"); scanf("%d", &s->stu.number); printf("請輸入語文成績:"); scanf("%d", &s->stu.chinese); printf("請輸入數學成績:"); scanf("%d", &s->stu.math); printf("請輸入英語成績:"); scanf("%d", &s->stu.english); s->stu.sum = s->stu.chinese + s->stu.math + s->stu.english; s->stu.average = s->stu.sum / 3; //若鏈表為空,將尾指針指向新節點 if (L->head == L->tail) { L->tail = s; } //將新節點插進鏈表頭部(頭插法) s->next = L->head->next; L->head->next = s; L->count++; //輸出互動信息 printf("信息錄入成功!\n\n"); }
3.display函數定義
遍歷鏈表輸出就完事兒瞭
void display(studentList *L) { printf("共有%d組學生數據:\n", L->count); printf("姓名\t\t學號\t\t語文\t\t數學\t\t英語\t\t總分\t\t平均分\n"); //創建一節點指針指向頭節點 studentNode *p; p = L->head; //遍歷鏈表輸出 while (p->next) { p = p->next; printf("%s", p->stu.name); printf("\t\t%d", p->stu.number); printf("\t\t%d", p->stu.chinese); printf("\t\t%d", p->stu.math); printf("\t\t%d", p->stu.english); printf("\t\t%d", p->stu.sum); printf("\t\t%d", p->stu.average); printf("\n"); } printf("\n"); }
4.find函數定義
void find(studentList *L) { //讓用戶輸入要查找的學生 printf("請輸入學生姓名:"); char name[NAME_LEN + 1]; scanf("%s", name); //遍歷鏈表對比名字 studentNode *p = L->head->next; while (p) { //符合瞭就輸出並結束函數 if (strcmp(p->stu.name, name) == 0) { printf("姓名\t\t學號\t\t語文\t\t數學\t\t英語\t\t總分\t\t平均分\n"); printf("%s", p->stu.name); printf("\t\t%d", p->stu.number); printf("\t\t%d", p->stu.chinese); printf("\t\t%d", p->stu.math); printf("\t\t%d", p->stu.english); printf("\t\t%d", p->stu.sum); printf("\t\t%d", p->stu.average); printf("\n\n"); return; } //名字不符合就下一個 p = p->next; } //遍歷完裡都沒找到這個名字 printf("沒找到這個%s的信息!\n\n", name); }
5.modify函數定義
void modify(studentList *L) { //讓用戶輸入要修改的學生 printf("請輸入學生姓名:"); char name[NAME_LEN + 1]; scanf("%s", name); //遍歷鏈表對比名字 studentNode *p = L->head->next; while (p) { //符合瞭就讓用戶重新鍵入並結束函數 if (strcmp(p->stu.name, name) == 0) { printf("請重新輸入信息:\n"); printf("請輸入學生學號:"); scanf("%d", &p->stu.number); printf("請輸入語文成績:"); scanf("%d", &p->stu.chinese); printf("請輸入數學成績:"); scanf("%d", &p->stu.math); printf("請輸入英語成績:"); scanf("%d", &p->stu.english); p->stu.sum = p->stu.chinese + p->stu.math + p->stu.english; p->stu.average = p->stu.sum / 3; printf("信息修改成功!\n\n"); return; } //名字不符合就下一個 p = p->next; } //遍歷完裡都沒找到這個名字 printf("沒找到這個%s的信息!\n\n", name); }
6.sort函數定義
void sort(studentList *L) { //兩個節點都沒有排個屁序 if (L->count < 2) { printf("鏈表排序完成!\n"); display(L); return; } //插入排序 studentNode *p, *pre, *tmp; //p指向第二個學生節點 p = L->head->next; //鏈表從頭節點和第一個學生節點處斷開 L->head->next = NULL; //從第一個學生節點開始一直往後循環 while (p) { //存好下一個節點的指針 tmp = p->next; //找到插入位置 pre = L->head; while (pre->next != NULL && pre->next->stu.average > p->stu.average) pre = pre->next; //更新尾指針 if (pre->next == NULL) { L->tail = p; } //插入 p->next = pre->next; pre->next = p; //跳到下一個 p = tmp; } printf("鏈表排序完成!\n"); display(L); }
7.write函數定義
此函數用於把鏈表中的信息保存到文件中並且銷毀所有節點(頭節點除外)
void write(studentList *L) { //打開文件流 FILE *fp = fopen(FILE_NAME, "w"); if (fp == NULL) { printf("文件%s打開失敗\n", FILE_NAME); exit(EXIT_FAILURE); } //將學生節點總數輸出在第一行 fprintf(fp, "%d\n", L->count); //創建一節點指針指向頭節點 studentNode *p; p = L->head->next; //遍歷鏈表,一組數據作為一行輸出 while (p) { fprintf(fp, "%s ", p->stu.name); fprintf(fp, "%d ", p->stu.number); fprintf(fp, "%d ", p->stu.chinese); fprintf(fp, "%d ", p->stu.math); fprintf(fp, "%d ", p->stu.english); fprintf(fp, "%d ", p->stu.sum); fprintf(fp, "%d ", p->stu.average); fprintf(fp, "\n"); //輸出完成之後釋放節點空間 studentNode *next = p->next; free(p); p = next; } //關閉文件流 fclose(fp); //互動信息 printf("數據已保存!謝謝使用,再見!\n"); }
8.read函數定義
此函數用於把文件中的信息讀取到鏈表中並且創建節點(頭節點除外)
void read(studentList *L) { //打開文件流 FILE *fp = fopen(FILE_NAME, "r"); if (fp == NULL) { printf("文件%s打開失敗\n", FILE_NAME); exit(EXIT_FAILURE); } //讀取第一行的學生節點總數 fscanf(fp, "%d", &L->count); //循環讀取數據,循環次數為count for (int i = 1; i <= L->count; i++) { //創建新節點 studentNode *s = (studentNode *)malloc(sizeof(studentNode)); //讀取數據 fscanf(fp, "%s ", s->stu.name); fscanf(fp, "%d ", &s->stu.number); fscanf(fp, "%d ", &s->stu.chinese); fscanf(fp, "%d ", &s->stu.math); fscanf(fp, "%d ", &s->stu.english); fscanf(fp, "%d ", &s->stu.sum); fscanf(fp, "%d ", &s->stu.average); //將新節點插進鏈表尾部(尾插法) s->next = NULL; L->tail->next = s; L->tail = s; } //關閉文件流 fclose(fp); }
四、運行示例
輸出全部學生成績
錄入一組新數據然後關閉程序
上次輸入的信息還在,說明信息保存成功
五、註意事項
文件得和源碼在同一目錄
文件名是"學生成績.txt"
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。