目录
一、目标
1. 数据结构课程利用项目化教学模式符合现代教学改革需要,也适合数据结构课程改革需求,提高学生实践技能,为企业培养需要的应用型高级技术人才。
2. 通过互联网在线学习方式,使学生能够掌握数据结构的基本知识和技巧,同时熟悉数据结构在实际问题中应用的基本知识,达到能独立使用合适的数据结构实现数据保存与操作的能力。
3. 提供运用数据结构知识以及高级编程语言解决非数值实际问题的能力。
4. 在完成基本知识教学的同时,通过实践环节,强化对学生动手能力的培养与训练。
二、开发环境
技术指标 | 技术参数 |
开发工具 | Vscode/dev-c++ |
使用技术 | C语言 |
三、任务要求
3.1.1任务
要求完成一个小型系统的建设,具体内容如下:
题目1:学生成绩管理系统
(1)任务:要求实现对学生资料的录入、浏览、插入和删除等功能。
输入:设学生成绩以记录形式存储,每个学生记录包含的信息有:学号和各门课程的成绩,设学生成绩至少 3 门以上。存储结构:采用线性链式结构。
(2)详细设计
LinkList *create() : 输入学生成绩记录函数;
void print(LinkList *head) : 显示全部记录函数
LinkList *Delete(LinkList *head) : 删除记录函数
LinkList *Insert(LinkList *head) : 插入记录函数
void menu_select() : 菜单选择
void ScoreManage() : 函数界面
(3) 程序流程图
(4)程序模块及其接口描述
该程序可以分为以下几个模块:
a菜单选择: void menu_select();
提 供 五 种 可 以 选 择的 操作 , 在 main 函 数 中 通 过 switch 语句 调 用 菜 单
menu_select() 函数,进入不同的功能函数中完成相关操作。
b输入功能: LinkList *create();
通过一个 for 循环语句的控制, 可以一次完成无数条记录的输入。 并将其存入表。
c输出功能: void print(LinkList *head);
通过一个 while 的循环控制语句,在指针 p!=NULL时,完成全部学生记录的显示。知道不满足循环语句,程序再次回到菜单选择功能界面。
d删除功能: LinkList *Delete(LinkList *head);
按想要删除的学生的学号首先进行查找,通过指针所指向结点的下移来完成,如果找到该记录, 则完成前后结点的连接, 同时对以查找到的结点进行空间的释放,最后完成对某个学生记录进行删除,并重新存储。
e插入功能: LinkList *Insert(LinkList *head) ;
输入你想插入的位置,通过指针所指向结点的下移,找到该位置, 将该新的学生记录插入到该结点,并对该结点后面的指针下移。链表长度加一,重新存储。
f 程序的输入与输出描述
输入:调用 LinkList *create() 函数,输入学生的姓名、学号、三门功课的成绩;
输出:调用 void print(LinkList *head) 函数,输出学生的记录。
四、考评方式
学生成绩管理系统
评分点 | 分数 | 说明 |
搭建项目 | 5 | 搭建项目 |
创建结构体 | 5 | 创建学生成绩结构体 |
输入模块 | 10 | 输入学生成绩记录 |
输出模块 | 10 | 显示全部记录函数 |
删除模块 | 10 | 删除记录函数 |
增加模块 | 10 | 插入记录函数 |
主菜单 | 5 | 菜单选择 |
函数界面 | 5 | 函数界面 |
项目整体 | 10 | 项目正常运行部署,业务板块基本正常,设计功能整体实现 |
课程设计报告 | 30 | 符合一般论文格式规范。 |
五、代码部分:
#include<stdio.h>
#include<stdlib.h>
#include<String.h>
#include <time.h>
//------------------------------------------------------------------------------
typedef struct UserLogin {
char UserName[20];
char Code[20];
}user;
typedef struct stu { //学号和各门课程的成绩,设学生成绩至少 3 门以上
char Student_ID[20];
char name[20];
int Chinese;
int math;
int English;
struct stu* pnext;
}stu;
stu* phead; //phead为链表首地址
char fileuser[50] = "user.txt";//用户记录文件相对地址
char filename[50] = "111.txt";//文件默认的相对地址
char ch[1];//清除缓冲数据
int x = -1;//菜单选择(变量)
int n = 0;//n存着信息条数
int power=0;//0查看权限1管理员权限
char* user1;//用户登录名称
time_t t;//时间函数
//------------------------------------------------------------------------------
char* register_user(){ //用户使用记录
user* login = (user*)malloc(sizeof(user));
system("cls");
printf("高校教学管理与服务平台 (V8.2.0)");
printf("\n****************************************\n用户名:");
scanf("%s",login->UserName);
printf("管理员密码为:00000\n密码:");
scanf("%s",login->Code);
gets(ch);
if(!strcmp("00000",login->Code)){//用户权限,"00000"为管理员权限
power=1;
} else{
power=0;
}
FILE *w;//文件指针
w = fopen(fileuser, "a+"); //找不到文件就创建文件
fprintf(w, "%s ", login->UserName); //数据存入到文件
fprintf(w, "%s %ld", login->Code,time(&t));
fprintf(w, "%s", "\r\n"); //换行
fclose(w); //关闭文件
return login->UserName;
}
//------------------------------------------------------------------------------
int menu_select() { // 菜单选择
system("cls");
printf("高校教学管理与服务平台 (V8.2.0)");
printf("\n****************************************\n");
printf("欢迎(");
if(power){
printf(" 管理员:");
}else{
printf(" 用户:");
}
printf("%s )登录成绩管理系统\n%s",user1,ctime(&t),time(&t));
printf("****************************************");
printf("\n 菜单选择(当前文件目录%s)",filename);
printf("\n****************************************");
printf("\n\t0.修改文件路径");
printf("\n\t1.输入学生记录");printf("\t(仅管理员使用)");
printf("\n\t2.输出学生记录");
printf("\n\t3.删除学生记录");printf("\t(仅管理员使用)");
printf("\n\t4.插入学生记录");printf("\t(仅管理员使用)");
printf("\n\t5.退出用户登录");
printf("\n\t6.退出程序");
printf("\n****************************************");
printf("\n请输入您的选择:");
scanf("%d", &x);
gets(ch);
return x;
}
//------------------------------------------------------------------------------
void filePath() {//0.修改文件路径
printf("是否进行修改文件路径?0保持,1修改\n");
scanf("%d", &x);
if (x == 1){
printf("输入文件所在路径及名称<需要加文件后缀.txt>:");
scanf("%s", filename); /*输入文件所在路径及名称*/
printf("修改成功");
}gets(ch);//清除多余字符
}
//------------------------------------------------------------------------------
void save();
void Create() { //1.输入学生记录
int f=1;
printf("输入人数为: ");
scanf("%d", &n);
stu *pend, *pnew; //尾节点,新节点
pend = phead = (stu*)malloc(sizeof(stu)); //分配内存给首节点
phead->pnext=pend;//头节点指向第一条记录;
if(n){
printf("\t学号\t姓名\t语文\t数学\t英语\n");
}
for (int i = 0; i < n&&f; i++){
pnew = (stu*)malloc(sizeof(stu)); //分配新节点
pend->pnext = pnew; //原来的尾节点指向新节点
pnew->pnext = NULL; //新节点的指针为NULL
printf("NO.%d: ", i+1);
scanf("%s",pend->Student_ID);//输入数据存到链表中
scanf("%s",pend->name);
scanf("%d",&pend->Chinese);
scanf("%d",&pend->math);
scanf("%d",&pend->English);
pend = pnew; //赋值后指向尾节点
printf("是否继续输入<0结束1继续>");
scanf("%d",&f);
}pend->pnext=NULL;
free(pnew);//循环结束后释放pnew内存
save();
}
void save() { //1.1存到文件内
FILE *w;//文件指针
if ((w = fopen(filename, "a+")) == NULL) { /*二进制只写打开文件*/
printf("无法打开文件\n");
exit(1);
}
for (int i = 0; phead->pnext; i++) { //链表数据循环输入到文件里
fprintf(w, "%s ", phead->Student_ID); //数据存入到文件
fprintf(w, "%s ", phead->name);
fprintf(w, "%d ", phead->Chinese);
fprintf(w, "%d ", phead->math);
fprintf(w, "%d", phead->English);
fprintf(w, "%s", "\r\n"); //换行
phead = phead->pnext; //指向下一个节点
}fclose(w); //关闭文件
}
//------------------------------------------------------------------------------
void print() { //2.输出学生记录
FILE *fp;//文件指针
if ((fp = fopen(filename, "rb")) == NULL) { /*二进制只读打开文件*/
printf("无法打开文件\n");
exit(1);
}
stu *pend, *pnew; //尾节点,新节点
pend = phead = (stu*)malloc(sizeof(stu)); //分配内存给首节点
phead->pnext=pend;//头节点指向第一条记录;
printf("序号\t学号\t姓名\t语文\t数学\t英语\n");
int i=0;//计数
while(1) {
pnew = (stu*)malloc(sizeof(stu)); //分配新节点
pend->pnext = pnew; //原来的尾节点指向新节点
pnew->pnext = NULL; //新节点的指针为NULL
fscanf(fp, "%s", &(pend->Student_ID)); //输出数据到数组
fscanf(fp, "%s", &(pend->name));
fscanf(fp, "%d", &(pend->Chinese));
fscanf(fp, "%d", &(pend->math));
fscanf(fp, "%d", &(pend->English));
char ch;
if (ch = fgetc(fp) == EOF) {//结束的标志
if (feof(fp)) {
printf("共%d行\n",i);
break;
}
}
printf("%2d. %s\t%s\t%d\t%d\t%d\n",++i,pend->Student_ID,
pend->name,pend->Chinese,pend->math,pend->English); //输出数据到屏幕
if(!(i%200)){//每200行数据按任意键继续
system("pause");
}
pend = pnew; //赋值后指向尾节点
}pend->pnext=NULL;
free(pnew);//循环结束后释放pnew内存
fclose(fp);//关闭文件
}
//------------------------------------------------------------------------------
int query(){//3.1.查询对应的学号
int f=0;
char ID[20];
print(filename);//打印学生信息
stu *pend;//读取第一条记录
printf("请输入查找的学号");
scanf("%s",ID);
int i=1;
for(pend=phead;pend;pend=pend->pnext,i++){
if(!strcmp(ID,pend->Student_ID)){
f=1;
break;
}
}
if(f==1){
printf("%d查找到了学号\t%s\n",i,pend->Student_ID);
}else{
printf("没有找到该学号\n");
i=0;
}
return i;
}
int Delete() {//3.删除学生记录
n=query();
if(n==0){//没找到该同学;
return 0;
}
char buf[1024]; //每读取一行,都将内容放到该数组中
FILE* fp = fopen(filename, "r"); //filename里是原内容
FILE* fpt = fopen("temp.txt", "w"); //将filepath文件第n行内容删除后存入temp.txt中
int i = 0;
while (!feof(fp)) {
i++;
fgets(buf, sizeof(buf), fp);
if (i != n&&!feof(fp)) { //删掉第n行
fprintf(fpt, "%s", buf);
}
}
fclose(fp);
fclose(fpt);
fpt = fopen("temp.txt", "r");
fp = fopen(filename, "wb");
while (!feof(fpt)) {
fgets(buf, sizeof(buf), fpt);
if(!feof(fpt)) {
fprintf(fp, "%s", buf);
}
}
fclose(fp);
fclose(fpt);
system("ERASE temp.txt"); //删除文件temp.txt
print(filename);
return 1;
}
int Insert(){//4.插入学生记录
n=query();
if(n==0){//没找到该同学;
return 0;
}
char buf[1024]; //每读取一行,都将内容放到该数组中
FILE* fp = fopen(filename, "r"); //filename里是原内容
FILE* fpt = fopen("temp.txt", "w");
int i = 0;
while (!feof(fp)) {
i++;
fgets(buf, sizeof(buf), fp);
if(!feof(fp)) {
fprintf(fpt, "%s", buf);
}
if (i == n&&!feof(fp)) {
stu *pend;
pend = (stu*)malloc(sizeof(stu));
printf("\t学号\t姓名\t语文\t数学\t英语\n");
printf("NO.%d: ", i+1);
scanf("%s",pend->Student_ID);
scanf("%s",pend->name);
scanf("%d",&pend->Chinese);
scanf("%d",&pend->math);
scanf("%d",&pend->English);
fprintf(fpt, "%s ", pend->Student_ID); //数据存入到文件
fprintf(fpt, "%s ", pend->name);
fprintf(fpt, "%d ", pend->Chinese);
fprintf(fpt, "%d ", pend->math);
fprintf(fpt, "%d", pend->English);
fprintf(fpt, "%s", "\r\n"); //换行
}
}
fclose(fp);
fclose(fpt);
fpt = fopen("temp.txt", "r");
fp = fopen(filename, "wb");
while (!feof(fpt)) {
fgets(buf, sizeof(buf), fpt);
if(!feof(fpt)) {
fprintf(fp, "%s", buf);
}
}
fclose(fp);
fclose(fpt);
system("ERASE temp.txt"); //删除文件temp.txt
print(filename);
}
//------------------------------------------------------------------------------
void ScoreManage(){//函数选择
if(!power){//普通用户权限
switch (x) {
case 0:
filePath();//修改文件地址
break;
case 1:
printf("权限不足");
break;// 输入学生成绩记录函数;//调用函数建立链表存文件
case 2:
print();
break;// 显示全部记录函数//调用函数存到文件
case 3:
printf("权限不足");
break ;// 删除记录函数
case 4:
printf("权限不足");
break ;// 插入记录函数
case 5:
strcpy(user1,register_user());
break ;// 退出登录
case 6:
exit(1);//退出
default:;
}
}else{//管理员权限
switch (x) {
case 0:
filePath();//修改文件地址
break;
case 1:
Create();
break;// 输入学生成绩记录函数;//调用函数建立链表存文件
case 2:
print();
break;// 显示全部记录函数//调用函数存到文件
case 3:
Delete();
break ;// 删除记录函数
case 4:
Insert();
break ;// 插入记录函数
case 5:
strcpy(user1,register_user());
break ;// 退出登录
case 6:
exit(1);//退出
default:;
}
}
system("pause");
system("cls");
}
//------------------------------------------------------------------------------
int main() {
user1=register_user(); //用户登录界面返回用户名称
while (1) {
ScoreManage(menu_select());//函数选择(菜单选择)
}
return 0;
}