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