无法将二进制文件中的数据读入结构指针数组
Fails to read data from binary file into array of structure pointers
以下代码writes/reads二进制数据to/from二进制文件。按fread
return值写入成功,连读取也成功。但是最后两三个值总是垃圾,我已经通过增加递减数组大小验证了这一点。
如果我们在写入后立即读取文件,那么值就没问题了。但是,如果我们在写入后关闭程序一次,然后 运行 再次执行第一个操作为读取的程序,那么它会将最后几个值打印为垃圾。为什么会这样?
#include<stdio.h>
#include<stdlib.h>
#define MAX 7
void write(FILE *);
void read(FILE *);
int flag=0;
struct emp
{
char name[20];
int id;
float salary;
}*e[MAX];
void write(FILE *f)
{
int i=0,check=0;
flag=1;
for(i=0;i<MAX;i++)
{
e[i]=malloc(sizeof(struct emp));
if(e[i])
{
printf("\nEnter Name id salary\n");
scanf("%s %d %f",e[i]->name,&e[i]->id,&e[i]->salary);
//printf("\n----------%s %d %f\n",e[i]->name,e[i]->id,e[i]->salary);
//fflush(stdin);
}
else
{
printf("\nError allocating Memory\n");
exit(0);
}
}
check= fwrite(*e,sizeof(struct emp),MAX,f);
if(check!=MAX)
{
printf("\nerror writing to file\n");
}
else
{
printf("\nwritten successfully to file\n");
}
}
void read(FILE *f)
{
int i=0;
if(flag==0) //reading file right after running program
{
for(i=0;i<MAX;i++)
{
e[i]=malloc(sizeof(struct emp));
if(e[i]==NULL)
{
printf("\nError Allocating Memory for read\n");
exit(0);
}
}
}
if(fread(*e,sizeof(struct emp),MAX,f)==MAX)
{
for(i=0;i<MAX;i++)
{
printf("\n%s %d %f\n",e[i]->name,e[i]->id,e[i]->salary);
}
}
else
{
printf("\nEither reading error or partial content read\n");
}
}
int main()
{
FILE *fp=NULL;
char a='a';
do
{
printf("\nEnter w to write, r to read and e to exit\n");
//scanf("%c",&a);
a=getche();
switch(a)
{
case 'w':
fp=fopen("binary_ptr.exe","wb");
if(fp==NULL)
{
printf("\nError opening file to write\n");
exit(0);
}
write(fp);
fclose(fp);
break;
case 'r':
fp=fopen("binary_ptr.exe","rb");
if(fp==NULL)
{
printf("\nError opening file to read\n");
exit(0);
}
read(fp);
fclose(fp);
break;
case 'e':
exit(0);
break;
default:
printf("\nInvalid input\n");
break;
}
}
while(1);
return 0;
}
在 reading/writing 上,所示代码假定所有结构都放置在以 *e
开头的连续内存区域中。不是这种情况。
代码没有定义 struct
的数组,而是指向后者的指针。动态分配的 struct
本身分散在内存中。
就目前而言,代码为所有 MAX
> 1
调用 writing/reading 超出 *e[0]
范围的未定义行为。
修复此循环 fread()
/fwrite()
MAX
次,每次 struct
次。
(要明确指出这个问题 运行 使用 Valgrind 内存检查器编译的代码,例如。)
作为与您的问题无关的附注:read()
和 write()
是拥有函数的错误名称,因为 POSIX C 标准已经使用了这些名称。
在读取函数中,你有
if(fread(*e,sizeof(struct emp),MAX,f)==MAX)
这会将 MAX 个元素读入数组 e
。但是,e
不是连续数组。您将 e
与
分开分配
e[i]=malloc(sizeof(struct emp));
你不能做 (fread(*e, sizeof(struct emp), MAX, f)
因为你已经为你的 emp 结构分配了非连续的内存,正如正确指出的那样,你有一个指向 emp
结构的指针数组,而不是一个数组emp
个结构。您需要分别阅读每个 emp
:
for (int i = 0; i < MAX; ++i){
if (fread(e[i], sizeof(struct emp), 1, f) == sizeof(struct emp)){
printf("\n%s %d %f\n", e[i]->name, e[i]->id, e[i]->salary);
} else {
...
}
}
同样,当你将emp
数据写入文件时,你也需要单独进行
for (int i = 0; i < MAX; ++i){
check = fwrite(e[i], sizeof(struct emp), 1, f);
if (check != sizeof(struct emp)){
...
} else {
...
}
}
以下代码writes/reads二进制数据to/from二进制文件。按fread
return值写入成功,连读取也成功。但是最后两三个值总是垃圾,我已经通过增加递减数组大小验证了这一点。
如果我们在写入后立即读取文件,那么值就没问题了。但是,如果我们在写入后关闭程序一次,然后 运行 再次执行第一个操作为读取的程序,那么它会将最后几个值打印为垃圾。为什么会这样?
#include<stdio.h>
#include<stdlib.h>
#define MAX 7
void write(FILE *);
void read(FILE *);
int flag=0;
struct emp
{
char name[20];
int id;
float salary;
}*e[MAX];
void write(FILE *f)
{
int i=0,check=0;
flag=1;
for(i=0;i<MAX;i++)
{
e[i]=malloc(sizeof(struct emp));
if(e[i])
{
printf("\nEnter Name id salary\n");
scanf("%s %d %f",e[i]->name,&e[i]->id,&e[i]->salary);
//printf("\n----------%s %d %f\n",e[i]->name,e[i]->id,e[i]->salary);
//fflush(stdin);
}
else
{
printf("\nError allocating Memory\n");
exit(0);
}
}
check= fwrite(*e,sizeof(struct emp),MAX,f);
if(check!=MAX)
{
printf("\nerror writing to file\n");
}
else
{
printf("\nwritten successfully to file\n");
}
}
void read(FILE *f)
{
int i=0;
if(flag==0) //reading file right after running program
{
for(i=0;i<MAX;i++)
{
e[i]=malloc(sizeof(struct emp));
if(e[i]==NULL)
{
printf("\nError Allocating Memory for read\n");
exit(0);
}
}
}
if(fread(*e,sizeof(struct emp),MAX,f)==MAX)
{
for(i=0;i<MAX;i++)
{
printf("\n%s %d %f\n",e[i]->name,e[i]->id,e[i]->salary);
}
}
else
{
printf("\nEither reading error or partial content read\n");
}
}
int main()
{
FILE *fp=NULL;
char a='a';
do
{
printf("\nEnter w to write, r to read and e to exit\n");
//scanf("%c",&a);
a=getche();
switch(a)
{
case 'w':
fp=fopen("binary_ptr.exe","wb");
if(fp==NULL)
{
printf("\nError opening file to write\n");
exit(0);
}
write(fp);
fclose(fp);
break;
case 'r':
fp=fopen("binary_ptr.exe","rb");
if(fp==NULL)
{
printf("\nError opening file to read\n");
exit(0);
}
read(fp);
fclose(fp);
break;
case 'e':
exit(0);
break;
default:
printf("\nInvalid input\n");
break;
}
}
while(1);
return 0;
}
在 reading/writing 上,所示代码假定所有结构都放置在以 *e
开头的连续内存区域中。不是这种情况。
代码没有定义 struct
的数组,而是指向后者的指针。动态分配的 struct
本身分散在内存中。
就目前而言,代码为所有 MAX
> 1
调用 writing/reading 超出 *e[0]
范围的未定义行为。
修复此循环 fread()
/fwrite()
MAX
次,每次 struct
次。
(要明确指出这个问题 运行 使用 Valgrind 内存检查器编译的代码,例如。)
作为与您的问题无关的附注:read()
和 write()
是拥有函数的错误名称,因为 POSIX C 标准已经使用了这些名称。
在读取函数中,你有
if(fread(*e,sizeof(struct emp),MAX,f)==MAX)
这会将 MAX 个元素读入数组 e
。但是,e
不是连续数组。您将 e
与
e[i]=malloc(sizeof(struct emp));
你不能做 (fread(*e, sizeof(struct emp), MAX, f)
因为你已经为你的 emp 结构分配了非连续的内存,正如正确指出的那样,你有一个指向 emp
结构的指针数组,而不是一个数组emp
个结构。您需要分别阅读每个 emp
:
for (int i = 0; i < MAX; ++i){
if (fread(e[i], sizeof(struct emp), 1, f) == sizeof(struct emp)){
printf("\n%s %d %f\n", e[i]->name, e[i]->id, e[i]->salary);
} else {
...
}
}
同样,当你将emp
数据写入文件时,你也需要单独进行
for (int i = 0; i < MAX; ++i){
check = fwrite(e[i], sizeof(struct emp), 1, f);
if (check != sizeof(struct emp)){
...
} else {
...
}
}