读写数据块函数fread怎么用?

本人照题目设计了个程序,想用fread读取数据,结果......
题目是:某班有30名学习,每名学生的数据包括学号、姓名、3门课的成绩,输入20名学生的数据,要求打印出3门课总平均成绩,以及总分最高的学生的数据(包括学号、姓名、3门课成绩,平均成绩)。
#include <stdio.h>
struct student
{ long num;
char name[10];
float score[3];
} stu[20];
float SUM(float *a)
{ int i;
float sum=0;
for(i=0;i<3;i++)
sum+=*(a+i);
return sum;
}
void main()
{
FILE *fp;
int i,j=0,k;
float sum=0,aver,max;
clrscr();
if((fp=fopen("data.txt","r"))==NULL)
{
printf("Can't open this file\n");exit(0);
}
for(i=0;i<20;i++)
{ fread(&stu[i],sizeof(struct student),1,fp);/* 使用读写数据块函数fread,结果运行得不到正确答案 */
/* 如果用后面这种格式化读写一点错都没有:
fscanf(fp,"%ld%s%f%f%f",&stu[i].num,stu[i].name,&stu[i].score[0],&stu[i].score[1],&stu[i].score[2]);*/
sum=sum+SUM(stu[i].score);
}
aver=sum/60;
printf("Average score is: %5.2f\n",aver);
max=SUM(stu[0].score);
while(j<20)
{
if(max<SUM(stu[j].score))
{
max=SUM(stu[j].score);
k=j;
}
j++;
}
printf("Date of the highest score students:\nnumber: %ld\nname: %s\nscore:%5.2f %5.2f %5.2f\naverage score:%5.2f\n",stu[k].num,stu[k].name,stu[k].score[0],stu[k].score[1],stu[k].score[2],max/3);
fclose(fp);
}

其中"data.txt"如下:
200501 zhao 78 79 79
200502 qian 79 89 89
200503 sun 87 89 90
200504 li 90 97 86
200505 zhou 78 76 89
200506 wu 90 87 76
200507 zheng 78 89 89
200508 wang 89 87 88
200509 liu 88 87 76
200510 ji 89 88 87
200511 xu 89 89 89
200512 xue 87 76 76
200513 wei 89 80 90
200514 zhu 95 91 87
200515 zhuo 87 89 81
200516 zhang 76 78 71
200517 sheng 87 85 79
200518 shao 70 90 99
200519 feng 87 85 78
200520 yu 87 81 82

初学C语言,不知道是什么原因,望高手赐教!
初步怀疑是sizeof(struct student)所计算出的字节数有误,请问float score[3];占多少字节?

首先是最简单的读写一个字符的函数fputc和fgetc,在这个基础上又出现了putw和getw、fgets和fputs,此外还说过格式化读写函数fprintf和fscanf函数。

  从原理上来说,只要fputc和fgetc函数基本就可以完成数据的读写操作了,但是在实际的使用中会遇到诸多不便,因此上面那一大堆函数就冒出来了(其实也不多)。上面函数中最方便的就是格式化读写函数fprintf和fscanf了,因为可以一行行的进行读取,但是有个问题就是这两位老人家动作比较慢,fprintf在写文件的时候要把二进制形式表示的数据转换为ASCII码形式,fscanf在读文件的时候又要将ASCII码转换为二进制的形式。

  好不容易出来个好用的函数,竟然是个慢性子,聪明的你现在也许就在想了:那能不能不转换,直接读写二进制的数据呢?答案就是fread和fwrite,在需要频繁进行数据读写的时候,使用这两个函数将大大提升效率。

  fread和fwrite函数的定义

  fread(pBuffer,size,count,pFile);

  fwrite(pBuffer,size,count,pFile);

  要读写一个数据块的话,无论是读还是写,都需要指定一个起始地址,读的话从这个起始地址读,写的话从这个起始地址写,上面函数定义中的第一个参数pBuffer就是用于指定这个起始地址,size读写的字节数,count则指定读写多少个size大小的数据,pFile是文件结构指针。

  fread和fwrite函数使用示例

  说到数据块我们自然会想到结构体,如果一个文件中保存的是一个个结构体信息,那每一个结构体信息就可以看做一个数据块了。这里直接用前面文章中我们一直使用的学生成绩信息的结构体:

  C语言: 知蚁博客

  struct student

  {

  int nID; //学号

  char chName[20]; //姓名

  float fScores[3]; //3门课的成绩

  };

  实例程序有点小复杂的,首先我们自己新建一个txt文件,也就是ASCII文件啦,然后写上一些数据,如下:

  1 zhangsan 78.0 79.0 80.0

  2 lisi 79.0 77.0 78.0

  3 wangwu 90.0 97.0 78.0

  4 zhaokai 56.0 57.0 58.0

  我们先用ASCII方式打开这个文件,通过fscanf函数读取里面的数据,然后通过fwrite写入到新的二进制格式的文件中,这样我们就得到了一个保存上面信息的二进制格式的文件了,下面就是通过fread函数进行数据的读取了。(记住:fread和fwrite一般用于二进制文件的输入输出,ASCII文件还是不要考虑了)。

  C++语言: 知蚁博客

  #include "stdio.h"

  struct student

  {

  int nID; //学号

  char chName[20]; //姓名

  float fScores[3]; //3门课的成绩

  };

  void main()

  {

  FILE *pRead,*pWrite;

  struct student tStu[4];

  struct student *ptStu = NULL;

  int nCount = 0;

  //ASCII方式打开文件 用于读入

  pRead=fopen("stu_scores.txt","r");

  if(NULL == pRead)

  {

  return;

  }

  //二进制文件打开文件 用于写入

  pWrite=fopen("stu_scores_bin.txt","wb");

  if(NULL == pWrite)

  {

  fclose(pRead);

  return;

  }

  //fscanf读取数据,fwrite写入数据

  ptStu = tStu;

  while(!feof(pRead))

  {

  fscanf(pRead,"%d %s %f %f %f\n",&ptStu->nID,ptStu->chName,&ptStu->fScores[0],&ptStu->fScores[1],&ptStu->fScores[2]);

  fwrite(ptStu,sizeof(struct student),1,pWrite);

  printf("%d %s %.1f %.1f %.1f\n",ptStu->nID,ptStu->chName,ptStu->fScores[0],ptStu->fScores[1],ptStu->fScores[2]);

  ptStu++;

  }

  fclose(pRead);

  fclose(pWrite);

  memset(tStu,0×00,sizeof(tStu)); //清空数据

  //二进制文件打开文件 用于读取

  pRead=fopen("stu_scores_bin.txt","rb");

  if(NULL == pRead)

  {

  printf("open file stu_scores_bin.txt failed");

  return;

  }

  //下面有两种fread的读数据方式,将下面的1换成0,则使用第二种方式

  #if 1

  //一条条的读取

  ptStu = tStu;

  nCount = fread(ptStu,sizeof(struct student),1,pRead);

  while(nCount>0)

  {

  printf("%d %s %.1f %.1f %.1f\n",ptStu->nID,ptStu->chName,ptStu->fScores[0],ptStu->fScores[1],ptStu->fScores[2]);

  ptStu++;

  nCount = fread(ptStu,sizeof(struct student),1,pRead);

  }

  #else

  //因为事先知道有4条信息,因此可以直接读取四条信息

  fread(tStu,sizeof(struct student),4,pRead);

  for(nCount=0; nCount<4; nCount++)

  {

  printf("%d %s %.1f %.1f %.1f\n",tStu[nCount].nID,tStu[nCount].chName,tStu[nCount].fScores[0],tStu[nCount].fScores[1],tStu[nCount].fScores[2]);

  }

  #endif

  fclose(pRead);

  }

  上面用fread读取的时候,我们既可以一条条的读取,也可以一次读入多条,这就是为什么参数中有size和count的原因
