简单复习下C语言基础知识,使用单链表,结构体嵌套,文件读写信息,实现控制台简单学生成绩管理系统.
源码
- 枚举类型
#include<stdio.h>
#include <stdlib.h>
#include <string>
enum CONMMAND
{
SAVEANDQUIT, ADD, MODIFY, INUIRY, DELETE, BROWSE
};
- 相关结构体与单链表结构体
struct Results
{
int math;
int language;
int english;
int computer;
};
struct Student
{
char s_StuId[10]; // 学号
char s_Name[10]; // 姓名
char s_IDcard[20]; // 身份证号
char s_DateBirth[20]; // 出生日期
int s_Age; // 年龄
char s_Gender[3]; // 性别
Results re; // 各科成绩
float s_result; // 成绩
int s_rank = 1; // 排名
char s_Finalassess[10] = ""; // 最终评价
};
struct StudentLinklist
{
Student stu; // 数据域
StudentLinklist* next; // 指针域
};
- 全局操作指令与文件路径
int nConmmand;
const char* file = "E:\\student\\saveLinklist.bin";
- 简单的显示菜单,以及录入信息函数
// 菜单
void MenuFirst(int* nConmmand) {
printf("\n\n\n\t\t\t\t++#@%=================学生成绩管理系统=================%@#++\n\n\n");
printf("\t\t\t\t\t1.添加学生成绩信息\t2.修改学生成绩信息\n\t\t\t\t\t3.查询学生成绩信息\t4.删除学生成绩信息\n\t\t\t\t\t5.浏览学生成绩信息\t0.保存并退出系统\n");
printf("\n\n\t\t\t\t++#@%=================学生成绩管理系统=================%@#++\n");
printf("请输入你的指令(0-6):\n");
scanf_s("%d", nConmmand);
}
// 录入学生信息.
Student mScanfstudent() {
Student stu;
printf("请输入学生基本信息:\n");
printf("学号\t姓名\t身份证号\t出生日期\t年龄\t性别\n");
scanf("%s\t%s\t%s\t%s\t%d\t%s", stu.s_StuId, stu.s_Name, stu.s_IDcard, stu.s_DateBirth, &stu.s_Age, stu.s_Gender);
printf("请输入学生基本成绩信息:\n");
printf("数学\t语文\t英语\t计算机课程设计\n");
scanf("%d\t%d\t%d\t%d", &stu.re.math, &stu.re.language, &stu.re.english, &stu.re.computer);
stu.s_result = (stu.re.computer + stu.re.english + stu.re.language + stu.re.math) / 4;
return stu;
}
- 链表的各种操作函数
// 创建节点
StudentLinklist* mcretelink() {
StudentLinklist* H = (StudentLinklist*)malloc(sizeof(StudentLinklist));
if (!H)
{
printf("创建失败");
getchar();
exit(0);
}
else { // 初始化
H->next = NULL;
}
return H;
}
// 遍历返回链表长度
int mGetLinklist(StudentLinklist* stulink) {
StudentLinklist* temp = stulink;
int nLen = 0;
while (temp)
{
temp = temp->next;
nLen++;
}
return nLen;
}
// 在尾部插入stu信息.
void minsertend(StudentLinklist* stulink, Student stu) {
StudentLinklist* temp = stulink;
while (temp->next != NULL)
{
temp=temp->next;
}
StudentLinklist* s = mcretelink();
s->stu = stu;
s->next = temp->next;
temp->next = s;
}
- 链表遍历操作函数(各种增,删,改,查等操作)
// 遍历输出链表
void mPrintlinklist(StudentLinklist* stulink) {
StudentLinklist* temp = stulink->next;
Student stu;
printf("学号\t姓名\t身份证号\t\t出生日期\t年龄\t性别\t综合成绩\t排名\t总评\n");
while (temp!= NULL)
{
stu = temp->stu;
printf("%s\t%s\t%s\t%s\t%d\t%s\t%.1f\t\t%d\t%s\n", stu.s_StuId, stu.s_Name, stu.s_IDcard, stu.s_DateBirth, stu.s_Age, stu.s_Gender, stu.s_result, stu.s_rank, stu.s_Finalassess);
temp = temp->next;
}
}
//遍历设置总评成绩
bool mSetFinalassess(StudentLinklist* stulnk) {
StudentLinklist* temp = stulnk;
if (temp == NULL)
{
return 0;
}
while (temp)
{
if (60.0 <= temp->stu.s_result && temp->stu.s_result < 70.0)
{
strcpy(temp->stu.s_Finalassess, "合格");
}
else if (70.0 <= temp->stu.s_result && temp->stu.s_result< 90.0) {
strcpy(temp->stu.s_Finalassess, "优良");
}
else if (90.0 <= temp->stu.s_result) {
strcpy(temp->stu.s_Finalassess, "优秀");
}
else {
strcpy(temp->stu.s_Finalassess, "不合格");
}
temp = temp->next;
}
}
// 遍历排序.
void mSort(StudentLinklist* stulinklist) {
StudentLinklist* temp = stulinklist->next;
Student p;
if (!temp) {
printf("信息为空\n");
}
else {
while (temp->next != NULL)
{
if (temp->stu.s_result < temp->next->stu.s_result)
{
p = temp->stu;
temp->stu = temp->next->stu;
temp->next->stu = p;
}
temp = temp->next;
}
}
}
// 遍历设置排名
void mSetrank(StudentLinklist* stulinklist) {
StudentLinklist* temp = stulinklist;
int i = 0;
while (temp)
{
temp->stu.s_rank = i;
i++;
temp = temp->next;
}
}
//遍历查询通过学号
Student mInquire(StudentLinklist* stulinklist,char* stuid) {
StudentLinklist* temp = stulinklist;
Student stu;
while (temp)
{
if (strcmp(temp->stu.s_StuId,stuid)==0)
break;
else
temp = temp->next;
}
stu = temp->stu;
return stu;
}
// 删除指定元素
bool mDelete(StudentLinklist* stulinklist,char* stuid){
StudentLinklist* temp=stulinklist;
while (temp->next)
{
if (strcmp(temp->next->stu.s_StuId, stuid) == 0)
break;
else
temp = temp->next;
}
// 创建一个新节点
StudentLinklist* s = mcretelink();
// 使s指向第i个位置(要删除的位置)
s = temp->next;
//用stu参数暂时保存即将删除的数据.
//让temp.next指向i后面的一位.
temp->next = s->next;
//删除节点,释放掉s指向的第i个位置的节点空间
free(s);
return 1; //删除成功
}
// 修改指定元素
bool mModify(StudentLinklist* stulinklist,char* stuid,Student stu){
StudentLinklist* temp = stulinklist;
while (temp)
{
if (strcmp(temp->stu.s_StuId, stuid) == 0)
break;
else
temp = temp->next;
}
temp->stu = stu;
return 1;
}
- 文件读写函数(将链表数据写入文件,与将文件的数据读入到链表中).
读写模式采用覆盖,所有数据只存入一条链表.
// 文件是无法保存一个链表指针域的.只能按数据块来保存.所以需要单独将链表
// 的数据域存进文件,读取的时候再创建链表初始化即可.
// 将链表数据写入文件..
bool mWriteLinklist(const char* file,StudentLinklist* stulinklist) {
FILE* fp;
StudentLinklist* temp = stulinklist->next;
fp = fopen(file, "rb+");
if (!fp)
{
return 0;
}
else {
// 将链表中的所有节点的数据域存放进文件中
while (temp)
{
fwrite(&temp->stu, sizeof(Student), 1, fp);
temp = temp->next;
}
return 1;
}
}
// 读取文件中的数据到linklist中
bool mReadlinklist(const char* file,StudentLinklist* stulinklist) {
FILE* fp;
Student stu;
fp = fopen(file, "rb+");
if (!fp)
{
printf("打开失败");
exit(1);
return 0;
}
else {
while (fread(&stu,sizeof(Student),1,fp))
{
StudentLinklist* s = mcretelink();
s->stu = stu;
s->next =stulinklist ->next;
stulinklist->next = s;
}
return 1;
}
}
- 主函数
int main()
{
// 先读取文件,将链表取出.
StudentLinklist* stulinklist = mcretelink(); // 全局链表,只对它操作.
if (!mReadlinklist(file, stulinklist))
{
printf("读取文件失败");
}
char stuid[10]; //学号
Student stu; // 学生
char a;
while (1) {
MenuFirst(&nConmmand);
switch (nConmmand)
{
case ADD: // 添加
stu = mScanfstudent();
minsertend(stulinklist,stu);
system("cls");
break;
case MODIFY: // 修改
printf("请输入要修改的学生的学号:");
scanf("%s", stuid);
stu = mScanfstudent();
if (mModify(stulinklist, stuid, stu))
{
printf("修改成功");
}
system("cls");
break;
case INUIRY: // 查询
printf("请输入查询学号:");
scanf("%s", stuid);
stu = mInquire(stulinklist, stuid);
printf("%s\t%s\t%s\t%s\t%d\t%s\t%.1f\t\t%d\t%s\n", stu.s_StuId, stu.s_Name, stu.s_IDcard, stu.s_DateBirth, stu.s_Age, stu.s_Gender, stu.s_result, stu.s_rank, stu.s_Finalassess);
system("cls");
break;
case DELETE: // 删除
printf("请输入要删除学生的学号:");
scanf("%s", stuid);
if (mDelete(stulinklist, stuid)) {
printf("删除成功");
}
system("cls");
break;
case BROWSE: // 浏览
mSetFinalassess(stulinklist); // 设置总评
mSort(stulinklist); // 遍历判断,按成绩排序
mSetrank(stulinklist); // 遍历设置排名
mPrintlinklist(stulinklist); // 遍历输出链表.
break;
case SAVEANDQUIT: // 保存
mSetFinalassess(stulinklist); //设置总评
mSort(stulinklist); // 遍历判断,按成绩排序
mSetrank(stulinklist); //遍历设置排名
if (mWriteLinklist(file, stulinklist)) //判断写入是否成功,并退出程序.
{
printf("保存成功");
}
exit(0);
break;
default:
break;
};
}
}
图片.png 图片.png
当然,时间仓促,系统很简陋,还有很多可以完善和改进的地方.只是重点回顾了一下指针,链表,结构体,文件的一些常用操作.至于读写excel表格文件(格式化存储),实现条件判断自动分发邮件(网络编程,sokect套接字,smtp协议).等技术,之后有时间再写吧.
2019.12.30日.
网友评论