【问题标题】:Fails to read data from binary file into array of structure pointers无法将二进制文件中的数据读入结构指针数组
【发布时间】:2016-10-30 12:36:51
【问题描述】:

以下代码将二进制数据写入/读取二进制文件。根据fread返回值,写入成功,甚至读取成功。但是最后两个或三个值总是垃圾,我已经通过增加减小数组大小来验证这一点。

如果我们在写入后立即读取文件,那么值就可以了。但是,如果我们在写入后关闭程序一次,然后以第一个动作作为读取再次运行程序,那么它会将最后几个值打印为垃圾。为什么会这样?

#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;
}

【问题讨论】:

    标签: c arrays file structure dynamic-memory-allocation


    【解决方案1】:

    在读/写代码时,假定所有结构都放置在以*e 开头的连续内存区域中。不是这种情况。

    代码没有定义struct 的数组,而是指向后者的指针。动态分配的structs 本身分散在整个内存中。

    就目前而言,代码通过写入/读取超出*e[0] 的范围来调用所有MAX > 1 的未定义行为。

    要在 fread()/fwrite() MAX 周围修复此循环,每个 struct 一次。

    (要指出这个问题,例如使用Valgrind 内存检查器显式运行编译代码。)


    作为与您的问题无关的旁注:read()write() 是一个拥有函数的坏名称,因为它们已被 POSIX C 标准使用。

    【讨论】:

      【解决方案2】:

      在读取函数中,你有

      if(fread(*e,sizeof(struct emp),MAX,f)==MAX)
      

      这会将 MAX 个元素读入数组 e。但是,e 不是连续数组。您正在使用

      单独分配 e
      e[i]=malloc(sizeof(struct emp));
      

      【讨论】:

        【解决方案3】:

        你不能做(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 {
            ...
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-04-28
          • 1970-01-01
          • 2019-05-14
          • 1970-01-01
          • 1970-01-01
          • 2021-11-14
          • 1970-01-01
          相关资源
          最近更新 更多