基本功能:
0.添加学生信息
1.删除学生信息(按学号)
2.修改学生信息(按学号)
3.修改学生信息(按名字)
4.查询学生信息(按名字)
5.排序:
- 按学号排序
- 按名字排序
6.显示所有学生信息及统计信息
7.退出软件
实现思路:
1.基本功能实现依靠对链表的各种操作实现(增删改查,链表排序)
2.功能选择依靠switch选择实现
3.退出程序后再次进入数据的保存依靠对文件的简单操作实现,只需对链表操作增添写入函数和写出函数即可实现数据的保存
文件操作介绍:
文件操作详解,转自贾继康的博客
文件类型指针:
冲文件系统中,关键的概念是“文件指针”。每个被使用的文件都在内存中开辟一个区,用来存放文件的有关信息(如文件的名字、文件状态及文件当前位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统定义的,取名为FILE。
使用方法:
FILE* fp;//定义一个文件指针
文件的打开与关闭
文件的打开:
FILE *fp; // 文件指针
fp = fopen("D:\\管理系统.txt","r"); // 打开文件,D:\\管理系统.txt 为文件地址
fclose(fp);//使用完文件关闭文件,防止后续对其误操作
说明:
(1)用“r”方式打开的文件只能用于向计算机输入而不能用作向该文件输出数据,而且该文件应该已经存在,不能用“r”方式打开一个并不存在的文件(即输入文件),否则出错。
(2)用“w”方式打开的文件只能用于向该文件写数据(即输出文件),而不能用来向计算机输入。如果原来不存在该文件,则在打开时新建立一个以指定的名字命名的文件。如果原来已存在一个以该文件名命名的文件,则在打开时将该文件删去,然后重新建立一个新文件。
(3)如果希望向文件末尾添加新的数据(不希望删除原有数据),则应该用“a”方式打开。但此时该文件必须已存在,否则将得到出错信息。打开时,位置指针移到文件末尾。
(4)用“r+”、“w+”、
“a+”方式打开的文件既可以用来输入数据,也可以用来输出数据。用“r+”方式时该文件应该已经存在,以便能向计算机输入数据。用“w+”方式则新建立一个文件,先向此文件写数据,然后可以读此文件中的数据。用“a+”方式打开的文件,原来的文件不被删去,位置指针移到文件末尾,可以添加,也可以读。
(5)如果不能实现“打开”的任务,fopen函数将会带回一个出错信息。出错的原因可能是用“r”方式打开一个并不存在的文件;磁盘出故障;磁盘已满无法建立新文件等。此时fopen函数将带回一个空指针值NULL。
(6)在向计算机输入文本文件时,将回车换行符转换为一个换行符,在输出时把换行符转换成为回车和换行两个字符。在用二进制文件时,不进行这种转换,在内存中的数据形式与输出到外部文件中的数据形式完全一致,一一对应。
(7)在程序开始运行时,系统自动打开3个标准文件:标准输入、标准输出、标准出错输出。这3个文件都与终端相联系。因此以前所用到的从终端输入或输出都不需要打开终端文件。系统自动定义了3个文件指针stdin、stdout和stderr,分别指向终端输入、终端输出和标准出错输出(也从终端输出)。如果程序中指定要从stdin所指的文件输入数据,就是指从终端键盘输入数据
文件的关闭
在使用完一个文件后应该关闭它,以防止它再被误用。“关闭”就是使文件指针变量不指向该文件,也就是文件指针变量与文件“脱钩”,以后不能再通过该指针对原来与其相联系的文件进行读写操作。除非再次打开,使该指针变量重新指向该文件。
完整代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct student //学生信息结构体
{
int StuNum;
char name[50];
float chData;
float maData;
float enData;
float sumData;
};
typedef struct Node//链表结点
{
struct student data;
struct Node *next;
}Node, *Linklist;
void printStuData (struct student data);
void printStuData (struct student data);
Linklist createHeadNode ();
Linklist headNode = createHeadNode ();
Linklist createHeadNode ()//创建头结点
{
Linklist headNode = (Linklist)malloc(sizeof(Node));
headNode->next = NULL;
return headNode;
}
Linklist createNewNode (struct student data)//创建新结点
{
Linklist newNode = (Linklist)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
void addNodeHead(Linklist headNode, struct student data)//头插增添结点
{
Linklist newNode = createNewNode(data);
newNode->next = headNode->next;
headNode->next = newNode;
}
void deleLinkNode(Linklist headNode, int posNum)//按学号删除学生信息
{
if(headNode->next == NULL)
{
printf("系统未录入数据!请先录入数据\n");
return ;
}
Linklist posNode, frontposNode;
frontposNode = headNode;
posNode = headNode->next;
while(posNode->data.StuNum != posNum)
{
posNode = posNode->next;
if(!posNode)
{
printf("未录入该学号学生\n");
return ;
}
frontposNode = frontposNode->next;
}
frontposNode->next = posNode->next;
free(posNode);
return ;
}
void reclinkNodeS(Linklist headNode, int posNum)//修改学生信息 (按学号)
{
if(headNode->next == NULL)
{
printf("系统数据为空!请先录入数据\n");
return ;
}
Linklist posNode;
posNode = headNode->next;
while(posNode->data.StuNum != posNum)
{
posNode = posNode->next;
if(!posNode)
{
printf("未录入该学号学生\n");
return ;
}
}
printf("输入数据之间以空格隔开\n");
printf(" 学号 姓名 语文 数学 英语 \n");
scanf("%d %s %f %f %f", &posNode->data.StuNum , posNode->data.name ,&posNode->data.chData , &posNode->data.maData ,&posNode->data.enData);
posNode->data.sumData = posNode->data.chData + posNode->data.enData + posNode->data.maData;
return ;
}
void reclinkNodeN(Linklist headNode, char *posName)//修改学生信息(按名字)
{
if(headNode->next == NULL)
{
printf("系统数据为空!请先录入数据\n");
return ;
}
Linklist posNode;
posNode = headNode->next;
while(strcmp(posNode->data.name,posName))//int strcmp(char *s1, char *s2)若s1、s2字符串相等,则返回零
{
posNode = posNode->next;
if(!posNode)
{
printf("未录入该名字学生\n");
return ;
}
}
printf("输入数据之间以空格隔开\n");
printf(" 学号 姓名 语文 数学 英语 \n");
scanf("%d %s %f %f %f", &posNode->data.StuNum , posNode->data.name ,&posNode->data.chData , &posNode->data.maData ,&posNode->data.enData);
posNode->data.sumData = posNode->data.chData + posNode->data.enData + posNode->data.maData;
}
void seekNode (Linklist headNode, char *posName)//查询学生信息(按名字)
{
if(headNode->next == NULL)
{
printf("系统数据为空!请先录入数据\n");
return ;
}
Linklist posNode;
posNode = headNode->next;
while(strcmp(posNode->data.name,posName))//int strcmp(char *s1, char *s2)若s1、s2字符串相等,则返回零
{
if(!posNode)
{
printf("未录入该名字学生\n");
return ;
}
posNode = posNode->next;
}
printf("| 学号 | 姓名 | 语文 | 数学 | 英语 | 总分 |\n");
printf("|--------|--------|--------|--------|--------|--------|\n");
printStuData(posNode->data);
printf("*******************************************************\n");
}
void sortStunum(Linklist headNode)//按学号排序
{
struct student temp;
Linklist q1, q2;
if(!headNode->next || !headNode->next->next)
{
printf("系统数据为空!请先录入数据\n");
return ;
}
for (q1 = headNode->next; q1; q1 = q1->next)
for(q2 = q1->next; q2; q2 = q2->next)
{
if(q1->data.StuNum > q2->data.StuNum)
{
temp = q1->data;
q1->data = q2->data;
q2->data = temp;
}
}
return ;
}
void sortSumdata(Linklist headNode)//按总分排序
{
struct student temp;
Linklist q1, q2;
if(!headNode->next || !headNode->next->next)
{
printf("系统数据为空!请先录入数据\n");
return ;
}
for (q1 = headNode->next; q1; q1 = q1->next)
for(q2 = q1->next; q2; q2 = q2->next)
{
if(q1->data.sumData < q2->data.sumData)
{
temp = q1->data;
q1->data = q2->data;
q2->data = temp;
}
}
return ;
}
void printList (Linklist headNode)//输出链表数据
{
if(headNode->next == NULL)
{
printf("系统数据为空!请先录入数据\n");
return ;
}
headNode = headNode->next;
printf("**********************学 生 信 息**********************\n");
printf("| 学号 | 姓名 | 语文 | 数学 | 英语 | 总分 |\n");
printf("|--------|--------|--------|--------|--------|--------|\n");
while(headNode)
{
printStuData(headNode->data);
headNode = headNode->next;
}
printf("*******************************************************\n");
return ;
}
void readFile(Linklist headNode, const char *name)//从文件夹读出文件数据
{
FILE *fp;
fp = fopen(name,"r");
struct student data;
if(fp == NULL)
{
fp = fopen(name,"w+");
}
while(fscanf(fp,"%d\t%s\t%f\t%f\t%f\t%f",&data.StuNum ,data.name ,&data.chData ,&data.maData ,&data.enData, &data.sumData ) != EOF)
{
addNodeHead(headNode,data);
}
fclose(fp);
}
void writeFile(Linklist headNode, const char *name)//向文件写入数据
{
Linklist p = headNode->next;
FILE *fp;
fp = fopen(name, "w");
while(p)
{
fprintf(fp,"%d\t%s\t%.2f\t%.2f\t%.2f\t%.2f\n", p->data.StuNum, p->data.name, p->data.chData, p->data.maData, p->data.enData, p->data.sumData);
p = p->next;
}
fclose(fp);
}
void printStuData (struct student data)//输出学生信息
{
printf("| %-6d | %-6s | %-6.2f | %-6.2f | %-6.2f | %-6.2f |\n", data.StuNum, data.name, data.chData, data.maData, data.enData, data.sumData);
return ;
}
void systemMenu ()//交互页面
{
printf("*--------------------【学生管理系统】-------------------*\n");
printf("*\t\t0.添加学生信息 \t\t*\n");
printf("*\t\t1.删除学生信息(按学号)\t\t*\n");
printf("*\t\t2.修改学生信息(按学号)\t\t*\n");
printf("*\t\t3.修改学生信息(按名字)\t\t*\n");
printf("*\t\t4.查询学生信息(按名字)\t\t*\n");
printf("*\t\t5.排序\t\t\t\t\t*\n");
printf("*\t\t6.显示所有学生信息及统计信息\t\t*\n");
printf("*\t\t7.退出软件\t\t\t\t*\n");
printf("*-------------------------------------------------------*\n");
printf("请输入0~5:");
}
void keydown()//选择操作
{
int UseKey;
struct student data;
scanf("%d", &UseKey);
switch(UseKey)
{
int posNum;
char posName[50];
case 0:
printf("【添加学生信息】\n");
printf("输入数据之间以空格隔开\n");
printf(" 学号 姓名 语文 数学 英语 \n");
fflush(stdin);
scanf("%d %s %f %f %f", &data.StuNum , data.name ,&data.chData , &data.maData ,&data.enData);
data.sumData = data.chData + data.enData +data.maData;
addNodeHead(headNode, data);
writeFile(headNode, "D:\\管理系统.txt");
break;
case 1:
printf("【删除学生信息】\n");
printf("请输入学生学号:");
scanf("%d", &posNum);
deleLinkNode(headNode, posNum);
writeFile(headNode, "D:\\管理系统.txt");
break;
case 2:
printf("【修改学生信息】\n");
printf("请输入学生学号:");
scanf("%d", &posNum);
fflush(stdin);
reclinkNodeS(headNode, posNum);
writeFile(headNode, "D:\\管理系统.txt");
break;
case 3:
printf("【修改学生信息】\n");
printf("请输入学生姓名:");
scanf("%s", posName);
fflush(stdin);
reclinkNodeN(headNode, posName);
writeFile(headNode, "D:\\管理系统.txt");
break;
case 4:
printf("【查询学生信息】\n");
printf("请输入学生姓名:");
scanf("%s", posName);
seekNode(headNode, posName);
break;
case 5:
printf("【排序】\n");
printf("1.按学号排序\n");
printf("2.按总成绩排序\n");
scanf("%d", &posNum);
switch(posNum)
{
case 1:
sortStunum(headNode);
writeFile(headNode, "D:\\管理系统.txt");
printf("排序完成\n");
break;
case 2:
sortSumdata(headNode);
writeFile(headNode, "D:\\管理系统.txt");
printf("排序完成\n");
break;
default:
printf("你输入的内容有误!");
break;
}
break;
case 6:
printList (headNode);
break;
case 7:
printf("【退出程序】\n");
system("pause");
exit(1);
break;
default:
printf("你输入的内容有误!请重新输入:\n");
}
}
int main(void)
{
readFile(headNode,"D:\\管理系统.txt");
while(1)
{
systemMenu();
keydown();
system("pause");
system("cls");
}
system("pause");
return 0;
}