C语言编一个成绩记录簿
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1. 设计要求:
成绩记录簿中记录以下数据:学号、姓名、课程编号、课程名称、成绩、学分,所有成绩都以百分制计分。
在程序中可以输入新的成绩记录,可以按学号或姓名查询一个学生的所有成绩,和已完成的总学分。
也可以按课程编号查出一个班的成绩表,班成绩表后面要统计平均分,和及格率。
2. 提高水平
在程序中增加将数据写入文本文件和从文件中读入数据的功能,文件名由用户输入。
3. 提示
在没有使用文件时,数据可以保存在一个大的数组中,要注意的数据项的类型。
知识范围;C程序设计第三版谭浩强
答案一
// 包含必须的头文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// 定义课程的结构体
struct course
{
int num; //课程编号
char name[20]; // 课程名字
int result; // 学生的成绩
float credit; // 学分
};
// 定义成绩记录簿的结构体,每个学生修了4门课
struct scorelist
{
int num; //学号
char name[10]; //学生姓名
struct course subject[4]; //课程相关的数据。
意思是一个学生修了4门课
};
int n=0; // n用来存储一共有多少个学生
struct scorelist score[200]; //初始化成绩记录簿,上限为200条学生成绩
// 查询课程的函数
void queryclass()
{
int number,i,j,max=0,count=0;
float average;//平均分
float pass=0; //及格人数
printf("*********请输入要查询的课程编号:");
scanf("%d",&number);
// 遍历所有的学生,打印每个学生修的课程成绩
for(i=0;i<n;i++) // 遍历所有学生
{ for(j=0;j<4;j++) // 遍历当前学生所修的4门课
{
if(score[i].subject[j].num==number) // 如果符合此条件,说明当前条目即为用户查询的课程
{
printf("学号:%d 姓名:%s %s:%d\n",score[i].num,score[i].name,score[i].subject[j].name,score[i].subject[j].res ult);
if(score[i].subject[j].result>=60)
pass++;
max+=score[i].subject[j].result;
count++;
}
}
}
if(count!=0)
{
average=(float)max/count;
pass=pass/count;
printf("平均分:%f\n",average);
printf("及格率:%.2f%c\n\n",pass*100,37);
}
}
// 查询学生信息
void querystudent()
{ char xm[10];
int i,flag=0,j,a,xh;
printf("*********请输入要查询的项目: 1.学号 2.姓名;");
scanf("%d",&a);
if(a==1) scanf("%d",&xh);
else scanf("%s",xm);
// 根据用户输入判定用户是根据学号还是姓名查询
switch(a)
{
// 根据学号查询
case 1:
// 遍历查找用户所输入的学号
for(i=0;i<n;i++)
if(score[i].num==xh){
j=i;flag=1;}
if(flag==0) printf("*****抱歉没有找到.******"); // 没有找到,跳出
else //找到了用户输入的学号,打印
{ printf("学号:%d 姓名: %s\n",score[j].num,score[j].name);
printf("**课程编号课程名称课程成绩课程学分**\n");
for(i=0;i<4;i++)
{printf("%d %s %d %5.2f\n",score[j].subject[i].num,
score[j].subject[i].name,score[j].subject[i].result,score[j].subject[i].credit);
}
}
break;
// 根据姓名查询
case 2:
// 遍历查找用户输入的姓名
for(i=0;i<n;i++)
if(strcmp(score[i].name,xm)==0)
{j=i;flag=1;
}
if(!flag) printf("*****抱歉没有找到.******");
else // 找到了用户输入的学生姓名,打印
{ printf("学号:%d 姓名: %s\n",score[j].num,score[j].name);
printf("课程编号课程名称课程成绩课程学分\n");
for(i=0;i<4;i++)
{
printf("%d %s %d %f\n",score[j].subject[i].num,
score[j].subject[i].name,score[j].subject[i].result,score[j].subject[i].credit);
}
}
break;
default:printf("****输入错误!!****");
}
}
// 删除一条学生记录
void del()
{ char xm[10];
int i,flag=0,j,a,xh;
printf("****请输入要删除的项目: 1.学号 2.姓名:");
scanf("%d",&a);
// 根据用户输入进行不同的查找
switch(a)
{
// 接收用户输入为学号
case 1:scanf("%d",&xh);
// 查找此学号的记录
for(i=0;i<n;i++)
if(score[i].num==xh) // 找到
{
for(j=i;j<n-1;j++) //进行删除,策略是用后一项覆盖前一项,达到删除目的
score[j]=score[j+1];
n=n-1;flag=1;
}
if(!flag)printf("*****抱歉没有找到.******\n");break;
// 接收用户输入为姓名。
原理同上
case 2:scanf("%d",&xm);
for(i=0;i<n;i++)
if(strcmp(score[i].name,xm)==0)
{for(j=i;j<n-1;j++)
score[j]=score[j+1];
n=n-1;flag=1;
}
if(!flag)printf("not found!\n");break;
default:printf("错!请再输入一遍");
}
}
// 添加一条记录。
原理是提示并接收用户输入,然后储存到当前的学生记录(用n的值指示当前记录)
void append()
{ char ch;
int choice;
int i;
while(1)
{
system("cls");
printf("****请输入学号:");
scanf("%d",&score[n].num);
printf("****请输入姓名:");
scanf("%s",score[n].name);ch=getchar();
for(i=0;i<4;i++)
{ printf("***请输入第%d门的课程编号:",i+1);
scanf("%d",&score[n].subject[i].num);
printf("***请输入第%d门的课程名称:",i+1);
scanf("%s",score[n].subject[i].name);
printf("***请输入第%d门的课程成绩:",i+1);
scanf("%d",&score[n].subject[i].result);
printf("***请输入第%d门的课程学分:",i+1);
scanf("%f",&score[n].subject[i].credit);
}
n++;
printf("\n1、继续添加2、退出[ ]\b\b");
scanf("%d",&choice);
if(choice==2) break;
}
}
// 写入文件
void writefile()
{ FILE *fp;
int i;
fp=fopen("score_list","wb");//以写二进制的模式打开文件
//遍历所有记录,并把每一个结构体对象以二进制形式写入文件
for(i=0;i<=n-1;i++)
fwrite(&score[i],sizeof(struct scorelist),1,fp);
printf(" 文件已保存为scorelist\n\n");
fclose(fp); //关闭文件
}
// 读文件,并初始化学生成绩数组
void readfile()
{ struct scorelist add;
FILE *fp;
n=0;
fp=fopen("score_list","rb"); // 以读取二进制文件的模式打开文件
fread(&add,sizeof(struct scorelist),1,fp); // 读取一个结构体长度的数据并把它付给add对象。
// 持续读取文件,初始化新的add对象,并把它加到score的数组中去
while(!feof(fp)){
score[n]=add;n++;
fread(&add,sizeof(struct scorelist),1,fp);
}
printf(" 文件scorelist已读取\n");
fclose(fp); // 关闭文件
}
// 主程序入口
main()
{
int a;
struct scorelist add;
FILE *fp;
// 如果没有score_list这个文件,创建它
if((fp=fopen("score_list","rb"))==NULL)
fp=fopen("score_list","wb");
else{ // 如果有score_list这个文件,那么将其中的数据读取到全局的score数组。
参考readfile()
fread(&add,sizeof(struct scorelist),1,fp);
while(!feof(fp)){
score[n]=add;n++;
fread(&add,sizeof(struct scorelist),1,fp);
}
}
fclose(fp);
// 程序一直读取用户输入并解析,然后调用不同的函数进行处理,并返回结果。
while(1)
{
printf("************************************************************************* *******");
printf("\t\t 欢迎Welcome to\n");
printf("\n\t\t\t 使用成绩记录簿系统1.0\n");
printf("****copyright归山东超峰所有********************在此鸣谢百度知道老师****************\n") ;
printf("*************************************MENU****************************** *********");
printf("\n");
printf(" 成绩记录簿\n");
printf("** ****1.添加\n");
printf("** *****2.删除\n");
printf("** *****3.查学生成绩\n");
printf("** *****4.查班成绩表(附加功能@显示平均分和及格率@)\n");
printf("** *****5.写入文件\n");
printf("** *****6.读取文件\n");
printf("** *****0.退出\n");
printf("\n\t\t输入你的选择Enter your choice(0--6):");
scanf("%d",&a);
getchar();
switch(a)
{
case 1:append();break;
case 2:del();break;
case 3:querystudent();break;
case 4:queryclass();break;
case 5:writefile();break;
case 6:writefile();readfile();break;
case 0:writefile();exit(0);break;
default:printf("*********错!请再输入一遍********");
}
}
}
答案二
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1000
typedef struct Lesson //定义课程结构体
{
int Lesson_Num;
char Lesson_Name[50];
int Lesson_Mark;
int Lesson_Credit;
}Lesson;
typedef struct Student //定义学生的结构体
{
char Name[50];
int Num;
int Lesson_Count;
Lesson L[20];
}Student;
Student S[MAX];
static int Student_Count = 0; //记录学生数的变量
void PrintInterface(); //打印界面
int AddStudent(); //添加,带返回值,提示操作成功
int DelStudent(); //删除,带返回值,提示操作成功
void CheckStudent(); //查学生成绩
void CheckClass(); //查班成绩表
void WriteFile(); //写入文本文件
void ReadFile(); //读取文本文件
void main()
{
int Choice;
while (1)
{
PrintInterface();
scanf("%d%*c", &Choice); //"%*c"是吸收回车的,因为后面会输入字母类型
if (Choice >= 0 && Choice <= 6) //选择操作合法
{
switch (Choice)
{
case 0: exit(1);
case 1:
{
system("cls");
if (AddStudent()) printf("\n添加成功...回车继续\n");
else printf("\n添加失败...回车继续\n");
getchar();
getchar();
system("cls");
break;
}
case 2:
{
system("cls");
if (DelStudent()) printf("\n删除成功...回车继续\n");
else printf("\n删除失败...回车继续\n");
getchar();
getchar();
system("cls");
break;
}
case 3:
{
system("cls");
CheckStudent();
system("cls");
break;
}
case 4:
{
system("cls");
CheckClass();
system("cls");
break;
}
case 5: WriteFile();system("cls");break;
case 6: ReadFile();system("cls");break;
default:;
}
}
else
{
printf("无此功能..重新选择..回车确定\n"); //选择操作非法
getchar();
system("cls"); //清屏函数
}
}
}
void PrintInterface()
{
printf("\t -------------------------- \n");
printf("\t| 1、添加|\n");
printf("\t| |\n");
printf("\t| 2、删除|\n");
printf("\t| |\n");
printf("\t| 3、查学生成绩|\n");
printf("\t| |\n");
printf("\t| 4、查班成绩表|\n");
printf("\t| |\n");
printf("\t| 5、写入文本文件|\n");
printf("\t| |\n");
printf("\t| 6、读取文本文件|\n");
printf("\t| |\n");
printf("\t| 0、退出|\n");
printf("\t -------------------------- \n");
printf("\t选择操作:");
}
int AddStudent()
{
int S_count, i, j;
printf("\n添加中......\n");
printf("\n添加学生人数(如1、2 ……999):");
scanf("%d", &S_count);
if (Student_Count + S_count >= MAX) return 0; //超过了数组上限
for (i = Student_Count; i < Student_Count + S_count; i++)
{
printf("\n\t第%d个学生:\n", i - Student_Count + 1);
printf("\n\t学生学号:"); scanf("%d%*c", &S[i].Num);
printf("\n\t学生姓名:"); gets(S[i].Name);
printf("\n\t该学生所修课程数:"); scanf("%d", &S[i].Lesson_Count);
for (j = 0; j < S[i].Lesson_Count; j++)
{
printf("\n\t第%d门课:\n", j + 1);
printf("\n\t\t课程编号:"); scanf("%d%*c", &S[i].L[j].Lesson_Num);
printf("\n\t\t课程名称:"); gets(S[i].L[j].Lesson_Name);
printf("\n\t\t课程成绩:"); scanf("%d", &S[i].L[j].Lesson_Mark);
printf("\n\t\t课程学分:"); scanf("%d", &S[i].L[j].Lesson_Credit);
if (S[i].L[j].Lesson_Mark < 60) S[i].L[j].Lesson_Credit = 0; //不及格的课程学分为0
}
}
Student_Count += S_count;
return 1;
}
int DelStudent()
{
char *D_Name;
int D_Num;
int i, j;
printf("\n填写待删除学生的信息:\n");
printf("\n学生姓名:"); gets(D_Name);
printf("\n学生学号:"); scanf("%d", &D_Num);
for (i = 0; i < Student_Count; i++)
{
if (!strcmp(S[i].Name, D_Name) && S[i].Num == D_Num)
{
printf("\n找到该学生,删除中......\n");
for (j = i + 1; j < Student_Count; j++)
{
S[j - 1] = S[j];
}
break;
}
}
if (i == Student_Count)
{
printf("\n未找到该学生...请核对所填信息\n\n");
return 0;
}
else
{
Student_Count--;
return 1;
}
}
void CheckStudent()
{
int C_Choice;
char C_Name[50];
int C_Num;
int i, j;
printf("\n输入所查学生信息(1.姓名\\ 2.学号)选择:");
scanf("%d%*c", &C_Choice);
printf("\n查找中......\n");
if (C_Choice == 1 || C_Choice == 2) //选择合法
{
if (C_Choice == 1)
{
printf("\n姓名:"); gets(C_Name);
for (i = 0; i < Student_Count; i++) //全部穷举,防止同名同姓
{
if (!strcmp(S[i].Name, C_Name))
{
printf("\n学号:%d\t姓名:%s\n", S[i].Num, S[i].Name);
printf("\n课程编号\t课程名称\t课程成绩\t课程学分\n");
printf("-----------------------------------------------------\n");
for (j = 0; j < S[i].Lesson_Count; j++)
{
printf("%d\t\t%s\t\t%d\t\t%d\n", S[i].L[j].Lesson_Num,
S[i].L[j].Lesson_Name, S[i].L[j].Lesson_Mark,
S[i].L[j].Lesson_Credit);
printf("-----------------------------------------------------\n");
}
printf("\n\n");
}
}
}
else
{
printf("\n学号:"); scanf("%d%*c", &C_Num);
for (i = 0; i < Student_Count; i++) //不用全部穷举,学号唯一
{
if (S[i].Num == C_Num)
{
printf("\n学号:%d\t姓名:%s\n", S[i].Num, S[i].Name);
printf("\n课程编号\t课程名称\t课程成绩\t课程学分\n");
printf("-----------------------------------------------------\n");
for (j = 0; j < S[i].Lesson_Count; j++)
{
printf("%d\t\t%s\t\t%d\t\t%d\n", S[i].L[j].Lesson_Num,
S[i].L[j].Lesson_Name, S[i].L[j].Lesson_Mark,
S[i].L[j].Lesson_Credit);
printf("-----------------------------------------------------\n");
}
printf("\n\n");
break;
}
}
}
printf("查找完毕...回车继续\n");
getchar();
}
else //选择不合法
{
printf("选择错误...回车继续\n");
getchar();
return;
}
}
void CheckClass()
{
int C_LNum;
double SSNum = 0, PassSNum = 0, SMark = 0;
int i, j;
printf("\n请输入课程编号:");
scanf("%d%*c", &C_LNum);
printf("\n查找中......\n\n");
printf("学号\t姓名\t课程名称\t课程成绩\t课程学分\n");
printf("----------------------------------------------------\n");
for (i = 0; i < Student_Count; i++)
{
for (j = 0; j < S[i].Lesson_Count; j++)
{
if (S[i].L[j].Lesson_Num == C_LNum)
{
printf("%d\t%s\t%s\t\t%d\t\t%d\n", S[i].Num, S[i].Name,
S[i].L[j].Lesson_Name,
S[i].L[j].Lesson_Mark,
S[i].L[j].Lesson_Credit);
printf("----------------------------------------------------\n");
SMark += S[i].L[j].Lesson_Mark;
SSNum ++;
if (S[i].L[j].Lesson_Mark >= 60) PassSNum++;
break;
}
}
}
printf("\n平均分:%.2lf\t及格率:%.2lf%%\n\n", SMark / SSNum, PassSNum / SSNum * 100);
printf("\n查找完毕...回车继续\n");
getchar();
}
void WriteFile()
{
FILE *fp;
int i, j;
char Adr[100];
printf("\n请输入写入的文件地址:\n\n地址输入格式:例如d:\\\\Student.txt(\\\\为转义字符):");
scanf("%s%*c", Adr);
printf("\n写入中......\n");
if (fp = fopen(Adr,"w")) //写入文件
{
fprintf(fp,"%d\n",Student_Count);
for (i = 0; i < Student_Count; i++)
{
fprintf(fp,"%d\t%s\t%d\n",S[i].Num, S[i].Name,S[i].Lesson_Count);
for (j = 0; j < S[i].Lesson_Count; j++)
{
fprintf(fp,"%d\t%s\t%d\t%d\n", S[i].L[j].Lesson_Num,
S[i].L[j].Lesson_Name,S[i].L[j].Lesson_Mark,
S[i].L[j].Lesson_Credit);
}
}
printf("\n写入完成...回车继续\n");
fclose(fp);
}
else
{
printf("\n写入失败...回车继续\n");
}
getchar();
}
void ReadFile()
{
FILE *fp;
int i, j;
char Adr[100];
printf("\n请输入读取(为防止读入错误,希望与写入文件内容格式一致)的文件地址:\n\n地址输入格式:例如d:\\\\Student.txt(\\\\为转义字符):");
scanf("%s%*c", Adr);
printf("\n读取中......\n");
if (fp = fopen(Adr,"r"))
{
fscanf(fp,"%d",&Student_Count);
for (i = 0; i < Student_Count; i++)
{
fscanf(fp,"%d%s%d",&S[i].Num, &S[i].Name,&S[i].Lesson_Count);
for (j = 0; j < S[i].Lesson_Count; j++)
{
fscanf(fp,"%d%s%d%d",&S[i].L[j].Lesson_Num,
&S[i].L[j].Lesson_Name,&S[i].L[j].Lesson_Mark,
&S[i].L[j].Lesson_Credit);
}
}
printf("\n读取成功...回车继续\n");
fclose(fp);
}
else
{
printf("\n读取失败...回车继续\n");
}
getchar();
}。