教務(wù)管理系統(tǒng)
一、項(xiàng)目需求
本項(xiàng)目管理三種身份人員的信息:
- 管理員(僅一個(gè)):姓名:admin 密碼:
- 教師(多個(gè)):姓名、密碼、工號(hào)、性別、出生日期、
- 學(xué)生(多個(gè)):姓名、密碼、學(xué)號(hào)、性別、出生日期、數(shù)學(xué)、語(yǔ)文、英語(yǔ)三門功課成績(jī)
管理員登錄后可以進(jìn)行如下操作:
- 修改自身登錄密碼
- 添加新教師
- 查看所有教師
- 刪除教師
- 修改教師信息
教師登錄后可以進(jìn)行如下操作:
- 修改自身登錄密碼
- 查閱自身信息
- 添加新學(xué)生
- 刪除學(xué)生
- 查閱指定學(xué)生信息
- 修改學(xué)生信息(姓名、性別、出生日期、三門功課成績(jī))
- 按學(xué)號(hào)從低到高查看所有學(xué)生信息
- 按數(shù)學(xué)成績(jī)從高到低查看所有學(xué)生信息
- 按語(yǔ)文成績(jī)從高到低查看所有學(xué)生信息
- 按英語(yǔ)成績(jī)從高到低查看所有學(xué)生信息
- 按總分從高到低查看所有學(xué)生信息
學(xué)生登錄后可以進(jìn)行如下操作:
- 修改自身登錄密碼
- 查閱自身信息
二、設(shè)計(jì)思路
- 可以先設(shè)計(jì)管理員的功能
- 設(shè)計(jì)老師的功能
- 設(shè)計(jì)學(xué)生的功能`
三、功能實(shí)現(xiàn)
1、數(shù)據(jù)類型可以選擇結(jié)構(gòu)體
2、數(shù)據(jù)結(jié)構(gòu)可以選用帶頭結(jié)點(diǎn)的鏈表來(lái)存儲(chǔ)
一、管理員功能實(shí)現(xiàn)
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
struct adm
{
char name[20];
char ser[20];
};
struct teacher
{
char name[20];
char ser[20];
int num;
char sex[10];
char bir[20];
struct teacher*next;
};
上面就是我們定義好的結(jié)構(gòu)體,定義好了數(shù)據(jù)類型我們可以開(kāi)始搭建框架了。
二、管理員分支函數(shù)框架
void adm_info(void)
{
int x=1;
struct adm s = my_read();
struct teacher *head = NULL;
head = create_node();
head = teacher_read();
while(x)
{
printf("———————————————————————————————————————\n");
printf("歡迎來(lái)到管理員登陸界面!\n");
printf("請(qǐng)輸入姓名:");
char name[20];
scanf("%s",name);
while(getchar() !='\n');
printf("請(qǐng)輸入密碼:");
char ser[20];
scanf("%s",ser);
while(getchar() !='\n');
printf("身份確認(rèn)中...\n");
if(strcmp(s.name,name)==0&&strcmp(s.ser,ser)==0)
{
printf("登陸成功!\n");
break;
}
printf("信息有誤,請(qǐng)核實(shí)姓名和密碼!\n");
printf("———————————————————————————————————————\n");
return;
}
int flag = 1,set,n;
while(flag)
{
printf("——————————————————————————————————\n");
printf("| 管理員功能菜單! |\n");
printf("——————————————————————————————————\n");
printf("|1、修改自身登陸密碼 |\n");
printf("——————————————————————————————————\n");
printf("|2、添加新教師信息 |\n");
printf("——————————————————————————————————\n");
printf("|3、查看所有教師 |\n");
printf("——————————————————————————————————\n");
printf("|4、刪除教師 |\n");
printf("——————————————————————————————————\n");
printf("|5、修改教師信息 |\n");
printf("——————————————————————————————————\n");
printf("|0、返回上一層! |\n");
printf("+————————————————————————————————+\n");
printf("輸入您的選擇: |\n");
printf("——————————————————————————————————\n");
scanf("%d",&set);
while(getchar() != '\n');
switch(set)
{
case 1:mod_ser(&s);break;
case 2:add_teacher(head);break;
case 3:show_teacher(head);
printf("任意健退出顯示,返回上一層!\n");
scanf("%d",&n);
while(getchar() != '\n');
break;
case 4:del_teacher(head);break;
case 5:mod_teacher(head);break;
case 0:flag = 0;break;
default:printf("無(wú)該選項(xiàng)!\n");break;
}
}
adm_write(s);
teacher_write(head);
return;
}
2.1 函數(shù)分析
1、函數(shù)的框架是先進(jìn)入登陸界面
2、利用分支結(jié)構(gòu)實(shí)現(xiàn)管理員的功能
2.2、登錄功能實(shí)現(xiàn)
1、想實(shí)現(xiàn)登錄功能我們需要記住管理員的賬號(hào)和密碼,通過(guò)比較是否相等,從而實(shí)現(xiàn)這個(gè)功能。
2、此處就需要用到文件I/O的相關(guān)知識(shí)了,
2.3、管理員信息的文件保存與讀寫(xiě)函數(shù)
//保存管理員密碼信息 0成功-1失敗
int adm_write(struct adm s)
{
FILE*fp = NULL;
fp = fopen("./adm.txt","w");//打開(kāi)文件
assert(fp != NULL);
int ret;
ret = fprintf(fp,"%s %s\n",s.name,s.ser);//把數(shù)據(jù)傳到文件中
if(ret != EOF)
{
printf("保存管理員數(shù)據(jù)成功!\n");
fclose(fp);//關(guān)閉文件
return 0;
}
return -1;
}
//讀管理員密碼
struct adm my_read()
{
FILE*fp = NULL;
fp = fopen("./adm.txt","r");//打開(kāi)文件
assert(fp != NULL);
struct adm a;
int ret;
ret = fscanf(fp,"%s%s",a.name,a.ser);//讀文件
if(ret != EOF)
printf("讀取管理員數(shù)據(jù)成功!\n");
fclose(fp);//關(guān)閉文件
return a;//返回?cái)?shù)據(jù)
}
2.4、修改管理員密碼
//修改管理員密碼
void mod_ser(struct adm*s)
{
printf("請(qǐng)輸入想修改的密碼:");
scanf("%s",s->ser);
while(getchar() !='\n');
printf("修改成功!\n");
return;
}
下一步就是設(shè)置跟老師相關(guān)的參數(shù)了,我們需要寫(xiě)一個(gè)創(chuàng)建老師信息的節(jié)點(diǎn)函數(shù)和使用頭插法插入老師信息的函數(shù)。
2.5、添加老師信息
//創(chuàng)建老師結(jié)構(gòu)體節(jié)點(diǎn)
struct teacher *create_node()
{
struct teacher *p = NULL;
p = (struct teacher*)malloc(sizeof(struct teacher));//申請(qǐng)堆空間
assert(p != NULL);//條件為真執(zhí)行否則段錯(cuò)誤
p->next = NULL;
return p;//返回地址
}
//帶頭節(jié)點(diǎn)的鏈表來(lái)添加老師信息
void add_teacher(struct teacher*head)
{
int flag = 1;
struct teacher *p = NULL;
p = head->next;
struct teacher *pnew = NULL;
pnew = create_node();
printf("請(qǐng)輸入老師姓名:");
scanf("%s",pnew->name);
while(getchar() != '\n');
printf("請(qǐng)輸入老師密碼:");
scanf("%s",pnew->ser);
while(getchar() != '\n');
while(flag) //防止工號(hào)重復(fù)
{
printf("請(qǐng)輸入工號(hào):");
scanf("%d",&pnew->num);
while(getchar() != '\n');
p = head->next;
while(p!= NULL)
{
if(p->num == pnew->num)//找到相等的工號(hào)p就停止
{
break;
}
p = p->next;
}
if(NULL != p)//說(shuō)明重復(fù)
{
flag = 1;
}
else
{
break;
}
}
printf("請(qǐng)輸入性別:");
scanf("%s",pnew->sex);
while(getchar() != '\n');
printf("請(qǐng)輸入出生日期例如(19980312):");
scanf("%s",pnew->bir);
while(getchar() != '\n');
//頭插法插入數(shù)據(jù)
pnew->next = head->next;
head->next = pnew;
printf("添加老師信息成功!\n");
return;
}
因?yàn)樯婕暗胶竺娴睦蠋煹卿?,和修改老師信息所以我們,還需要做一個(gè)讀寫(xiě)老師數(shù)據(jù)到文件的函數(shù)。
2.6、老師信息的文件I/O函數(shù)
//讀取老師信息
struct teacher*teacher_read()
{
FILE*fp = NULL;
fp = fopen("./teacher.txt","r");
assert(fp != NULL);
//開(kāi)始讀取數(shù)據(jù)
int ret;
struct teacher *pnew = NULL,*head = NULL,*newhead = NULL;
head = create_node();
while(1)
{
pnew = create_node();//創(chuàng)建新的節(jié)點(diǎn)
ret = fscanf(fp,"%s%s%d%s%s",pnew->name,pnew->ser,&pnew->num,pnew->sex,pnew->bir);
if(ret == EOF)//ret == EOF讀取到末尾
{
break;
}
pnew->next = newhead;
newhead = pnew;
}
free(pnew);//釋放多出來(lái)的一個(gè)節(jié)點(diǎn)
fclose(fp);
printf("讀取老師數(shù)據(jù)成功!\n");
head->next = newhead;
return head;
}
//保存老師的數(shù)據(jù)
int teacher_write(struct teacher*head)
{
FILE*fp = NULL;//打開(kāi)文件
fp = fopen("./teacher.txt","w");
assert(fp != NULL);
int ret;
struct teacher *p = head->next;
while(p != NULL)
{
ret = fprintf(fp,"%s\t%s\t%d\t%s\t%s\n",p->name,p->ser,p->num,p->sex\
,p->bir);//寫(xiě)操作
if(ret == EOF)
{
break;
}
p = p->next;
}
if(p == NULL)
printf("保存老師數(shù)據(jù)成功!\n");
fclose(fp);//關(guān)閉文件
return 0;
}
添加信息后,當(dāng)然需要可以顯示和查找老師的信息咯。所以接下來(lái)就來(lái)實(shí)現(xiàn)這兩個(gè)功能吧
2.7、老師信息的查找和顯示
//帶頭節(jié)點(diǎn)顯示老師的信息
void show_teacher(struct teacher *head)
{
if(head->next == NULL)//入?yún)z測(cè)
{
printf("無(wú)老師信息!\n");
}
struct teacher *p = head->next;
while(p!= NULL)
{
printf("姓名:%s\t密碼:%s\t工號(hào):%d\t性別:%s\t出生:%s\n",p->name,\
p->ser,p->num,p->sex,p->bir);
p = p->next;
}
return ;
}
//通過(guò)工號(hào)查找老師的信息
struct teacher*search_teacher(struct teacher*head,int num)
{
struct teacher *ps = NULL,*p = NULL;
p = head->next;
while(p != NULL)
{
if(p->num == num)
{
ps = p;
}
p = p->next;
}
if(ps == NULL)
{
printf("無(wú)該老師信息!\n");
}
return ps;
}
可以添加可以查找可以顯示,但是我們還缺少編輯老師信息的函數(shù),所以接下來(lái)可以創(chuàng)建刪除老師信息,和修改老師信息的函數(shù)。
2.8、老師信息的刪除
//通過(guò)工號(hào)刪除老師信息
void del_teacher(struct teacher*head)
{
struct teacher *pdel = NULL,*p = NULL;
p = head->next;
if(p ==NULL)
{
printf("無(wú)老師信息無(wú)法刪除!\n");
return;
}
int num;
printf("請(qǐng)輸入想刪除老師工號(hào):");
scanf("%d",&num);
while(p != NULL)
{
if(p->num == num)
{
pdel = p;
break;
}
p = p->next;
}
//頭刪
if(pdel == head->next)
{
head->next = pdel->next;
printf("刪除成功!\n");
free(pdel);
return ;
}
//尾刪中間刪
p = head->next;
while(p != NULL)
{
if(p->next == pdel)
{
break;
}
p = p->next;
}
p->next = pdel->next;
free(pdel);//釋放刪掉的節(jié)點(diǎn)
printf("刪除成功!\n");
return;
}
2.9、老師信息各項(xiàng)的單獨(dú)修改
分析:其實(shí)從標(biāo)題就可以看出因?yàn)樾枰羞x擇的修改,所以需要用到分支結(jié)構(gòu),然后通過(guò)選擇實(shí)現(xiàn)單獨(dú)的修改操作,無(wú)非就是一個(gè)子菜單了。
//修改老師信息
void mod_teacher(struct teacher*head)
{
printf("請(qǐng)輸入想修改老師的工號(hào):");
int num;
scanf("%d",&num);
struct teacher *pmod = NULL;
pmod = search_teacher(head,num);
int set,flag = 1;
while(flag)
{
printf("+———————————————————+\n");
printf("| 修改老師信息菜單 |\n");
printf("+———————————————————+\n");
printf("|1 修改姓名 |\n");
printf("+———————————————————+\n");
printf("|2 修改密碼 |\n");
printf("+———————————————————+\n");
printf("|3 修改性別 |\n");
printf("+———————————————————+\n");
printf("|4 修改出生日期 |\n");
printf("+———————————————————+\n");
printf("|0 返回上一層 |\n");
printf("+———————————————————+\n");
printf(" 請(qǐng)輸入你的選擇:");
scanf("%d",&set);
while(getchar() != '\n');
switch(set)
{
case 1:printf("輸入新的姓名:");
scanf("%s",pmod->name);
while(getchar() != '\n');
break;
case 2:printf("輸入新的密碼:");
scanf("%s",pmod->ser);
while(getchar() != '\n');
break;
case 3:printf("輸入新的性別:");
scanf("%s",pmod->sex);
while(getchar() != '\n');
break;
case 4:printf("輸入新的生日:");
scanf("%s",pmod->bir);
while(getchar() != '\n');
break;
case 0:flag = 0;break;
default:printf("無(wú)此功能!\n");break;
}
}
}
小結(jié)
到目前為止我們已經(jīng)寫(xiě)好了管理者這個(gè)小分支的所有功能了,目前我們能做到的功能有如下:
1、加載管理員的信息和保存管理員的信息。
2、加載老師和保存老師的信息
3、修改和添加老師的信息。
三、老師分支函數(shù)的創(chuàng)建
3.1、函數(shù)分析
1.修改自身登錄密碼
2. 查閱自身信息
2. 添加新學(xué)生
3. 刪除學(xué)生
4. 查閱指定學(xué)生信息
5. 修改學(xué)生信息(姓名、性別、出生日期、三門功課成績(jī))
6. 按學(xué)號(hào)從低到高查看所有學(xué)生信息
7. 按數(shù)學(xué)成績(jī)從高到低查看所有學(xué)生信息
8. 按語(yǔ)文成績(jī)從高到低查看所有學(xué)生信息
9. 按英語(yǔ)成績(jī)從高到低查看所有學(xué)生信息
10. 按總分從高到低查看所有學(xué)生信息
從功能上我們不難看出我們需要先進(jìn)行一個(gè)登錄,這里就需要加載之前保存好的老師數(shù)據(jù),我們已經(jīng)寫(xiě)好,然后需要對(duì)學(xué)生進(jìn)行操作,很明顯需要定義關(guān)于學(xué)生的結(jié)構(gòu)體,整體的框架跟管理員的并沒(méi)有什么不同,想好了就可以直接動(dòng)手敲代碼了。
3.2、創(chuàng)建學(xué)生的結(jié)構(gòu)體
#pragma once
#include"adm.h"
struct stu
{
char name[30];
char ser[30];
int num;
char sex[10];
char bir[15];
float math;
struct stu*next;
float chinese;
float english;
};
typedef struct stu STU;
因?yàn)樾枰玫焦芾韱T里面的一些函數(shù)所以之前創(chuàng)建好的函數(shù)一定要都在管理員.h文件進(jìn)行聲明,這樣老師分支這邊調(diào)用只需要包含管理員那邊的頭文件即可,避免重復(fù)勞動(dòng)。
3.3、老師分支的函數(shù)主框架
void teacher_info()
{
int x=1;
struct teacher *head = NULL;
head = create_node();
head = teacher_read();
STU*stu_head = NULL;
stu_head = create_stu_node();
stu_head = read_stu();
TEACH*s = NULL;
while(x)
{
printf("———————————————————————————————————————\n");
printf("歡迎來(lái)到老師登陸界面!\n");
printf("請(qǐng)輸入工號(hào):");
int num;
scanf("%d",&num);
while(getchar() !='\n');
printf("請(qǐng)輸入密碼:");
char ser[20];
scanf("%s",ser);
while(getchar() !='\n');
printf("身份確認(rèn)中...\n");
s = search_teacher(head,num);
if(NULL == s)
{
printf("登陸失敗!\n");
return;
}
if(s->num == num && strcmp(s->ser,ser)==0)
{
printf("登陸成功!\n");
x = 0;
break;
}
else
{
printf("信息有誤,請(qǐng)核實(shí)工號(hào)和密碼!\n");
printf("———————————————————————————————————————\n");
return;
}
}
int flag = 1,set,n;
while(flag)
{
printf("——————————————————————————————————————————————\n");
printf("| 老師功能菜單! |\n");
printf("——————————————————————————————————————————————\n");
printf("|1、 修改自身登陸密碼 |\n");
printf("——————————————————————————————————————————————\n");
printf("|2、 查閱自身信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|3、 添加新學(xué)生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|4、 刪除學(xué)生 |\n");
printf("——————————————————————————————————————————————\n");
printf("|5、 查閱指定學(xué)生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|6、 修改學(xué)生信息(性別、姓名、出生日期、成績(jī))|\n");
printf("——————————————————————————————————————————————\n");
printf("|7、 按學(xué)號(hào)從低到高查看所有學(xué)生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|8、 按數(shù)學(xué)成績(jī)從高到低查看所有學(xué)生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|9、 按語(yǔ)文成績(jī)從高到低查看所有學(xué)生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|10、按英語(yǔ)成績(jī)從高到低查看所有學(xué)生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|11、按總分從高到低查看所有學(xué)生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|0、 返回上一層 |\n");
printf("——————————————————————————————————————————————\n");
printf("輸入您的選擇:");
scanf("%d",&set);
while(getchar() != '\n');
switch(set)
{
case 1:mod_teacher_ser(s);break;
case 0:flag = 0;break;
case 2:
printf("姓名:%s\t密碼:%s\t工號(hào):%d\t性別:%s\t出生:%s\n",\
s->name,s->ser,s->num,s->sex,s->bir);break;
case 3:add_stu_info(stu_head);break;
case 5:show_stu_info_by_num(stu_head);break;
case 4:del_stu_info(stu_head);break;
case 6:mod_stu_info_by_num(stu_head);break;
case 7:sortup_by_num(stu_head);
printf("任意健退出顯示,返回上一層!");
scanf("%d",&n);
while(getchar() != '\n');
break;
case 8:sortdown_by_math(stu_head);
printf("任意健退出顯示,返回上一層!\n");
scanf("%d",&n);
while(getchar() != '\n');
break;
case 9:sortdown_by_chinese(stu_head);
printf("任意健退出顯示,返回上一層!\n");
scanf("%d",&n);
while(getchar() != '\n');
break;
case 10:sortdown_by_english(stu_head);
printf("任意健退出顯示,返回上一層!\n");
scanf("%d",&n);
while(getchar() != '\n');
break;
case 11:sortdown_by_allscore(stu_head);
printf("任意健退出顯示,返回上一層!\n");
scanf("%d",&n);
while(getchar() != '\n');
break;
default:printf("沒(méi)有這個(gè)功能!\n");break;
}
}
teacher_write(head);
write_stu(stu_head);
return;
}
同樣也是先登錄成功,然后在進(jìn)行后續(xù)的功能,前面有思路分析這里就不贅述了。
3.4、老師分支修改自身密碼
#include "teacher.h"
//修改老師密碼
void mod_teacher_ser(TEACH*p)
{
printf("請(qǐng)輸入新的密碼:");
scanf("%s",p->ser);
while(getchar() != '\n');
printf("修改成功!\n");
return ;
}
3.5、添加學(xué)生信息
//創(chuàng)建學(xué)生節(jié)點(diǎn)
STU*create_stu_node()
{
STU*pnew = NULL;
pnew = (STU*)malloc(sizeof(STU));
assert(pnew != NULL);
pnew->next = NULL;
return pnew;
}
//增加學(xué)生信息帶頭節(jié)點(diǎn)
void add_stu_info(STU*stu_head)
{
STU*pnew = NULL;
pnew = create_stu_node();
printf("請(qǐng)輸入學(xué)生姓名:");
scanf("%s",pnew->name);
while(getchar() != '\n');
printf("請(qǐng)輸入學(xué)生密碼:");
scanf("%s",pnew->ser);
while(getchar() != '\n');
int flag = 1;
STU*p = stu_head->next;
while(flag) //防止學(xué)號(hào)重復(fù)
{
printf("請(qǐng)輸入學(xué)號(hào):");
scanf("%d",&pnew->num);
while(getchar() != '\n');
p = stu_head->next;
while(p!= NULL)
{
if(p->num == pnew->num)
{
break;//重復(fù)就退出循環(huán)
}
p = p->next;
}
if(NULL == p)//不重復(fù)退出循環(huán)
{
break;
}
}
printf("請(qǐng)輸入性別:");
scanf("%s",pnew->sex);
while(getchar() != '\n');
printf("請(qǐng)輸入出生日期例如(1998-03-12):");
scanf("%s",pnew->bir);
while(getchar() != '\n');
printf("請(qǐng)輸入數(shù)學(xué)成績(jī):");
scanf("%f",&pnew->math);
while(getchar() != '\n');
printf("請(qǐng)輸入語(yǔ)文成績(jī):");
scanf("%f",&pnew->chinese);
while(getchar() != '\n');
printf("請(qǐng)輸入英語(yǔ)成績(jī):");
scanf("%f",&pnew->english);
while(getchar() != '\n');
// 頭插
pnew->next = stu_head->next;
stu_head->next = pnew;
printf("添加學(xué)生信息成功!\n");
return ;
}
這里其實(shí)有一個(gè)比較重要的點(diǎn)就是如何防止學(xué)號(hào)重復(fù),這里簡(jiǎn)單的分析一下提供幾個(gè)思路:
1、可以考慮用全局靜態(tài)變量,每次讀取,或者添加一個(gè)學(xué)生數(shù)據(jù)就自增一下,刪除就自減。
2、可以考慮添加一個(gè)判斷,學(xué)號(hào)重復(fù)就遞歸調(diào)用本身,不重復(fù)就執(zhí)行下一步。
3、就是我用的方法,直接循環(huán)解決問(wèn)題。
3.6、學(xué)生信息的文件I/O操作
//寫(xiě)學(xué)生信息到文件
int write_stu(STU*head)
{
FILE*fp = NULL;//打開(kāi)文件
fp = fopen("./student.txt","w");
assert(fp != NULL);
int ret;
STU *p = head->next;
while(p != NULL)//寫(xiě)操作
{
ret = fprintf(fp,"%s\t%s\t%d\t%s\t%s\t%.2f\t%.2f\t%.2f\n"\
,p->name,p->ser,p->num,p->sex,p->bir,p->math,p->chinese,p->english);
if(ret == EOF)
{
break;
}
p = p->next;
}
if(p == NULL)
printf("保存學(xué)生數(shù)據(jù)成功!\n");
fclose(fp);//關(guān)閉文件
return 0;
}
//讀學(xué)生文件操作
STU*read_stu()
{
FILE*fp = NULL;//打開(kāi)文件
fp = fopen("./student.txt","r");
assert(fp != NULL);
int ret;
STU *pnew = NULL,*head = NULL,*newhead = NULL;
head = create_stu_node();//創(chuàng)建一個(gè)頭節(jié)點(diǎn)
while(1)
{
pnew = create_stu_node();//新的節(jié)點(diǎn)接受數(shù)據(jù)
ret = fscanf(fp,"%s%s%d%s%s%f%f%f",\
pnew->name,pnew->ser,&pnew->num,pnew->sex,\
pnew->bir,&pnew->math,&pnew->chinese,&pnew->english);
if(ret == EOF)//讀到末尾
{
break;
}
//頭插
pnew->next = newhead;
newhead = pnew;
}
free(pnew);//釋放多余的節(jié)點(diǎn)
fclose(fp);//關(guān)閉文件
printf("讀取學(xué)生數(shù)據(jù)成功!\n");
head->next = newhead;
return head;
}
3.7、刪除學(xué)生信息通過(guò)學(xué)號(hào)
//刪除學(xué)生信息
void del_stu_info(STU*head)
{
STU *pdel = NULL,*p = NULL;
p = head->next;//入?yún)z查
if(p ==NULL)
{
printf("無(wú)學(xué)生信息無(wú)法刪除!\n");
return;
}
int num;
printf("請(qǐng)輸入想刪除學(xué)生學(xué)號(hào):");
scanf("%d",&num);
while(getchar() != '\n');
while(p != NULL)
{
if(p->num == num)
{
pdel = p;
break;//找到目標(biāo)
}
p = p->next;
}
// pdel = search_teacher(head,num);
if(pdel == head->next)//頭刪
{
head->next = pdel->next;
printf("刪除學(xué)生信息成功!\n");
free(pdel);
return ;
}
p = head->next;
//中間刪和尾刪
while(p != NULL)
{
if(p->next == pdel)
{
break;
}
p = p->next;
}
p->next = pdel->next;
free(pdel);//釋放刪除的節(jié)點(diǎn)
printf("刪除學(xué)生信息成功!\n");
return;
}
其實(shí)這里只提供了一種方法,還可以考慮通過(guò)名字,或者其他的方式,但是因?yàn)槲覀冊(cè)O(shè)定學(xué)號(hào)不可以重復(fù)具有唯一性,所以選擇了這個(gè)方法。
3.8、學(xué)生信息的查找
//通過(guò)學(xué)號(hào)顯示特定學(xué)生的信息
void show_stu_info_by_num(STU*head)
{
if(head->next == NULL)//入?yún)z查
{
printf("還沒(méi)有這個(gè)學(xué)生信息!\n");
return;
}
printf("請(qǐng)輸入想查找的學(xué)生學(xué)號(hào):");
int num;
scanf("%d",&num);
while(getchar() != '\n');
STU*p = NULL;
p = head->next;
STU*ps = NULL;
while(p != NULL)
{
if(p->num == num)
{
ps = p;//找到目標(biāo)
break;
}
p = p->next;
}
//顯示
if(ps != NULL)
{
printf("姓名:%s\t密碼:%s\t學(xué)號(hào):%d\t性別:%s\t出生:%s\t數(shù)學(xué)分?jǐn)?shù):%.2f\t語(yǔ)文分?jǐn)?shù):%.2f\t英語(yǔ)分?jǐn)?shù)%.2f\n",p->name,p->ser,p->num,p->sex,p->bir,\
p->math,p->chinese,p->english);
return ;
}
printf("沒(méi)有這個(gè)學(xué)生信息!\n");
return;
}
同樣的原因我們還是使用學(xué)號(hào)作為查找依據(jù)。
3.9、學(xué)生信息的修改
//修改學(xué)生信息通過(guò)學(xué)號(hào)
void mod_stu_info_by_num(STU*head)
{
printf("請(qǐng)輸入想修改學(xué)生的學(xué)號(hào):");
int num;
scanf("%d",&num);
while(getchar() !='\n');
STU *pmod = NULL;
if(head->next == NULL)//入?yún)z測(cè)
{
printf("還沒(méi)有這個(gè)學(xué)生!\n");
return;
}
STU*p = NULL;
p = head->next;
while(p != NULL)
{
if(p->num == num)
{
pmod = p;//找到目標(biāo)
break;
}
p = p->next;
}
int set,flag = 1;
while(flag)
{
printf("——————————————————————————\n");
printf("| 修改學(xué)生信息菜單! |\n");
printf("——————————————————————————\n");
printf("|1 修改姓名 |\n");
printf("——————————————————————————\n");
printf("|2 修改密碼 |\n");
printf("——————————————————————————\n");
printf("|3 修改性別 |\n");
printf("——————————————————————————\n");
printf("|4 修改出生日期 |\n");
printf("——————————————————————————\n");
printf("|5 修改數(shù)學(xué)成績(jī) |\n");
printf("——————————————————————————\n");
printf("|6 修改語(yǔ)文成績(jī) |\n");
printf("——————————————————————————\n");
printf("|7 修改英語(yǔ)成績(jī) |\n");
printf("——————————————————————————\n");
printf("|0 返回上一層 |\n");
printf("——————————————————————————\n");
printf("|請(qǐng)輸入你的選擇 |\n");
printf("——————————————————————————\n");
scanf("%d",&set);
switch(set)
{
case 1:printf("輸入新的姓名:");
scanf("%s",pmod->name);
while(getchar() != '\n');
break;
case 2:printf("輸入新的密碼:");
scanf("%s",pmod->ser);
while(getchar() != '\n');
break;
case 3:printf("輸入新的性別:");
scanf("%s",pmod->sex);
while(getchar() != '\n');
break;
case 4:printf("輸入新的生日:");
scanf("%s",pmod->bir);
while(getchar() != '\n');
break;
case 5:printf("輸入新的數(shù)學(xué)成績(jī):");
scanf("%f",&pmod->math);
while(getchar() != '\n');
break;
case 6:printf("輸入新的語(yǔ)文成績(jī):");
scanf("%f",&pmod->chinese);
while(getchar() != '\n');
break;
case 7:printf("輸入新的英語(yǔ)成績(jī):");
scanf("%f",&pmod->english);
while(getchar() != '\n');
break;
case 0:flag = 0;break;
default:printf("無(wú)此功能!\n");break;
}
}
printf("修改學(xué)生信息成功!\n");
return;
}
這個(gè)和管理員修改老師信息一樣,我們同樣做了一個(gè)子菜單方便操作。
3.9、排序
其實(shí)無(wú)論是根據(jù)什么排序原理其實(shí)都差不多,無(wú)非是改變一下判別條件,這邊就不做詳細(xì)的介紹了。
//學(xué)號(hào)升序
void sortup_by_num(STU*head)
{
if(head->next == NULL)
{
printf("還沒(méi)有學(xué)生信息!\n");
return;
}
STU*head1 = head->next;
STU*p = NULL;
STU*pmax = NULL;
head->next = NULL;
STU*newhead = NULL;
/*排序*/
while(head1 != NULL)
{
p = head1;
pmax = head1;
while(p != NULL)
{
if(pmax->num < p->num)//找出最大值
{
pmax = p;
}
p = p->next;
}
if(pmax == head1)//移除最大值
{
head1 = head1->next;
}
else
{
p = head1;
while(p->next != pmax)
{
p = p->next;
}
p->next = pmax->next;
}
/*插入最大值*/
pmax->next = NULL;
pmax->next = newhead;
newhead = pmax;
}
head->next = newhead;
/*展示排序后的鏈表*/
p = head->next;
printf("學(xué)號(hào)從低到高開(kāi)始顯示!\n");
while(p != NULL)
{
printf("姓名:%s\t密碼:%s\t學(xué)號(hào):%d\t性別:%s\t出生:%s\t數(shù)學(xué)分?jǐn)?shù):%.2f\t語(yǔ)文分?jǐn)?shù):%.2f\t英語(yǔ)分?jǐn)?shù)%.2f\n",\
p->name,p->ser,p->num,p->sex,p->bir,p->math,p->chinese,p->english);
p = p->next;
}
return;
}
//數(shù)學(xué)成績(jī)降序排列
void sortdown_by_math(STU*head)
{
if(head->next == NULL)
{
printf("還沒(méi)有學(xué)生信息!\n");
return;
}
STU*head1 = head->next;
STU*p = NULL;
STU*pmin = NULL;
head->next = NULL;
STU*newhead = NULL;
/*排序*/
while(head1 != NULL)
{
p = head1;
pmin = head1;
while(p != NULL)
{
if(pmin->math > p->math)//找出最大值
{
pmin = p;
}
p = p->next;
}
if(pmin == head1)//移除最大值
{
head1 = head1->next;
}
else
{
p = head1;
while(p->next != pmin)
{
p = p->next;
}
p->next = pmin->next;
}
/*插入最大值*/
pmin->next = NULL;
pmin->next = newhead;
newhead = pmin;
}
head->next = newhead;
/*展示排序后的鏈表*/
p = head->next;
printf("數(shù)學(xué)成績(jī)從高到底開(kāi)始顯示!\n");
while(p != NULL)
{
printf("姓名:%s\t密碼:%s\t學(xué)號(hào):%d\t性別:%s\t出生:%s\t數(shù)學(xué)分?jǐn)?shù):%.2f\t語(yǔ)文分?jǐn)?shù):%.2f\t英語(yǔ)分?jǐn)?shù)%.2f\n",p->name,p->ser,p->num,p->sex,p->bir,\
p->math,p->chinese,p->english);
p = p->next;
}
return;
}
//語(yǔ)文成績(jī)降序排列
void sortdown_by_chinese(STU*head)
{
if(head->next == NULL)
{
printf("還沒(méi)有學(xué)生信息!\n");
return;
}
STU*head1 = head->next;
STU*p = NULL;
STU*pmin = NULL;
head->next = NULL;
STU*newhead = NULL;
/*排序*/
while(head1 != NULL)
{
p = head1;
pmin = head1;
while(p != NULL)
{
if(pmin->chinese > p->chinese)//找出最大值
{
pmin = p;
}
p = p->next;
}
if(pmin == head1)//移除最大值
{
head1 = head1->next;
}
else
{
p = head1;
while(p->next != pmin)
{
p = p->next;
}
p->next = pmin->next;
}
/*插入最大值*/
pmin->next = NULL;
pmin->next = newhead;
newhead = pmin;
}
head->next = newhead;
/*展示排序后的鏈表*/
p = head->next;
printf("語(yǔ)文成績(jī)從高到底開(kāi)始顯示!\n");
while(p != NULL)
{
printf("姓名:%s\t密碼:%s\t學(xué)號(hào):%d\t性別:%s\t出生:%s\t數(shù)學(xué)分?jǐn)?shù):%.2f\t語(yǔ)文分?jǐn)?shù):%.2f\t 英語(yǔ)分?jǐn)?shù)%.2f\n",\
p->name,p->ser,p->num,p->sex,p->bir,p->math,p->chinese,p->english);
p = p->next;
}
return;
}
//英語(yǔ)成績(jī)降序排列
void sortdown_by_english(STU*head)
{
if(head->next == NULL)
{
printf("還沒(méi)有學(xué)生信息!\n");
return;
}
STU*head1 = head->next;
STU*p = NULL;
STU*pmin = NULL;
head->next = NULL;
STU*newhead = NULL;
/*排序*/
while(head1 != NULL)
{
p = head1;
pmin = head1;
while(p != NULL)
{
if(pmin->english > p->english)//找出最大值
{
pmin = p;
}
p = p->next;
}
if(pmin == head1)//移除最大值
{
head1 = head1->next;
}
else
{
p = head1;
while(p->next != pmin)
{
p = p->next;
}
p->next = pmin->next;
}
/*插入最大值*/
pmin->next = NULL;
pmin->next = newhead;
newhead = pmin;
}
head->next = newhead;
/*展示排序后的鏈表*/
p = head->next;
printf("英語(yǔ)成績(jī)從高到底開(kāi)始顯示!\n");
while(p != NULL)
{
printf("姓名:%s\t密碼:%s\t學(xué)號(hào):%d\t性別:%s\t出生:%s\t數(shù)學(xué)分?jǐn)?shù):%.2f\t語(yǔ)文分?jǐn)?shù):%.2f\t 英語(yǔ)分?jǐn)?shù)%.2f\n",p->name,p->ser,p->num,p->sex,p->bir,p->math,p->chinese,p->english);
p = p->next;
}
return;
}
//總分降序排列
void sortdown_by_allscore(STU*head)
{
if(head->next == NULL)
{
printf("還沒(méi)有學(xué)生信息!\n");
return;
}
STU*head1 = head->next;
STU*p = NULL;
STU*pmin = NULL;
head->next = NULL;
STU*newhead = NULL;
/*排序*/
while(head1 != NULL)
{
p = head1;
pmin = head1;
while(p != NULL)
{
if(pmin->english+pmin->math+pmin->chinese > p->math+p->chinese+p->english)//找出最大值
{
pmin = p;
}
p = p->next;
}
if(pmin == head1)//移除最大值
{
head1 = head1->next;
}
else
{
p = head1;
while(p->next != pmin)
{
p = p->next;
}
p->next = pmin->next;
}
/*插入最大值*/
pmin->next = NULL;
pmin->next = newhead;
newhead = pmin;
}
head->next = newhead;
/*展示排序后的鏈表*/
p = head->next;
printf("總成績(jī)從高到底開(kāi)始顯示!\n");
while(p != NULL)
{
printf("姓名:%s\t總分:%.2f\t密碼:%s\t學(xué)號(hào):%d\t性別:%s\t出生:%s\t數(shù)學(xué)分?jǐn)?shù):%.2f\t語(yǔ)文分?jǐn)?shù):%.2f\t英語(yǔ)分?jǐn)?shù)%.2f\n",p->name,(p->math+p->chinese+p->english),p->ser,p->num,\
p->sex,p->bir,p->math,p->chinese,p->english);
p = p->next;
}
return;
}
小結(jié):
其實(shí)很容易可以發(fā)現(xiàn),老師分支的很多操作跟管理員分支差不多,我們只需要讓兩者很好的聯(lián)系起來(lái)就行了。這邊主要就是把握程序的一個(gè)整體框架,至于具體每個(gè)分支所需要的知識(shí)和難點(diǎn)就不做詳細(xì)介紹了。
四、學(xué)生分支函數(shù)
學(xué)生這邊其實(shí)就比較簡(jiǎn)單了,比起前面的老師分支,我們只需要很短的時(shí)間就可以做出來(lái)。
#include "stu.h"
//修改學(xué)生密碼
void mod_stu_ser(STU*p)
{
printf("請(qǐng)輸入新的密碼:");
scanf("%s",p->ser);
while(getchar() != '\n');
printf("修改成功!\n");
return ;
}
//查找學(xué)生信息
STU*search_stu(STU*head,int num)
{
STU *ps = NULL,*p = NULL;
p = head->next;
while(p != NULL)
{
if(p->num == num)
{
ps = p;
}
p = p->next;
}
if(ps == NULL)
{
printf("無(wú)該學(xué)生信息!\n");
}
return ps;
}
void stu_info()
{
STU*head = NULL;
head = create_stu_node();
head = read_stu();
STU*s = NULL;
int flag = 1;
int num;
char ser[20];
while(flag)
{
printf("——————————————————————————\n");
printf(" 歡迎來(lái)到學(xué)生登陸頁(yè)面!\n");
printf("請(qǐng)輸入您的學(xué)號(hào):");
scanf("%d",&num);
while(getchar() != '\n');
printf("請(qǐng)輸入您的密碼:");
scanf("%s",ser);
while(getchar() != '\n');
printf("登陸中...\n");
printf("——————————————————————————\n");
s = search_stu(head,num);
if(NULL == s)
{
printf("登陸失??!\n");
return;
}
if(s->num == num && strcmp(s->ser,ser)==0)
{
printf("登陸成功!\n");
break;
}
else
{
printf("信息有誤,請(qǐng)核實(shí)學(xué)號(hào)和密碼!\n");
printf("———————————————————————————————————————\n");
return;
}
}
int x = 1,set;
while(x)
{
printf("————————————————————————————————\n");
printf("| 學(xué)生功能菜單! |\n");
printf("————————————————————————————————\n");
printf("|1、修改密碼 |\n");
printf("————————————————————————————————\n");
printf("|2、查閱信息 |\n");
printf("————————————————————————————————\n");
printf("|0、返回上一層 |\n");
printf("————————————————————————————————\n");
printf("|請(qǐng)輸入您的選擇 |\n");
printf("————————————————————————————————\n");
scanf("%d",&set);
while(getchar() != '\n');
switch(set)
{
case 1:mod_stu_ser(s);break;
case 0:x = 0;break;
case 2:
printf("姓名:%s\t密碼:%s\t學(xué)號(hào):%d\t性別:%s\t出生:%s\t數(shù)學(xué)分?jǐn)?shù):%.2f\t語(yǔ)文分?jǐn)?shù):%.2f\t英語(yǔ)分?jǐn)?shù)%.2f\n",s->name,s->ser,s->num,\
s->sex,s->bir,s->math,s->chinese,s->english);break;
default:printf("還沒(méi)有這個(gè)功能!\n");break;
}
}
write_stu(head);
return;
}
4.1、需要用到的頭文件如下
#pragma once
#include "teacher.h"
void stu_info();
到這里差不多就結(jié)束了各個(gè)分支的函數(shù)編寫(xiě),只需要再來(lái)一個(gè)主函數(shù),把他們連起來(lái)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-480380.html
五、主函數(shù)連接
#include <stdio.h>
#include "teacher.h"
#include "adm.h"
#include "stu.h"
int main(){
int set,flag = 1;
while(flag)
{
printf("————————————————————————————————————\n");
printf("| 歡迎進(jìn)入教務(wù)管理系統(tǒng)! |\n");
printf("————————————————————————————————————\n");
printf("|1、管理員登陸 |\n");
printf("————————————————————————————————————\n");
printf("|2、老師登陸 |\n");
printf("————————————————————————————————————\n");
printf("|3、學(xué)生登陸 |\n");
printf("————————————————————————————————————\n");
printf("|0、退出! |\n");
printf("————————————————————————————————————\n");
printf("請(qǐng)輸入您的身份選擇:");
scanf("%d",&set);
while(getchar() != '\n');
switch(set)
{
case 1:adm_info();break;
case 2:teacher_info();break;
case 3:stu_info();break;
case 0:flag = 0;printf("成功退出系統(tǒng)!\n");break;
default:printf("無(wú)此選項(xiàng)!\n");break;
}
}
return 0;
}
總結(jié)
通過(guò)以上步驟,我們就實(shí)現(xiàn)了開(kāi)頭想要實(shí)現(xiàn)的功能,這只能算是一個(gè)很粗糙的小項(xiàng)目了,還有很多可以完善的地方。總的來(lái)說(shuō),有了這種基本的思路,想增加什么功能,往里面有序的添加就好。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-480380.html
到了這里,關(guān)于如何用C語(yǔ)言寫(xiě)一個(gè)簡(jiǎn)單的教務(wù)管理系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!