学生成绩管理系统
《数据结构》课程设计报告 题目: 学生成绩管理系统 班级: 计算机科学与技术 学号: 1820101989 姓名: 成绩: 指导教师: ...
《数据结构》课程设计报告
题目: 学生成绩管理系统
班级: 计算机科学与技术
学号: 1820101989
姓名:
成绩:
指导教师:
时间: 2018至2019第一学期第17周
日期:2018 年 12 月 23 日
目录
课程设计报告的内容
一、 问题描述
1. 通过此次课程设计中学生成绩管理系统的题目,掌握链表等数据结构的基本操作方面的知识,并能灵活的解决一些基本的问题,加深对其性质及各项操作的理解;
2. 将所学数据结构方面的知识与一门具体的语言——C语言来进行实现,感受数据结构的强大作用,加深理解。
二、实验要求
管理系统中有五个要求:输入 查找 修改 插入 删除 存储
(1) 输入要求:能够通过键盘输入和文件输入两种
(2) 查找要求:能够根据学生号查找单个学生的信息,也可以遍历所有学生信息
(3) 修改要求:能够根据学生号修改单个学生所有信息
(4) 插入要求:能够实现头插和尾插
(5) 删除要求:能够根据学生号删除单个学生信息
(6) 存储要求:通过链表存储所有信息
三、程序设计流程图
四、程序源码与功能使用
/*
声明:纯粹自己写的,搭框架,实现具体功能,所以可能有些Bug,希望有人使用的时候发现并指出。
体会: 程序只实现了大概的功能框架,主要注重实现链表的增删改查,一些显示格式之类的未做优化,看似简单的东西,其实坑还是比较多的,C和C++之间衔接,感觉很多东西兼容性处理的并不是那么好,掉坑里感觉好心塞,多动手吧,杜绝眼高手低。
*/
Main.cpp文件
/**********************************************
*文件名称:(数据结构课程设计)学生成绩管理系统
*文件标识:无
*内容摘要:实现学成成绩的输入、查找、修改、插入、删除、存储。
*其他内容:无
*当前版本:V1.0
*Author:李园
*完成日期:2018/12/23
*版本号:1.0
c++中如何将字符型数字转换为int型(https://zhidao.baidu.com/question/576359612.html)
大概功能实现, 具体细节待完善。。。。。。。
*************************************************/
#include <iostream>
#include <cstdio>
#include "Score.h"
using namespace std;
int main(int argc, char** argv)
{
SNode *L;
InitList(L);
char quit; //用字符类型的作为判断,int类型的有坑,不知道怎么填。开始明白为什么有char类型的了。
system("color 0D");
//system("color 3f");
while (1) {
cout << (" |*****************请选择相应功能*****************|") << endl;
cout << (" | 1 手动添加学生成绩信息(尾插) ") << endl;
cout << (" | 2 手动添加学生成绩信息(头插) ") << endl;
cout << (" | 3 文件中的信息导入到程序中 ") << endl;
cout << (" | 4 输出当前所有学生成绩信息 ") << endl;
cout << (" | 5 按学号查找学生成绩信息 ") << endl;
cout << (" | 6 根据学号修改学生信息 ") << endl;
cout << (" | 7 通过链表保存所有学生信息到文件中 ") << endl;
cout << (" | 8 根据学号删除单个学生信息 ") << endl;
cout << (" | 9 清空所有学生信息 ") << endl;
cout << (" | 0 操作完成退出程序 ") << endl;
cout << (" | ***********************************************|") << endl << endl;
cout << "请选择相应操作::" << endl;
cin >> quit;
switch (quit)
{
case '1': InsertNodeR(L); break;
case '2': InsertNodeH(L); break;
case '3': ReadInfo(L); break;
case '4': DisplayS(L); break;
case '5': FindStudent(L); break;
case '6': ModifyInfo(L); break;
case '7': SaveInfo(L); break;
case '8': DeleteNum(L); break;
case '9': Distroy(L); break;
case '0': exit(0); break;
default: cout << "输入错误请重新输入:" << endl << endl; break;
}
}
return 0;
}
.h头文件
#ifndef _SCORE_H_
#define _SCORE_H_
#include <string>
using namespace std; //使用整个命名空间。
typedef struct Student
{
string name;
string studentNum; //string是std名称空间里面的。
string className;
string Math;
string English;
struct Student *next; //结点中的指针域
}SNode;
static FILE *fp;
void ModifyInfo(SNode *L); //根据学号修改单个学生的所有信息
void InitList(SNode *&L); //创建一个头结点,便于操作
void InsertNodeR(SNode *L); //插入一个结点。采用尾插的方式
void InsertNodeH(SNode *L); //插入一个结点。采用头插的方式
void DeleteNum(SNode *L); //根据学号删除结点。
void FindStudent(SNode *L); //根据提供的学号来查找学生信息
void DisplayS(SNode *L); //显示全部学生
void Distroy(SNode *L); //销毁链表,释放结点。
//文件操作
void SaveInfo(SNode *L);
void ReadInfo(SNode *L);
#endif
.cpp源文件
#include "Score.h"
#include <iostream>
//#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <io.h>
using namespace std;
void InitList(SNode *&L) //创建一个头结点,便于操作
{
L = new SNode();
L->next = NULL;
}
void InsertNodeR(SNode *L) //插入一个结点。采用尾插的方式
{
SNode *sn = new SNode(); //这里有坑,明天详细看一下。 C++中的特性和C中的分开使用new ,cin。
sn->next = NULL;
SNode* rl;
cout << "姓名:" << endl;
cin >> sn->name;
cout << "学号:" << endl;
cin >> sn->studentNum;
cout << "班级名称:" << endl;
cin >> sn->className;
cout << "数学分数:" << endl;
cin >> sn->Math;
cout << "英语分数:" << endl;
cin >> sn->English;
rl = L;
while (rl->next != NULL)
{
rl = rl->next; //插到尾部。 尾插
}
rl->next = sn;
cout << "尾插入成功" << endl;
SaveInfo(L);
}
void InsertNodeH(SNode *L) //插入一个结点。采用头插的方式
{
SNode *sn = new SNode(); //这里有坑,明天详细看一下。 C++中的特性和C中的分开使用new ,cin。
sn->next = NULL;
cout << "姓名:" << endl;
cin >> sn->name;
cout << "学号:" << endl;
cin >> sn->studentNum;
cout << "班级名称:" << endl;
cin >> sn->className;
cout << "数学分数:" << endl;
cin >> sn->Math;
cout << "英语分数:" << endl;
cin >> sn->English;
sn->next = L->next;
L->next = sn;
cout << "头插入成功" << endl;
SaveInfo(L);
}
void DeleteNum(SNode *L) //根据学号删除结点。
{
//需要保留上一结点
SNode *pre = L, *p = L->next;
string num;
bool flag = false;
cout << "请输入您要查找的学号" << endl;
cin >> num;
while (p != NULL)
{
if (num == p->studentNum)
{
flag = true;
pre->next = p->next;
delete p;
cout << "删除的学号为:" << num << "成功" << endl;
break;
}
pre = p;
p = p->next;
}
if (!flag)
{
cout << "您要删除的元素不存在" << endl;
}
}
void FindStudent(SNode *L) //根据提供的学号来查找学生信息
{
SNode* p = L->next;
bool flag = false;
string num;
cout << "请输入您要查找的学号" << endl;
cin >> num;
while (p != NULL)
{
if (num == p->studentNum)
{
flag = true;
cout << "学生的姓名:" << p->name << endl;
cout << "学生的学号:" << p->studentNum << endl;
cout << "学生的班级名称:" << p->className << endl;
cout << "学生的数学成绩:" << p->Math << endl;
cout << "学生的英语成绩:" << p->English << endl;
break;
}
p = p->next;
}
if (!flag)
{
cout << "您查找的学号不存在:" << endl;
}
cout << "\n\n\n" << endl;
}
void DisplayS(SNode *L) //显示全部学生
{
SNode *p = L->next;
if (p == NULL) cout << "链表中没有元素" << endl;
while (p != NULL)
{
cout << "学生的姓名:" << p->name << endl;
cout << "学生的学号:" << p->studentNum << endl;
cout << "学生的班级名称:" << p->className << endl;
cout << "学生的数学成绩:" << p->Math << endl;
cout << "学生的英语成绩:" << p->English << endl;
p = p->next;
}
}
void ModifyInfo(SNode *L) //根据学号修改学生的所有信息。
{
SNode* p = L->next;
bool flag = false;
string num;
cout << "请输入您要修改的学生学号" << endl;
cin >> num;
while (p != NULL)
{
if (num == p->studentNum)
{
flag = true;
cout << "请输入新的学生姓名:" << endl;
string name;
cin >> name;
p->name = name;
cout << "请输入新的学生学号:" << endl;
string num;
cin >> num;
p->studentNum = num;
cout << "请输入新的学生班级名称:" << endl;
string className;
cin >> className;
p->className = className;
cout << "请输入新的学生数学成绩:" << endl;
string Math;
cin >> Math;
p->Math = Math;
cout << "请输入新的学生英语成绩:" << endl;
string English;
cin >> English;
p->English = English;
cout << "修改成功!!" << endl;
break;
}
p = p->next;
}
if (!flag)
{
cout << "您查找的学号不存在:" << endl;
}
cout << "\n\n\n" << endl;
}
void Distroy(SNode *L) //销毁链表,释放结点。
{
//保留前一结点地址,删除当前结点。
SNode *pre = L, *p = L->next;
while (p != NULL)
{
delete pre;
pre = p;
p = p->next;
}
delete pre; //最后, pre指向尾结点释放它,如果L只有一个头结点,那么这里就只释放头结点。
cout << "已清空" << endl;
}
//文件操作
void SaveInfo(SNode *L)
{
//(a)以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)
//因为EOF会保留,所以读取的时候记得移动lseek到文件开头。
//(a+) 则不保留EOF,就是不用移动到开头。
fp = fopen("studentFile.txt", "a");
SNode *p = L->next;
while (p != NULL)
{
//为什么用c_str()函数: 因为%s需要类型是char *,fprintf()的可变参数类型须与%s保持一致。
fprintf(fp, "%6s %6s %6s %6s %6s \n", p->name.c_str(), p->studentNum.c_str(), p->className.c_str(), p->English.c_str(), p->Math.c_str());
p = p->next;
}
fclose(fp); //将数据由缓冲区写到文件中。
cout << "保存成功" << endl;
}
void ReadInfo(SNode *L)
{
//到指定的文件夹下去读取数据
char a[30];
char b[30];
char c[30];
char d[30];
char e[30];
if (_access("studentFile.txt", 02) != -1)//判断文件夹是否存在,是否有写权限。
{
fp = fopen("studentFile.txt", "r+"); //打开可读写的文件。
//fseek(fp, 0, 0);
while (fgetc(fp) != EOF)
{
SNode *p = new SNode(); //作为新节点。
p->next = NULL;
fscanf(fp, "%6s %6s %6s %6s %6s \n", a, b, c, d, e);
p->name = a;
p->studentNum = b;
p->className = c;
p->English = d;
p->Math = e;
//插入到链表中。每读一次插一次。
SNode *rl = L;
while (rl->next != NULL)
{
rl = rl->next; //插到尾部。 尾插
}
rl->next = p;
}
fclose(fp);
cout << "导入成功" << endl;
}
else
{
cout << "暂无本地数据,请手动创建" << endl;
}
}
五、设计心得与问题处理
工程感悟:C/C++之中的特性要分开使用,C中malloc和free配套,C++中的new和delete配套,不要混合使用,有坑。通过本次课程设计加深了对链表的理解,对于链表的各种操作能够熟练掌握;相较于数组,链表具有动态扩容,插入和删除时不需要移动大量的元素等特点。
体会: 程序只实现了大概的功能框架,主要注重实现链表的增删改查,一些显示格式之类的未做优化,看似简单的东西,其实坑还是比较多的,C和C++之间衔接,感觉很多东西兼容性处理的并不是那么好,掉坑里感觉好心塞,多动手吧,杜绝眼高手低。
更多推荐
所有评论(0)