C語言鏈表實現(xiàn)學生成績管理系統(tǒng)
本文實例為大家分享了C語言基于鏈表實現(xiàn)學生成績管理系統(tǒng)的具體代碼,供大家參考,具體內(nèi)容如下
一、課程設計題目及內(nèi)容
程序名稱:學生成績管理系統(tǒng)
功能要求:錄入學生成績,修改學生成績,統(tǒng)計每個學生的總分及平均分并能根據(jù)學生的平均成績排序,查詢學生成績,輸出學生成績單。能夠保存學生成績,實現(xiàn)文件的讀寫。界面簡潔大方,易操作。
二、主要設計思路
以鏈表作為數(shù)據(jù)結(jié)構(gòu)存儲學生成績等信息,然后圍繞鏈表編寫一堆函數(shù)來實現(xiàn)一堆功能
程序開始時會讀取文件數(shù)據(jù)到鏈表,結(jié)束時會把更新后的鏈表中的信息重新寫入到文件中,以實現(xiàn)數(shù)據(jù)的保存
三、程序源碼及具體注釋
(1)預處理指令
導入<stdlib.h>是因為會用到malloc函數(shù)和free函數(shù)
導入<string.h>是因為會用到strcmp函數(shù)
#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;?? ??? ??? ??? ?//數(shù)學 ?? ?int english;?? ??? ??? ?//英語 ?? ?int average;?? ??? ??? ?//平均分 ?? ?int sum;?? ??? ??? ??? ?//總分 } student;?? ??? ??? ??? ??? ?//用于存儲單個學生的信息
2. studentNode類型定義
一個studentNode變量代表一個學生節(jié)點
typedef struct node { ?? ?student stu;?? ??? ?//數(shù)據(jù)域,存儲學生信息 ?? ?struct node *next;?? ?//指針域,指向下一個節(jié)點 } studentNode;?? ??? ??? ?//學生節(jié)點
3. studentList類型定義
一個studentList變量代表一個學生鏈表
typedef struct { ?? ?studentNode *head;?? ?//頭指針 ?? ?studentNode *tail;?? ?//尾指針 ?? ?int count;?? ??? ??? ?//學生節(jié)點總數(shù) } studentList;?? ??? ??? ?//學生鏈表
(3)函數(shù)原型
void initialize(studentList *L);//初始化鏈表,創(chuàng)建頭節(jié)點 void enter(studentList *L);?? ??? ?//錄入鏈表 void display(studentList *L);?? ?//輸出鏈表 void find(studentList *L);?? ??? ?//查找某節(jié)點 void modify(studentList *L);?? ?//修改某節(jié)點 void sort(studentList *L);?? ??? ?//降序重新建表并輸出 void write(studentList *L);?? ??? ?//寫入文件,邊寫邊釋放空間 void read(studentList *L);?? ??? ?//讀取文件,邊讀邊建表
(4)main函數(shù)定義
開頭會創(chuàng)建并初始化一個鏈表,然后把文件的信息讀到鏈表中
通過一個無限循環(huán)里面套一個switch來實現(xiàn)與用戶互動
結(jié)尾會把鏈表中的信息寫到文件中,然后銷毀鏈表
int main() { ?? ?//互動界面 ?? ?printf("?? ??? ?**************學生成績管理系統(tǒng)**************\n"); ?? ?printf("?? ??? ?* ?1.錄入新的學生成績 ? ? ? ? ? ? ? ? ? ? ?*\n"); ?? ?printf("?? ??? ?* ?2.按姓名修改學生成績 ? ? ? ? ? ? ? ? ? ?*\n"); ?? ?printf("?? ??? ?* ?3.按姓名查詢學生成績 ? ? ? ? ? ? ? ? ? ?*\n"); ?? ?printf("?? ??? ?* ?4.輸出全部學生的成績 ? ? ? ? ? ? ? ? ? ?*\n"); ?? ?printf("?? ??? ?* ?5.按平均分輸出學生成績 ? ? ? ? ? ? ? ? ?*\n"); ?? ?printf("?? ??? ?* ?6.退出學生成績管理系統(tǒng) ? ? ? ? ? ? ? ? ?*\n"); ?? ?printf("?? ??? ?********************************************\n"); ?? ?printf(" ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\n"); ?? ?//創(chuàng)建學生鏈表 ?? ?studentList *L = (studentList *)malloc(sizeof(studentList)); ?? ?//初始化學生鏈表 ?? ?initialize(L); ?? ?//從文件里讀取數(shù)據(jù)到鏈表 ?? ?read(L); ?? ?//互動界面是用一個無限循環(huán)和一個switch寫的 ?? ?while (1) { ?? ??? ?int code; ?? ??? ?printf("請輸入你想進行的操作對應的數(shù)字: "); ?? ??? ?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);?? ?//頭節(jié)點被銷毀 ?? ??? ??? ??? ?free(L);?? ??? ?//鏈表被銷毀 ?? ??? ??? ??? ?return 0; ?? ??? ??? ?default: ?? ??? ??? ??? ?printf("%d是無效的數(shù)字,請重新輸入!\n\n", code); ?? ??? ??? ??? ?break; ?? ??? ?} ?? ?} ?? ?return 0; }
(5)其他函數(shù)定義
1.initialize函數(shù)定義
接收一個鏈表指針作為參數(shù)
創(chuàng)建一個頭節(jié)點,不存儲任何信息,讓鏈表的頭尾指針都指向它
鏈表的初始長度設為0
void initialize(studentList *L) { ?? ?//創(chuàng)建頭節(jié)點 ?? ?studentNode *s = (studentNode *)malloc(sizeof(studentNode)); ?? ?s->next = NULL; ?? ?//初始化鏈表: ?? ?//頭尾指針均指向頭節(jié)點,初始長度為零 ?? ?L->head = s; ?? ?L->tail = s; ?? ?L->count = 0; }
2.enter函數(shù)定義
接收一個鏈表指針作為參數(shù)
讓用戶鍵入信息并存到新節(jié)點中
把新節(jié)點插進鏈表中
void enter(studentList *L) { ?? ?//創(chuàng)建新節(jié)點 ?? ?studentNode *s = (studentNode *)malloc(sizeof(studentNode)); ?? ?//鍵入信息并存到新節(jié)點中 ?? ?printf("請輸入學生姓名:"); ?? ?scanf("%s", s->stu.name); ?? ?printf("請輸入學生學號:"); ?? ?scanf("%d", &s->stu.number); ?? ?printf("請輸入語文成績:"); ?? ?scanf("%d", &s->stu.chinese); ?? ?printf("請輸入數(shù)學成績:"); ?? ?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; ?? ?//若鏈表為空,將尾指針指向新節(jié)點 ?? ?if (L->head == L->tail) { ?? ??? ?L->tail = s; ?? ?} ?? ?//將新節(jié)點插進鏈表頭部(頭插法) ?? ?s->next = L->head->next; ?? ?L->head->next = s; ?? ?L->count++; ?? ?//輸出互動信息 ?? ?printf("信息錄入成功!\n\n"); }
3.display函數(shù)定義
遍歷鏈表輸出就完事兒了
void display(studentList *L) { ?? ?printf("共有%d組學生數(shù)據(jù):\n", L->count); ?? ?printf("姓名\t\t學號\t\t語文\t\t數(shù)學\t\t英語\t\t總分\t\t平均分\n"); ?? ?//創(chuàng)建一節(jié)點指針指向頭節(jié)點 ?? ?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函數(shù)定義
void find(studentList *L) { ?? ?//讓用戶輸入要查找的學生 ?? ?printf("請輸入學生姓名:"); ?? ?char name[NAME_LEN + 1]; ?? ?scanf("%s", name); ?? ?//遍歷鏈表對比名字 ?? ?studentNode *p = L->head->next; ?? ?while (p) { ?? ??? ?//符合了就輸出并結(jié)束函數(shù) ?? ??? ?if (strcmp(p->stu.name, name) == 0) { ?? ??? ??? ?printf("姓名\t\t學號\t\t語文\t\t數(shù)學\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函數(shù)定義
void modify(studentList *L) { ?? ?//讓用戶輸入要修改的學生 ?? ?printf("請輸入學生姓名:"); ?? ?char name[NAME_LEN + 1]; ?? ?scanf("%s", name); ?? ?//遍歷鏈表對比名字 ?? ?studentNode *p = L->head->next; ?? ?while (p) { ?? ??? ?//符合了就讓用戶重新鍵入并結(jié)束函數(shù) ?? ??? ?if (strcmp(p->stu.name, name) == 0) { ?? ??? ??? ?printf("請重新輸入信息:\n"); ?? ??? ??? ?printf("請輸入學生學號:"); ?? ??? ??? ?scanf("%d", &p->stu.number); ?? ??? ??? ?printf("請輸入語文成績:"); ?? ??? ??? ?scanf("%d", &p->stu.chinese); ?? ??? ??? ?printf("請輸入數(shù)學成績:"); ?? ??? ??? ?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函數(shù)定義
void sort(studentList *L) { ?? ?//兩個節(jié)點都沒有排個屁序 ?? ?if (L->count < 2) { ?? ??? ?printf("鏈表排序完成!\n"); ?? ??? ?display(L); ?? ??? ?return; ?? ?} ?? ?//插入排序 ?? ?studentNode *p, *pre, *tmp; ?? ?//p指向第二個學生節(jié)點 ?? ?p = L->head->next; ?? ?//鏈表從頭節(jié)點和第一個學生節(jié)點處斷開 ?? ?L->head->next = NULL; ?? ?//從第一個學生節(jié)點開始一直往后循環(huán) ?? ?while (p) { ?? ??? ?//存好下一個節(jié)點的指針 ?? ??? ?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函數(shù)定義
此函數(shù)用于把鏈表中的信息保存到文件中并且銷毀所有節(jié)點(頭節(jié)點除外)
void write(studentList *L) { ?? ?//打開文件流 ?? ?FILE *fp = fopen(FILE_NAME, "w"); ?? ?if (fp == NULL) { ?? ??? ?printf("文件%s打開失敗\n", FILE_NAME); ?? ??? ?exit(EXIT_FAILURE); ?? ?} ?? ?//將學生節(jié)點總數(shù)輸出在第一行 ?? ?fprintf(fp, "%d\n", L->count); ?? ?//創(chuàng)建一節(jié)點指針指向頭節(jié)點 ?? ?studentNode *p; ?? ?p = L->head->next; ?? ?//遍歷鏈表,一組數(shù)據(jù)作為一行輸出 ?? ?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"); ?? ??? ?//輸出完成之后釋放節(jié)點空間 ?? ??? ?studentNode *next = p->next; ?? ??? ?free(p); ?? ??? ?p = next; ?? ?} ?? ?//關(guān)閉文件流 ?? ?fclose(fp); ?? ?//互動信息 ?? ?printf("數(shù)據(jù)已保存!謝謝使用,再見!\n"); }
8.read函數(shù)定義
此函數(shù)用于把文件中的信息讀取到鏈表中并且創(chuàng)建節(jié)點(頭節(jié)點除外)
void read(studentList *L) { ?? ?//打開文件流 ?? ?FILE *fp = fopen(FILE_NAME, "r"); ?? ?if (fp == NULL) { ?? ??? ?printf("文件%s打開失敗\n", FILE_NAME); ?? ??? ?exit(EXIT_FAILURE); ?? ?} ?? ?//讀取第一行的學生節(jié)點總數(shù) ?? ?fscanf(fp, "%d", &L->count); ?? ?//循環(huán)讀取數(shù)據(jù),循環(huán)次數(shù)為count ?? ?for (int i = 1; i <= L->count; i++) { ?? ??? ?//創(chuàng)建新節(jié)點 ?? ??? ?studentNode *s = (studentNode *)malloc(sizeof(studentNode)); ?? ??? ?//讀取數(shù)據(jù) ?? ??? ?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); ?? ??? ?//將新節(jié)點插進鏈表尾部(尾插法) ?? ??? ?s->next = NULL; ?? ??? ?L->tail->next = s; ?? ??? ?L->tail = s; ?? ?} ?? ?//關(guān)閉文件流 ?? ?fclose(fp); }
四、運行示例
輸出全部學生成績
錄入一組新數(shù)據(jù)然后關(guān)閉程序
上次輸入的信息還在,說明信息保存成功
五、注意事項
文件得和源碼在同一目錄
文件名是"學生成績.txt"
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
完全掌握C++編程中構(gòu)造函數(shù)使用的超級學習教程
這篇文章主要介紹了C++中的構(gòu)造函數(shù),包括C++11標準中的新特性的介紹,十分推薦!需要的朋友可以參考下2016-01-01Qt圖片繪圖類之QPixmap/QImage/QPicture詳解
這篇文章主要為大家詳細介紹了Qt圖片繪圖類中QPixmap、QImage和QPicture的使用方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2023-03-03typedef和#define用法區(qū)別總結(jié)
在C還是C++代碼中,typedef都使用的很多,在C代碼中尤其多,typedef與#define有些相似,其實是不同的,特別是在一些復雜的用法上,下面這篇文章主要給大家介紹了關(guān)于typedef和#define用法區(qū)別總結(jié)的相關(guān)資料,需要的朋友可以參考下2023-06-06C語言中關(guān)于庫函數(shù) qsort 快排的用法
快速排序Qsort是所有學習算法和數(shù)據(jù)結(jié)構(gòu)最基礎(chǔ)的一個部分,也是考試題和面試的一個小重點。本片文章帶你了解Qsort的詳細用法規(guī)則2021-09-09