c语言 用fwrite输出数据后,想要用fread读取就不能! 第二个代码哪里出错了?

第一个#include<stdio.h>#defineSIZE2typedefstruct//typedef{charname[10];intnum;intage;cha... 第一个
#include<stdio.h>
#define SIZE 2

typedef struct //typedef
{
char name[10];
int num;
int age;
char addr[15];
}student;

student stu[SIZE];

void save()
{
FILE *fp;
int i;
if((fp = fopen("dat.txt","wb")) == NULL)
{
printf("无法打开此文件!\n");
return;
}
for(i = 0; i < SIZE; i++)
if(fwrite(&stu[i], sizeof(student), 1, fp) != 1)
{
printf("文件写入错误。!\n");
}
fclose(fp);
}

void main()
{
int i;
for(i = 0; i < SIZE; i++)
scanf("%s,%d,%d,%s",&stu[i].name,&stu[i].num,&stu[i].age,&stu[i].addr);
save();
}

第二个
#include<stdio.h>
#include<stdlib.h>
#define SIZE 2

typedef struct
{
char name[10];
int num;
int age;
char addr[15];
}student;

student stu[SIZE];
int i;

void load()
{
FILE *fp;

if(!(fp = fopen("dat.txt", "rb")))//打开文件
{
printf("Cannot open the file!");
return;
}

for(i = 0; i < SIZE; i++)
{
fread(&stu[i], sizeof(student),1 , fp);//读取数据块!
}
fclose(fp);
}

void main()
{

for(i = 0; i < SIZE; i++)
{
printf("%s%d%d%s", stu[i].name, stu[i].num, stu[i].age, stu[i].addr );
}
}
展开
 我来答
kaladijia
2015-08-09 · TA获得超过4326个赞
知道小有建树答主
回答量:1737
采纳率:25%
帮助的人:520万
展开全部
读文件程序
void main()
{
load(); 少了这句
for(i = 0; i < SIZE; i++)
{
printf("%s%d%d%s", stu[i].name, stu[i].num, stu[i].age, stu[i].addr );
}
}

如果作为了解C语言编程原理,你完全可以这样写。但是作为正规文件数据读写程序来说。
这些保存数据的方式是错误的。而且是非常危险的。

写文件程序和读文件程序在同一台电脑中不会看出问题。
一旦,一个程序在32位系统中,另一个程序在64位系统中,就可能出现问题。
或者一个计算机的处理器使用的大端字节优先序,另一个计算机的处理器使用小端字节优先序。或者,这两个程序使用不同版本的编译器编译。都会出错的。

这是因为,你将结构体直接以二进制序列方式保存到文件中,也就是说,你将结构体在内存的布局结构直接暴露在文件中。
因为,你在同一个编译器中编译两个程序,并且在同一台计算机上或者相同类型处理器的计算机,是看不出来问题。

不同编译器,对于同一个结构体内部的布局结构是不同的。即使同一个编译器自身设置不同,它也会生成不同布局结构的结构体。

32位程序的编译器与64位程序的编译器生成的结构体布局结构是不同的,因为默认对齐方式不同。

正确的方法应该,将结构体中各个成员,作为单个个体依次分别保存。
并且将各个成员的全部转换为文字型,char 型本身就是文字型所以无须转换。int 等需要转换成相应的字符串数据,然后输出。

并且同一变量中各个字段之间要加特殊的字符作为分割。例如Tab键。
而各条记录之间也需要加特殊的字符作为分割。例如回车键。
这样在保存成TXT文件时,你就可以看到能阅读的数据记录了。否则与int等数字型部分就可能是一串乱码。

在读取文件时,需要转移那两个特殊字符。
可以采用这样的方法,连续读取字符,直到遇到特殊字符,Tab和回车。
之前的多个字符作为一个整体,如果它对应的结构体的成员变量的数据类型是字符型(包括字符串),则验证它是否超过字符型的限制(比如是否超过规定字符串的长度)。如果对应的数值型,则需要专门的函数转换成相应的数值。比如文字型“31”需要转换成数字型“31”。

遇到回车,则表示之前的内容为一条记录(直到上一个回车),则后续将保存到新的记录中。
当然为了保证读取程序的建壮性,你需要能够识别出错误,记录的能力。
比如你的结构体包含四个成员,而某条数据记录只有三个字段,或者某条记录有五个字段。
结构体的成员明明是数字类型,而文件中对应记录的字段却无法正确的转换成数字类型。
同一条记录的各个字段之间有多个Tab,或各条记录之间有多个回车等等。

而读写函数用读取文字型的函数

写函数
int fprintf(FILE *stream, char *format, );
int fputs(char *string, FILE *steam);
int fputc(int ch, FILE *steam);
读函数

int fscanf(FILE *stream, char *format, );
char fgets(char *string, int n, FILE *steam);
int fgetc(FILE *steam);
匿名用户
2015-08-08
展开全部
stu.name类似于指针。
追问
?
追答
意思就是你存的是一个地址,而不是数据。读取后,指向的内存不一定有需要的数据。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式