学生成绩记录簿设计
编制一个C语言成绩记录簿,每个学生信息包括:学号、姓名、C语言成绩。
具体功能:
(1)创建信息链表并以磁盘文件保存;
(2)读取磁盘文件并显示输出所有学生的成绩;
(3)按学号或姓名查询成绩;
(4)添加成绩记录;
(5)修改指定姓名或学号的学生的成绩并可存盘;
(6)显示输出60分以下、60~79、80~89、90分以上各分数段的学生信息(可
选项)。
源代码:
#include<stdio.h> // 头文件
#include<string.h> //字符函数和字符串函数 strcmp
#include<stdlib.h> //动态储存分配函数 malloc
struct Student{
char sno[20]; //学号
char name[100]; //姓名
float grade; //C语言成绩
};
typedef struct Node{
struct Student stu; //结构体变量(将以上信息封装到链表的结点当中)
struct Node *next; //下一个地址
}Node,*StuLinkList;
//菜单显示函数
void Menu(){
printf("\t|---------------------------------------------------|\n");
printf("\t| 学生成绩管理薄系统 |\n");
printf("\t| |\n");
printf("\t| 自动读取信息至程序中(链表) |\n");
printf("\t|---------------------------------------------------|\n");
printf("\t| 1.添加信息 |\n");
printf("\t| 2.查询信息 |\n");
printf("\t| 3.修改信息 |\n");
printf("\t| 4.显示所有信息 |\n");
printf("\t| 5.显示分段信息 |\n");
printf("\t| 6.保存信息至文件 |\n");
printf("\t| 0.退出系统 |\n");
printf("\t|---------------------------------------------------|\n");
}
//分数菜单
void gradeMenu(){
printf("\t|---------------------------------------------------|\n");
printf("\t| 学生成绩分段表 |\n");
printf("\t|---------------------------------------------------|\n");
printf("\t| 1.60以下 |\n");
printf("\t| 2.60~79 |\n");
printf("\t| 3.80~89 |\n");
printf("\t| 4.90以上 |\n");
printf("\t|---------------------------------------------------|\n");
}
//创建头结点
StuLinkList createHeadNode(){
Node *head = NULL;
head = (Node *)malloc(sizeof(Node)); //malloc是在堆上分配的地址 函数结束后 head的生存期还存在 因此可以返回结构体指针
if( !head ){
printf("头结点分配失败!\n"); //分配未成功说明内存不够,直接让函数结束
return NULL;
}else{
head->next = NULL;
}
return head;
}
//添加n个学生数据 (n从键盘输入)
void addStuinfo(Node *head){
int n; //输入信息的个数
int i; //用来for循环
printf("\n请输入初始化添加学生的个数:\n");
scanf("%d",&n);
for(i = 0;i < n;i++){
Node *p = (Node *)malloc(sizeof(Node));
p->next = NULL; //指针先赋值为空 防止野指针的出现
printf("\n请输入第%d个学生学号、姓名、分数\n",i+1);
scanf("%s%s%f",&p->stu.sno,&p->stu.name,&p->stu.grade);
//头插法链接再头结点后面
p->next = head->next; //将本来头结点的指针域的值(下一个结点的地址)赋值给在新结点指针域(相当于原来的结点链在了新结点上)
head->next = p; //将新的结点链接在头结点后面(完成头插法)
}
printf("\n添加成功!\n");
}
//查询学生成绩
void searchStuinfo(Node *head){
char temp[20];
int flag = 0; //标志找没找到
Node *p = head->next; //头结点无数据,无须遍历
if(p == NULL){
printf("此链表中无记录!\n ");
return;
}
printf("\n请输入要查询成绩的学生学号:");
scanf("%s",&temp);
while(p != NULL){
if(strcmp(temp,p->stu.sno) == 0){ //strcmp函数
flag = 1;
printf("\n-------------------------------------------------------------------------------------\n");
printf("学号:%s\t\t",p->stu.sno);
printf("姓名:%s\t\t",p->stu.name);
printf("成绩:%.2f\n",p->stu.grade);
break;
}else{
p = p->next; //没找到往后遍历
}
}
if(flag == 0){
printf("\n不存在该学生信息!\n");
}
printf("\n");
}
//输出所有链表元素
void displayStuinfo(Node *head){
Node *p = head->next; //头结点无数据,无须遍历
if(p == NULL){
printf("此链表中无记录!\n ");
return;
}
printf("\n-----------------------------------------------\n");
printf("学号 姓名 成绩 \n");
printf("-------------------------------------------------\n");
while(p != NULL){
//输出信息
printf("%s\t%s\t\t%.2f\n",p->stu.sno,p->stu.name,p->stu.grade); //.2f为控制输出为小数点后两位 ///%15为控制输出间距
p = p->next; //每打印一次信息使其往后遍历
}
printf("\n");
}
//根据成绩分段输出链表元素
void displaygradeStuinfo(Node *head){
int choice;
int flag = 0; //标志
float fenshu1[4] = {0,60,80,90}; //分数下限数组
float fenshu2[4] = {59,79,89,100}; //分数上限数组
Node *p = head->next; //头结点无数据,无须遍历
if(p == NULL){
printf("此链表中无记录!\n ");
return;
}
gradeMenu();
printf("\n请输入选择:");
scanf("%d",&choice);
while(p != NULL){
//判断
if(p->stu.grade >= fenshu1[choice-1] && p->stu.grade <= fenshu2[choice-1]){
flag = 1;
printf("\n-------------------------------------------------------------------------------------\n");
printf("学号:%s\t\t",p->stu.sno);
printf("姓名:%s\t\t",p->stu.name);
printf("成绩:%.2f\n",p->stu.grade); //.2f为控制输出为小数点后两位
}
p = p->next; //往后遍历
}
if(flag == 0){
printf("\n该分数段不存在学生!\n");
}
printf("\n");
}
//将文件中的数据读入到链表中
void readStuinfo(Node *head){
Node *p1 = head; //p1指向的头结点
Node *p2 = NULL;
FILE *fp = NULL;
//fp = fopen("data.txt","r"); //文件指针
fp = fopen("data.dat","rb"); //以r的方式 文件是data.txt 和当前代码所在路径一样 (相对路径)
if(fp == NULL){ //没在当前路径找到data文件
printf("本地不存在文件!\n\n");
return;
}
while(1){ //死循环直到文件末尾 //feof = f end of file 到达文件末尾就break退出while循环
//开辟结点fscanf从文件读取数据 并链接在链表上
p2 = (Node *)malloc(sizeof(Node));
fscanf(fp,"%s %s %f\n",&p2->stu.sno ,&p2->stu.name ,&p2->stu.grade);
p2->next = NULL;
p1->next = p2; //将新建的p2结点的地址赋值给p1(头)结点的指针域,进行连接
p1 = p1->next; //p1后移在次从文本读取数据到链表
if(feof(fp)){
break;
}
}
fseek(fp, 0, SEEK_SET);
fclose(fp); //关闭文件
printf("信息读取成功!\n");
}
//将链表中的数据写入文件
void writeStuinfo(Node *head){
struct Node *p = head->next; //头结点无数据不需要写入文件中
FILE *fp = NULL; //文件指针
//fp = fopen("data.dat","w");
fp = fopen("data.dat","wb");
while( p != NULL ){ //不到链表末尾就一直fprintf往文件里写数据
fprintf(fp,"%s %s% f\n",p->stu.sno ,p->stu.name ,p->stu.grade);
p = p->next;
}
fseek(fp, 0, SEEK_SET);
fclose(fp);//关闭文件
printf("信息保存成功!\n");
}
//修改学生成绩
void updateStuinfo(Node *head){
char temp[20];
int flag = 0; //标志
Node *p = head->next;
if(p == NULL){
printf("此链表中无记录!\n ");
return;
}
printf("\n请输入要修改成绩的学生学号:");
scanf("%s",&temp);
while(p != NULL){
if(strcmp(p->stu.sno,temp) == 0){ //找到就输出信息
flag = 1;
printf("\n-------------------------------------------------------------------------------------\n");
printf("\n旧的信息为:\n");
printf("学号:%s\t\t",p->stu.sno);
printf("姓名:%s\t\t",p->stu.name);
printf("成绩:%.2f\n",p->stu.grade);
printf("\n请输入该学生新的成绩:");
scanf("%f",&p->stu.grade);
printf("修改成功!\n");
writeStuinfo(head);
break;
}else{
p = p->next; //没找到往后遍历
}
}
if(flag == 0){
printf("\n不存在该学生信息!\n");
}
printf("\n");
}
int main(){
int choice;
Node *head = NULL; //头指针
head = createHeadNode(); //创建一个带头结点的空链表
readStuinfo(head); //读取文本的信息
while(1){
Menu();
printf("请输入选择:");
scanf("%d",&choice);
switch(choice){
case 1:
addStuinfo(head);
system("pause");
system("cls");
break;
case 2:
searchStuinfo(head);
system("pause");
system("cls");
break;
case 3:
updateStuinfo(head);
system("pause");
system("cls");
break;
case 4:
displayStuinfo(head);
system("pause");
system("cls");
break;
case 5:
displaygradeStuinfo(head);
system("pause");
system("cls");
break;
case 6:
writeStuinfo(head);
system("pause");
system("cls");
break;
case 0:
printf("退出成功!\n");
exit(0);
default:
printf("输入错误!请重新输入!\n");
system("pause");
system("cls");
break;
}
}
return 0;
}