温馨提示:答案为网友推荐,仅供参考
第1个回答  推荐于2016-01-29
fread(&stu[i],sizeof(struct student),1,fp);
二进制读取,每次读取指定字节数
你的文件是文本方式的,读出来就错了

float score[3];//float类型是4个byte,score[3]就是12个byte

比如----------------------------------------------------
200501 zhao 78 79 79
结构中定义num是long型,占4个字节
这里200501是字符型,占6个字节

用fread()读,num就对应"2005"(存储为32 30 30 35)

可以用Ultra-edit查看文本文件的二进制本回答被提问者采纳
第2个回答  2015-09-21
本人照题目设计了个程序,想用fread读取数据,结果......
题目是:某班有30名学习,每名学生的数据包括学号、姓名、3门课的成绩,输入20名学生的数据,要求打印出3门课总平均成绩,以及总分最高的学生的数据(包括学号、姓名、3门课成绩,平均成绩)。
#include <stdio.h>
struct student
{ long num;
char name[10];
float score[3];
} stu[20];
float SUM(float *a)
{ int i;
float sum=0;
for(i=0;i<3;i++)
sum+=*(a+i);
return sum;
}
void main()
{
FILE *fp;
int i,j=0,k;
float sum=0,aver,max;
clrscr();
if((fp=fopen("data.txt","r"))==NULL)
{
printf("Can't open this file\n");exit(0);
}
for(i=0;i<20;i++)
{ fread(&stu[i],sizeof(struct student),1,fp);/* 使用读写数据块函数fread,结果运行得不到正确答案 */
/* 如果用后面这种格式化读写一点错都没有:
fscanf(fp,"%ld%s%f%f%f",&stu[i].num,stu[i].name,&stu[i].score[0],&stu[i].score[1],&stu[i].score[2]);*/
sum=sum+SUM(stu[i].score);
}
aver=sum/60;
printf("Average score is: %5.2f\n",aver);
max=SUM(stu[0].score);
while(j<20)
{
if(max<SUM(stu[j].score))
{
max=SUM(stu[j].score);
k=j;
}
j++;
}
printf("Date of the highest score students:\nnumber: %ld\nname: %s\nscore:%5.2f %5.2f %5.2f\naverage score:%5.2f\n",stu[k].num,stu[k].name,stu[k].score[0],stu[k].score[1],stu[k].score[2],max/3);
fclose(fp);
}

其中"data.txt"如下:
200501 zhao 78 79 79
200502 qian 79 89 89
200503 sun 87 89 90
200504 li 90 97 86
200505 zhou 78 76 89
200506 wu 90 87 76
200507 zheng 78 89 89
200508 wang 89 87 88
200509 liu 88 87 76
200510 ji 89 88 87
200511 xu 89 89 89
200512 xue 87 76 76
200513 wei 89 80 90
200514 zhu 95 91 87
200515 zhuo 87 89 81
200516 zhang 76 78 71
200517 sheng 87 85 79
200518 shao 70 90 99
200519 feng 87 85 78
200520 yu 87 81 82

初学C语言,不知道是什么原因,望高手赐教!
初步怀疑是sizeof(struct student)所计算出的字节数有误,请问float score[3];占多少字节?
相似回答