C语言:将运行无误的键盘输入数据的程序改写成文件输入并保存,如何从同一个文件向两个 struct 输入
声明:1我的键盘输入数据进行操作的肯定没错的,要添加的只有一个load函数(从某个text里输入数据),和保存在另一个文件用的save函数2由于百度知道没法穿文件,所以我只能拍个图,如果有意愿的大神私信或者啥的留个什么方式,我把代码传过去这样改着方便。
3我大概知道怎么改,用fread(&stu[i],sizeof(struct student),1,fp),可是我这个程序里用了两个struct结构,不知道怎么从一个文件顺序地给两个strcut输入,fread(&cou[i],sizeof(struct cou),1,fp)的话不是和第一个fread一样都从头读了嘛。。。
4觉得可能用到fseek吧。。。
5啰啰嗦嗦说了好多,其实就是希望大神帮忙,自学不容易啊,input sort啥的可以忽略,我就是搞不懂怎么输入输出,只要改动不大,实现输入数据和另外保存就好。
输入数据的格式大概:一开始四门课程名字 之后是结构体stu[]的数据
我的原来键盘输入和我自己改的都发上来好了(我自己改的总说打不开文件= =)
改的:
#include<stdio.h>
#include<stdlib.h>
#include<process.h>
#define H 6//预处理宏定义命令(定义一个宏),预处理:在程序编译前先进行替换,将所有H替换为6;
//另外在C语言里宏定义只用来做的宏名替换,而不做语法检查的,因而它不是C语句,所以在宏定义的时候不需要在后面加";"
//便于更普遍的学生成绩排名的应用
#define L 4//所有L替换为4,同理H
struct course// (自学第9章内容后)声明一个结构体类型struct course
//选择struct,放弃数组是因为:学生成绩、对应课程等的一些联系紧密,结构较数组清晰
//在main函数里声明其他函数要想调用需要首先调用main函数,但是在main函数外面声明的函数调用是可直接调用
//所以在本上机作业中,为了在四个函数中都直接调用,采用在main函数外部声明
{
char name[L][50];//成员name为字符串,代表L门课程的名称
}cou;//定义course结构体变量cou
struct student// 声明一个结构体类型struct student
{
char name[10];//成员name为字符串,代表学生姓名
int score[L];//成员score为整型,代表L门课程的成绩
float ave;//成员ave为浮点型,代表某个学生的平均成绩
int max,min,maxid,minid,maxnum,minnum;// 最大、最小以及它们的次序
// int order;//名次
}stu[H];//定义student结构体下的数组stu
FILE*fp;
void input()//定义input函数,功能:累积总成绩求均分+比较最高最低记录ID
//先声名了函数input、sort、show,所以在之后的main函数中不用再声明
{
int i,j;
float sum=0.0;//总分
for(i=0;i<H;i++)
{
sum+=stu[i].score[j];//每次循环同时累加L门课程总分
if(j==0)
{
stu[i].max=stu[i].score[0];//max是结构体数组stu[]中的成员,代表最高分;
stu[i].maxid=0;//正如命名ID仅仅用于后面打印最高最低分对应课程名称的指示,如:cou.name[(stu[i].maxid)]
stu[i].min=stu[i].score[0];//j=0时,将学生第一门的成绩赋予最大和最小,初始化
stu[i].maxid=0;//j=o时,将学生的最高最低成绩ID初始化=0
}
if(stu[i].score[j]<stu[i].min)//以最小的基准,比较某名学生成绩(如果某门成绩<之前比较得出的最小的成绩)
{
stu[i].min=stu[i].score[j];//当满足比累计的最小值还小时,将此成绩替换给最小值
stu[i].minid=j;//记录当前最小值的次序
}
if(stu[i].max<stu[i].score[j])//同理以最小为基准的比较操作(如果某门成绩》之前比较得出的最大的成绩)
{
stu[i].max=stu[i].score[j];
stu[i].maxid=j;
}
}
stu[i].ave=sum/L;//求平均分数
sum=0;//为下一名学生累计总分清零
}
void sort()//定义函数sort,调整顺序+最高最低的排名,将排名第一的(一整行)放在上面,所以输出排名时候输出的直接是i+1
{
int i,j;
struct student ch;//定义结构体数组ch,它和stu有同样的成员,作为替换过程中的中间变量使用
for(i=0;i<H;i++)
{ stu[i].maxnum=1;//初始化最大最小值的排名
stu[i].minnum=H;
for(j=0;j<H;j++)
{
if(stu[i].score[(stu[i].maxid)]<stu[j].score[(stu[i].maxid)])
stu[i].maxnum++;
if(stu[i].score[(stu[i].minid)]>stu[j].score[(stu[i].minid)])
stu[i].minnum--;
}
}
for(i=0;i<H;i++)//不要企图用i.j.k一个嵌套的大的for循环实现如结果所示的总排名上的顺序调整以及最高最低的正确排名。
//因为j,k的比较方式不同,“行变换”会导致混乱。
{
for(j=i+1;j<H;j++)//每次和后面的学生平均分比较
{
if(stu[i].ave<stu[j].ave)
{
ch=stu[i];//若满足要求,则将结构体数组中的整行互换,达到排序作用
stu[i]=stu[j];
stu[j]=ch;
}
}
}
}
void show()//定义函数show,功能:按要求和顺序打印
{
int i;
for(i=0;i<H;i++)
{printf("\n");//细节:与输入部分分开
printf("姓名:%s\t均分:%5.2f\t总排名:%d\n最高分:%d\t最高分排名:%d\t课程名称:%s\n最低分:%d\t最低分排名:%d\t课程名称:%s\n\n",stu[i].name,stu[i].ave,i+1,stu[i].max,stu[i].maxnum,cou.name[(stu[i].maxid)],stu[i].min,stu[i].minnum,cou.name[(stu[i].minid)]); }//打印的平均分是浮点型,且要求共5位长度,小数位为2;由于原始成绩无小数点,所以打印整型;它们以一个tab间距隔开
printf("\n");//细节:与press any key to continue分开
}
void save()
{
int i;
if((fp=fopen("G:\\上机\\上机1\\stu2.text","wb"))==NULL)////初始化文件指针fp同时判断fp是否是为打开了一个并不存在的文件,fopen带回的空指针
//打开文件名为stu1的文本text;二进制文件,wb:只写
{
printf("打不开文件\n");
exit(0);//关闭所有文件,终止正在运行程序,待用户检查错误
}
for(i=0;i<H;i++)//循环存储
if(fwrite(&stu[i],sizeof(struct student),1,fp)!=1)//判断fread()函数有没有操作成功
printf("文件书写错误\n");
fclose(fp);
}
void load()
{
int i;
if((fp=fopen("G:\\上机\\上机1\\stu1.text","rb"))==NULL)//初始化文件指针fp同时判断fp是否是为打开了一个并不存在的文件,fopen带回的空指针
//打开文件名为stu1的文本text;二进制文件,rb:只读
{
printf("打不开文件\n");
exit(0);//关闭所有文件,终止正在运行程序,待用户检查错误
}
for(i=0;i<L;i++)
fscanf(fp,"%s",&cou.name[i]);
fseek(fp,sizeof(struct course),0);
for(i=0;i<H;i++)
{
if(fread(&stu[i],sizeof(struct student),1,fp)!=1)//判断fread()函数有没有操作成功
{
if(feof(fp))//feof()是文件结束检测函数,如果没有结束,返回值是0,结束了是1
{
fclose(fp);
exit;
}//关闭所有文件,终止正在运行程序,待用户检查错误
printf("文件读取错误\n");
}
fclose(fp);
}
for(i=0;i<H;i++)//循环读取
if(fread(&stu[i],sizeof(struct student),1,fp)!=1)//判断fread()函数有没有操作成功
{
if(feof(fp))//feof()是文件结束检测函数,如果没有结束,返回值是0,结束了是1
{
fclose(fp);
exit(0);
}//关闭所有文件,终止正在运行程序,待用户检查错误
printf("文件读取错误\n");
}
fclose(fp);
}
int main()
{
load();
input();
sort();
show();
save();
return 0;
}
这个是运行无误键盘输入
#include<stdio.h>
#define H 6
#define L 4//所有L替换为4,同理H
struct course// (自学第9章内容后)声明一个结构体类型struct course
{
char name[L][50];//成员name为字符串,代表L门课程的名称
}cou;//定义course结构体变量cou
struct student// 声明一个结构体类型struct student
{
int score[L];//成员score为整型,代表L门课程的成绩
char name[10];//成员name为字符串,代表学生姓名
float ave;//成员ave为浮点型,代表某个学生的平均成绩
int max,min,maxid,minid,maxnum,minnum;// 最大、最小以及它们的次序
// int order;//名次
}stu[H];//定义student结构体下的数组stu
void input()//定义input函数,功能:输入数据+累积总成绩求均分+比较最高最低记录ID
//先声名了函数input、sort、show,所以在之后的main函数中不用再声明
{
printf("请输入%d门课程的名称\n",L);
int i,j;
float sum=0.0;//总分
for(i=0;i<L;i++)
{
scanf("%s",cou.name[i]);
}
for(i=0;i<H;i++)//循环输入H个学生的姓名和成绩,
{ printf("请输入第%d名学生姓名:",i+1);//对应每个i(学生),都提示输入姓名
scanf("%s",stu[i].name);
for(j=0;j<L;j++)
{printf("请输入此学生第%d门课程成绩:",j+1);//对应每个j(学生某门成绩),都提示输入成绩
scanf("%d",&stu[i].score[j]);
sum+=stu[i].score[j];//每次循环同时累加L门课程总分
if(j==0)
{
stu[i].max=stu[i].score[0];//max是结构体数组stu[]中的成员,代表最高分;
stu[i].maxid=0;//正如命名ID仅仅用于后面打印最高最低分对应课程名称的指示,如:cou.name[(stu[i].maxid)]
stu[i].min=stu[i].score[0];//j=0时,将学生第一门的成绩赋予最大和最小,初始化
stu[i].maxid=0;//j=o时,将学生的最高最低成绩ID初始化=0
}
if(stu[i].score[j]<stu[i].min)//以最小的基准,比较某名学生成绩(如果某门成绩<之前比较得出的最小的成绩)
{
stu[i].min=stu[i].score[j];//当满足比累计的最小值还小时,将此成绩替换给最小值
stu[i].minid=j;//记录当前最小值的次序
}
if(stu[i].max<stu[i].score[j])//同理以最小为基准的比较操作(如果某门成绩》之前比较得出的最大的成绩)
{
stu[i].max=stu[i].score[j];
stu[i].maxid=j;
}
}
stu[i].ave=sum/L;//求平均分数
sum=0;//为下一名学生累计总分清零
}}
void sort()//定义函数sort,调整顺序+最高最低的排名,将排名第一的(一整行)放在上面,所以输出排名时候输出的直接是i+1
{
int i,j;
struct student ch;//定义结构体数组ch,它和stu有同样的成员,作为替换过程中的中间变量使用
for(i=0;i<H;i++)
{ stu[i].maxnum=1;//初始化最大最小值的排名
stu[i].minnum=H;
for(j=0;j<H;j++)
{
if(stu[i].score[(stu[i].maxid)]<stu[j].score[(stu[i].maxid)])
stu[i].maxnum++;
if(stu[i].score[(stu[i].minid)]>stu[j].score[(stu[i].minid)])
stu[i].minnum--;
}
}
for(i=0;i<H;i++)//不要企图用i.j.k一个嵌套的大的for循环实现如结果所示的总排名上的顺序调整以及最高最低的正确排名。
//因为j,k的比较方式不同,“行变换”会导致混乱。
{
for(j=i+1;j<H;j++)//每次和后面的学生平均分比较
{
if(stu[i].ave<stu[j].ave)
{
ch=stu[i];//若满足要求,则将结构体数组中的整行互换,达到排序作用
stu[i]=stu[j];
stu[j]=ch;
}
}
}
}
void show()//定义函数show,功能:按要求和顺序打印
{
int i;
for(i=0;i<H;i++)
{printf("\n");//细节:与输入部分分开
printf("姓名:%s\t均分:%5.2f\t总排名:%d\n最高分:%d\t最高分排名:%d\t课程名称:%s\n最低分:%d\t最低分排名:%d\t课程名称:%s\n\n",stu[i].name,stu[i].ave,i+1,stu[i].max,stu[i].maxnum,cou.name[(stu[i].maxid)],stu[i].min,stu[i].minnum,cou.name[(stu[i].minid)]); }//打印的平均分是浮点型,且要求共5位长度,小数位为2;由于原始成绩无小数点,所以打印整型;它们以一个tab间距隔开
printf("\n");//细节:与press any key to continue分开
}
int main()
{
input();
sort();
show();
return 0;
}