如何将二进制文件读取到C中的结构

时间:2016-03-15 03:26:07

标签: c struct binaryfiles

我有一个名为 product 的结构,我试图从二进制文件中读取以填充此函数:

void reading(FILE *fp){

  Product *obuff = malloc(sizeof(Product));
  fread(obuff->code, sizeof(obuff->code), 1, fp);
  fread(obuff->name, sizeof(obuff->name), 1, fp);
  fread(obuff->quantity, sizeof(obuff->quantity), 1, fp);
  fread(obuff->price, sizeof(obuff->price), 1, fp);   

  printf("%s %s %d %.2f\n", obuff.code, obuff.name, obuff.quantity, obuff.price);
}

当我尝试编译时,我得到错误,说我因为错误的数据类型而无法传递参数。有没有办法从二进制文件读取结构,或者我在这里做错了什么?

结构:

#pragma pack(2)
struct product {
   char code[15];
   char name[50];
   short int quantity;
   double price;
};
#pragma pack()

typedef struct product Product;

4 个答案:

答案 0 :(得分:2)

您必须传递指针以使fread()读取数据。

void reading(FILE *fp){

  Product *obuff = malloc(sizeof(Product));
  fread(&obuff->code, sizeof(obuff->code), 1, fp);
  fread(&obuff->name, sizeof(obuff->name), 1, fp);
  fread(&obuff->quantity, sizeof(obuff->quantity), 1, fp);
  fread(&obuff->price, sizeof(obuff->price), 1, fp);

  printf("%s %s %d %.2f\n", obuff->code, obuff->name, obuff->quantity, obuff->price);
  free(obuff); /* free whatever you allocated after finished using them */
}

答案 1 :(得分:1)

此代码存在一些问题。其中一些会阻止编译,而其他一些可能会导致不稳定的行为。由于不稳定的行为是您可能不会注意到的,我将首先介绍它。

在尝试使用之前,您应该始终检查malloc的返回值。例如:

Product *obuff = malloc(sizeof *obuff);
if (obuff == NULL) {
    /* obuff can't be used because allocation failed */
    return;
}

在相关的说明中,正如MikeCAT建议的那样,当您完成任何事情free时,可以使用malloc 来避免内存泄漏' d,realloc' d或calloc' d ...

在其他相关说明中,除非{{1}的返回值,否则您也不应使用值obuff->codenamequalityprice表示成功。

fread

这会编译,但你不需要&符号(fread(&obuff->code, sizeof(obuff->code), 1, fp); fread(&obuff->name, sizeof(obuff->name), 1, fp); ,实际上不应该在这里使用它们。表达式&obuff->code都指向同一位置(因为&obuff->code是一个数组),但它们指向的对象类型不同; obuff->code指向数组的第一个字节,而obuff->code指向整个数组。

&obuff->code

这将编译,并澄清你需要这里的&符号,但是说fread(&obuff->quantity, sizeof(obuff->quantity), 1, fp); fread(&obuff->price, sizeof(obuff->price), 1, fp); short int可能在不同的系统上有不同的表示。 您需要通过序列化这些字段在文件中形成一致的表示形式。序列化是一个冗长的主题,更适合软件设计手册中的一章,因此为了简洁起见,我将继续前进,除非在此提出有关此主题的更多具体问题。

double

这是不可移植的,在您提供的代码中并不需要它。

#pragma pack(2)

预期printf("%s %s %d %.2f\n", obuff.code, obuff.name, obuff.quantity, obuff.price); 对应于指向字符串的指针; 字符串是以第一个%s字符结尾的字符序列。但是,您的代码并未明确指定任何'\0'字符,因此我们无法保证'\0'obuff.code 字符串。如果他们不是,则行为未定义(或不稳定,正如我想描述的那样)。也许您打算分别使用obuff.name%15s来表示他们可能是字符串,但如果他们不是,那就是最大长度?< / p>

这也是编译错误的来源。请注意您之前引用的代码片段%50s obuff->code如何在此片段中引用obuff->name等 STRONG>? obuff.code运算符访问结构的字段,而.运算符访问指向结构的字段...也许您打算在这里使用->运算符? / p>

答案 2 :(得分:0)

http://www.tutorialspoint.com/c_standard_library/c_function_fread.htm引用,你必须将指针传递给fread:

 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

你的第一个fread参数不是指针;

 fread(obuff->code ...

答案 3 :(得分:0)

  

请注意fread()的定义,第一个argumnet需要是一个指针。另一个垃圾错误是我们需要使用“ - &gt;”获取printf()函数中的元素。

     

以下是我的修改:

void reading(FILE *fp){

  Product *obuff = malloc(sizeof(Product));
  fread(obuff->code, sizeof(obuff->code), 1, fp);
  fread(obuff->name, sizeof(obuff->name), 1, fp);
  fread(&obuff->quantity, sizeof(obuff->quantity), 1, fp);
  fread(&obuff->price, sizeof(obuff->price), 1, fp);   

  printf("%s %s %d %.2f\n", obuff->code, obuff->name, obuff->quantity, obuff->price);
}