柚子快報(bào)激活碼778899分享:【C語(yǔ)言】學(xué)生管理系統(tǒng)
柚子快報(bào)激活碼778899分享:【C語(yǔ)言】學(xué)生管理系統(tǒng)
大家好,歡迎來(lái)到我的博客總結(jié)應(yīng)用。在上一篇博客中,我寫(xiě)了有關(guān)結(jié)構(gòu)體和內(nèi)存操作函
數(shù)的總結(jié),這些博客記錄了我的學(xué)習(xí)、思考和經(jīng)驗(yàn)。為了更好地總結(jié)和回顧這些內(nèi)容,在此
篇博客中,我編寫(xiě)了”學(xué)生管理系統(tǒng)“來(lái)幫助我整理和應(yīng)用上一篇博客的總結(jié)知識(shí)點(diǎn)。在這個(gè)
”學(xué)生管理系統(tǒng)“中,我列舉了九條不同的標(biāo)題和內(nèi)容來(lái)進(jìn)行說(shuō)明,以下便是我的總結(jié)整理。
文章目錄
一、定義學(xué)生信息的結(jié)構(gòu)體二、主函數(shù)邏輯三、添加學(xué)生信息四、刪除學(xué)生信息五、修改學(xué)生信息六、顯示學(xué)生列表七、查詢學(xué)生信息八、退出程序九、完整代碼及補(bǔ)充
一、定義學(xué)生信息的結(jié)構(gòu)體
添加必要的頭文件和聲明,之后定義學(xué)生信息結(jié)構(gòu)體。
學(xué)生信息結(jié)構(gòu)體中含有必要的學(xué)生id、學(xué)生姓名和學(xué)生成績(jī),除此之外,也可以自行添加一些其他信息,如學(xué)生家庭年齡,學(xué)生住址,學(xué)生班級(jí),學(xué)生教師,學(xué)生所屬學(xué)校等
#include
#include
#include
// 學(xué)生信息結(jié)構(gòu)體
typedef struct _Student {
int id;
float score; /* 數(shù)據(jù)域 */
char name[50];
struct Student *next; /* 指針域 */
} Student;
int isExistId(Student **head, int id);
void freeMemory(Student *head);
void addStudent(Student **head);
void deleteStudent(Student **head);
void updateStudent(Student **head);
void printStudent(Student **head);
void searchStudent(Student **head);
可以將數(shù)據(jù)域和指針域分開(kāi)來(lái)定義,使結(jié)構(gòu)邏輯更加嚴(yán)整。
typedef struct _Student {
int id;
float score;
char name[50];
} Student;
// 嵌套結(jié)構(gòu)體
typedef struct _StuNode {
Student stu;
struct _Node *next;
} StuNode;
二、主函數(shù)邏輯
主函數(shù)主要負(fù)責(zé)輸出學(xué)生管理系統(tǒng)的文字頁(yè)面、選擇對(duì)應(yīng)的功能、暫停并清空控制臺(tái)
int main()
{
int choice;
Student *head = NULL; // 學(xué)生鏈表頭指針
while (1)
{
// 暫停程序
system("pause");
// 清空控制臺(tái)
system("cls");
printf("--------學(xué)生管理系統(tǒng)--------\n");
printf("\t1. 添加學(xué)生信息\n");
printf("\t2. 刪除學(xué)生信息\n");
printf("\t3. 修改學(xué)生信息\n");
printf("\t4. 顯示學(xué)生列表\n");
printf("\t5. 查找學(xué)生信息\n");
printf("\t0. 退出系統(tǒng)\n");
printf("請(qǐng)選擇操作:");
// 輸入非數(shù)字字符,清空輸入緩沖區(qū)
if (scanf("%d", &choice) != 1)
{
while (getchar() != '\n');
printf("無(wú)效的操作,請(qǐng)重新選擇。\n");
continue;
}
// 當(dāng)輸入數(shù)字字符后,防止緩沖區(qū)中的字符影響自己的選擇
while (getchar() != '\n');
switch (choice)
{
case 1:
addStudent(&head); // 添加學(xué)生信息
break;
case 2:
deleteStudent(&head); // 刪除學(xué)生信息
break;
case 3:
updateStudent(&head); // 更新學(xué)生信息
break;
case 4:
printStudent(&head); // 打印學(xué)生信息
break;
case 5:
searchStudent(&head); // 搜索學(xué)生信息
break;
case 0:
printf("感謝使用學(xué)生管理系統(tǒng),再見(jiàn)!\n");
freeMemory(head); // 釋放內(nèi)存,防止內(nèi)存泄漏
exit(0);
default:
printf("無(wú)效操作,請(qǐng)重新選擇。\n");
}
}
return 0;
}
注意,學(xué)生管理系統(tǒng)是需要手動(dòng)退出的一個(gè)頁(yè)面,所以很多操作都是在一個(gè)循環(huán)里面。
輸出學(xué)生管理系統(tǒng)的文字頁(yè)面 按照一定格式輸出文字,將其美觀排版后輸出即可 // 文字頁(yè)面
printf("--------學(xué)生管理系統(tǒng)--------\n");
printf("\t1. 添加學(xué)生信息\n");
printf("\t2. 刪除學(xué)生信息\n");
printf("\t3. 修改學(xué)生信息\n");
printf("\t4. 顯示學(xué)生列表\n");
printf("\t5. 查找學(xué)生信息\n");
printf("\t0. 退出系統(tǒng)\n");
printf("請(qǐng)選擇操作:");
選擇對(duì)應(yīng)的功能 使用switch語(yǔ)句,每一種case對(duì)應(yīng)一種功能,此外還需要一定的防御性編程,如選擇時(shí)要求輸入數(shù)字字符,消除輸入數(shù)字字符的后面其他無(wú)關(guān)字符的影響 // 輸入非數(shù)字字符,清空輸入緩沖區(qū)
if (scanf("%d", &choice) != 1)
{
while (getchar() != '\n');
printf("無(wú)效的操作,請(qǐng)重新選擇。\n");
continue;
}
// 當(dāng)輸入數(shù)字字符后,防止緩沖區(qū)中的字符影響自己的選擇
while (getchar() != '\n');
switch (choice)
{
case 1:
addStudent(&head); // 添加學(xué)生信息
break;
case 2:
deleteStudent(&head); // 刪除學(xué)生信息
break;
case 3:
updateStudent(&head); // 更新學(xué)生信息
break;
case 4:
printStudent(&head); // 打印學(xué)生信息
break;
case 5:
searchStudent(&head); // 搜索學(xué)生信息
break;
case 0:
printf("感謝使用學(xué)生管理系統(tǒng),再見(jiàn)!\n");
freeMemory(head); // 釋放內(nèi)存,防止內(nèi)存泄漏
exit(0);
default:
printf("無(wú)效操作,請(qǐng)重新選擇。\n");
}
暫停并清空控制臺(tái) 為了讓輸出界面和輸出的結(jié)果更加直觀,所以要求暫停程序觀看,之后清空控制臺(tái)以達(dá)到簡(jiǎn)潔直觀的目的 // 暫停程序
system("pause");
// 清空控制臺(tái)
system("cls");
三、添加學(xué)生信息
錄入學(xué)生信息 添加學(xué)生信息這一環(huán)節(jié)主要是創(chuàng)建一個(gè)結(jié)點(diǎn),結(jié)點(diǎn)中含有填寫(xiě)完的信息,然后把這個(gè)結(jié)點(diǎn)放在鏈表之中。 // 添加學(xué)生信息
void addStudent(Student **head) {
int id;
printf("請(qǐng)輸入學(xué)生id: ");
scanf("%d", &id);
// 判斷是否重復(fù)錄取學(xué)生信息
if (IsExistId(head, id)) {
printf("已存在id為%d的學(xué)生信息!\n", id);
return;
}
// 開(kāi)辟空間,并填寫(xiě)信息
Student *newStudent = (Student *) malloc(sizeof(Student));
newStudent->next = NULL;
char name[50];
float score;
printf("請(qǐng)輸入學(xué)生姓名: ");
scanf("%s", name);
printf("請(qǐng)輸入學(xué)生分?jǐn)?shù): ");
scanf("%f", &score);
newStudent->id = id;
/* 注意字符串賦值的方式 */
strcpy(newStudent->name, name);
newStudent->score = score;
// 尾插法:將結(jié)點(diǎn)插入在鏈表之后
if (*head == NULL) {
*head = newStudent;
}
else
{
Student *temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newStudent;
}
}
插入結(jié)點(diǎn)的方法 插入節(jié)點(diǎn)的兩個(gè)方法:頭插法和尾插法
頭插法:將結(jié)點(diǎn)放在頭部,使之成為新的頭結(jié)點(diǎn) // 頭插法
// 無(wú)論有沒(méi)有頭結(jié)點(diǎn)都可以
newStudent->next = *head;
*head = newStudent;
尾插法:不斷地將結(jié)點(diǎn)插在鏈表尾部 // 尾插法:將結(jié)點(diǎn)插入在鏈表之后
// 情況一,沒(méi)有頭結(jié)點(diǎn)
if (*head == NULL)
{
*head = newStudent;
}
// 情況二,有頭結(jié)點(diǎn)
else
{
Student *temp = *head;
// 一直找到最后一個(gè)結(jié)點(diǎn)
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newStudent;
}
避免重復(fù)錄入學(xué)生信息 為了不重復(fù)錄入學(xué)生信息,定義一個(gè)IsExistId函數(shù),該函數(shù)的實(shí)現(xiàn)就是遍歷鏈表,判斷鏈表中是否存在待錄入學(xué)生的id,如果存在,返回1;否則,返回0。 int IsExistId(Student *head, int id) {
while (head != NULL) {
if (head->id == id) {
return 1;
}
}
return 0;
}
四、刪除學(xué)生信息
刪除學(xué)生信息 這意味著將去除鏈表中指定學(xué)生信息的結(jié)點(diǎn),然后釋放內(nèi)存。 // 刪除學(xué)生信息
void deleteStudent(Student **head) {
int id;
Student *temp = *head;
// 待刪除結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn),用于指向待刪除結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)
Student *prev = NULL;
printf("請(qǐng)輸入要?jiǎng)h除的學(xué)生id: ");
scanf("%d", &id);
// 遍歷鏈表,查找要?jiǎng)h除的學(xué)生結(jié)點(diǎn)位置
while (temp != NULL && temp->id != id) {
prev = temp;
temp = temp->next;
}
// 說(shuō)明鏈表為空,或者到了鏈表尾部,即沒(méi)有找到指定學(xué)生id
if (temp == NULL) {
printf("未找到學(xué)生id為%d的記錄。\n", id);
return;
}
// 如果找到了要?jiǎng)h除的學(xué)生,從鏈表中刪除它
else
{
if (prev == NULL)
{
// 刪除頭節(jié)點(diǎn)
*head = temp->next;
}
else
{
prev->next = temp->next;
}
free(temp);
printf("已刪除學(xué)生id為%d的記錄。\n", id);
}
}
刪除學(xué)生信息結(jié)點(diǎn)有兩個(gè)位置區(qū)分
頭結(jié)點(diǎn)位置:刪除頭結(jié)點(diǎn)后,頭結(jié)點(diǎn)的下一位即為頭結(jié)點(diǎn)其他位置:待刪除結(jié)點(diǎn)的前一位,它的下一位是待刪除結(jié)點(diǎn)的下一位 if (prev == NULL)
{
// 刪除頭節(jié)點(diǎn)
*head = temp->next;
}
else
{
prev->next = temp->next;
}
free(temp);
五、修改學(xué)生信息
遍歷鏈表,找到待修改信息的學(xué)生id即可修改學(xué)生信息
// 修改學(xué)生信息
void updateStudent(Student **head)
{
int id;
Student *temp = *head;
printf("請(qǐng)輸入要修改信息的學(xué)生id: ");
scanf("%d", &id);
while (temp != NULL && temp->id != id)
{
temp = temp->next;
}
// 要么鏈表為空,要么已經(jīng)到鏈表尾部,這兩種情況都是未找到id
if (temp == NULL)
{
printf("未找到學(xué)生id為%d的記錄。\n", id);
}
else
{
printf("請(qǐng)輸入新的姓名和成績(jī):\n");
scanf("%s %f", temp->name, &temp->score);
printf("已更新學(xué)生id為%d的信息。\n", id);
}
}
六、顯示學(xué)生列表
遍歷鏈表,將學(xué)生信息一個(gè)個(gè)打印出來(lái)。這個(gè)過(guò)程是按照鏈表的插入順序進(jìn)行打印輸出的,還可以自己實(shí)現(xiàn)按照id大小排序進(jìn)行輸出,抑或著按照學(xué)生成績(jī)大小排序進(jìn)行輸出。
// 打印學(xué)生信息
void printStudent(Student **head)
{
if (*head == NULL)
{
printf("暫未錄入學(xué)生信息\n");
return;
}
printf("\n學(xué)生信息如下:\n");
Student *temp = *head;
while (temp != NULL)
{
printf("ID:%d,姓名:%s,成績(jī):%.2f\n", temp->id, temp->name, temp->score);
temp = temp->next;
}
}
七、查詢學(xué)生信息
本質(zhì)上還是遍歷鏈表,查看是否存在指定id的人
void searchStudent(Student **head) {
int id;
Student *temp = *head;
printf("輸入待搜索學(xué)生的id: ");
scanf("%d", &id);
while(temp != NULL && temp->id != id) {
temp = temp->next;
}
if (temp == NULL) {
printf("查無(wú)此id:%d信息。", id);
}
else
{
printf("id: %d name: %s score: %.2f\n", id, temp->name, temp->score);
}
}
八、退出程序
退出程序只需要在switch中添加一個(gè)選項(xiàng)即可,在這個(gè)選項(xiàng)中有exit。當(dāng)然,退出程序前,要主動(dòng)釋放內(nèi)存,避免內(nèi)存泄漏。
以下這個(gè)函數(shù)也i將添加在含有exit選項(xiàng)中。
// 釋放內(nèi)存空間
void freeMemory(Student *head)
{
Student *temp;
while (head != NULL)
{
temp = head;
head = head->next;
free(temp);
}
}
九、完整代碼及補(bǔ)充
以上就是學(xué)生管理系統(tǒng)的大致代碼,之后若是學(xué)習(xí)了文件管理相關(guān)的函數(shù),還可以將文件導(dǎo)出保存,將其他的對(duì)應(yīng)格式的學(xué)生信息文件導(dǎo)入進(jìn)行管理。除了文件管理相關(guān)的函數(shù),我們還可以將數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫(kù)中,這些都是之后將會(huì)學(xué)習(xí)的知識(shí)。
完整代碼 #include
#include
#include
// 學(xué)生信息結(jié)構(gòu)體
typedef struct Student
{
int id;
float score; /* 數(shù)據(jù)域 */
char name[50];
struct Student *next; /* 指針域 */
} Student;
int isExistId(Student **head, int id);
void freeMemory(Student *head);
void addStudent(Student **head);
void deleteStudent(Student **head);
void updateStudent(Student **head);
void printStudent(Student **head);
void searchStudent(Student **head);
int main()
{
int choice;
Student *head = NULL; // 學(xué)生鏈表頭指針
while (1)
{
// 暫停程序
system("pause");
// 清空控制臺(tái)
system("cls");
printf("--------學(xué)生管理系統(tǒng)--------\n");
printf("\t1. 添加學(xué)生信息\n");
printf("\t2. 刪除學(xué)生信息\n");
printf("\t3. 修改學(xué)生信息\n");
printf("\t4. 顯示學(xué)生列表\n");
printf("\t5. 查找學(xué)生信息\n");
printf("\t0. 退出系統(tǒng)\n");
printf("請(qǐng)選擇操作:");
// 輸入非數(shù)字字符,清空輸入緩沖區(qū)
if (scanf("%d", &choice) != 1)
{
while (getchar() != '\n')
;
printf("無(wú)效的操作,請(qǐng)重新選擇。\n");
continue;
}
// 當(dāng)輸入數(shù)字字符后,防止緩沖區(qū)中的字符影響自己的選擇
while (getchar() != '\n');
switch (choice)
{
case 1:
addStudent(&head); // 添加學(xué)生信息
break;
case 2:
deleteStudent(&head); // 刪除學(xué)生信息
break;
case 3:
updateStudent(&head); // 更新學(xué)生信息
break;
case 4:
printStudent(&head); // 打印學(xué)生信息
break;
case 5:
searchStudent(&head); // 搜索學(xué)生信息
break;
case 0:
printf("感謝使用學(xué)生管理系統(tǒng),再見(jiàn)!\n");
freeMemory(head); // 釋放內(nèi)存,防止內(nèi)存泄漏
exit(0);
default:
printf("無(wú)效操作,請(qǐng)重新選擇。\n");
}
}
return 0;
}
// 添加學(xué)生信息
void addStudent(Student **head)
{
int id;
printf("請(qǐng)輸入學(xué)生id: ");
scanf("%d", &id);
// 判斷是否重復(fù)錄取學(xué)生信息
if (isExistId(head, id))
{
printf("已存在id為%d的學(xué)生信息!\n", id);
return;
}
// 開(kāi)辟空間,并填寫(xiě)信息
Student *newStudent = (Student *)malloc(sizeof(Student));
newStudent->next = NULL;
char name[50];
float score;
printf("請(qǐng)輸入學(xué)生姓名: ");
scanf("%s", name);
printf("請(qǐng)輸入學(xué)生分?jǐn)?shù): ");
scanf("%f", &score);
newStudent->id = id;
/* 注意字符串賦值的方式 */
strcpy(newStudent->name, name);
newStudent->score = score;
// 尾插法:將結(jié)點(diǎn)插入在鏈表之后
if (*head == NULL)
{
*head = newStudent;
}
else
{
Student *temp = *head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = newStudent;
}
}
// 刪除學(xué)生信息
void deleteStudent(Student **head)
{
int id;
Student *temp = *head;
// 待刪除結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn),用于指向待刪除結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)
Student *prev = NULL;
printf("請(qǐng)輸入要?jiǎng)h除的學(xué)生id: ");
scanf("%d", &id);
// 遍歷鏈表,查找要?jiǎng)h除的學(xué)生結(jié)點(diǎn)位置
while (temp != NULL && temp->id != id)
{
prev = temp;
temp = temp->next;
}
// 如果找到了要?jiǎng)h除的學(xué)生,從鏈表中刪除它
if (temp == NULL)
{
printf("未找到學(xué)生id為%d的記錄。\n", id);
return;
}
else
{
if (prev == NULL)
{
// 刪除頭節(jié)點(diǎn)
*head = temp->next;
}
else
{
prev->next = temp->next;
}
free(temp);
printf("已刪除學(xué)生id為%d的記錄。\n", id);
}
}
// 修改學(xué)生信息
void updateStudent(Student **head)
{
int id;
Student *temp = *head;
printf("請(qǐng)輸入要修改信息的學(xué)生id: ");
scanf("%d", &id);
while (temp != NULL && temp->id != id)
{
temp = temp->next;
}
// 要么鏈表為空,要么已經(jīng)到鏈表尾部,這兩種情況都是未找到id
if (temp == NULL)
{
printf("未找到學(xué)生id為%d的記錄。\n", id);
}
else
{
printf("請(qǐng)輸入新的姓名和成績(jī):\n");
scanf("%s %f", temp->name, &temp->score);
printf("已更新學(xué)生id為%d的信息。\n", id);
}
}
// 打印學(xué)生信息
void printStudent(Student **head)
{
if (*head == NULL)
{
printf("暫未錄入學(xué)生信息\n");
return;
}
printf("\n學(xué)生信息如下:\n");
Student *temp = *head;
while (temp != NULL)
{
printf("ID: %d\t 姓名: %s\t 成績(jī): %.2f\n", temp->id, temp->name, temp->score);
temp = temp->next;
}
}
// 釋放內(nèi)存空間
void freeMemory(Student *head)
{
Student *temp;
while (head != NULL)
{
temp = head;
head = head->next;
free(temp);
}
}
// 判斷鏈表中是否存在指定學(xué)生id
int isExistId(Student **head, int id)
{
Student *temp = *head;
while (temp != NULL)
{
if (temp->id == id)
{
return 1;
}
temp = temp->next;
}
return 0;
}
void searchStudent(Student **head) {
int id;
Student *temp = *head;
printf("輸入待搜索學(xué)生的id: ");
scanf("%d", &id);
while(temp != NULL && temp->id != id) {
temp = temp->next;
}
if (temp == NULL) {
printf("查無(wú)此id:%d信息。\n", id);
}
else
{
printf("id: %d name: %s score: %.2f\n", id, temp->name, temp->score);
}
}
柚子快報(bào)激活碼778899分享:【C語(yǔ)言】學(xué)生管理系統(tǒng)
推薦鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。