如何将二进制文件读取到 C 中的结构
How to read a binary file to a structure in C
我有一个名为 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;
您必须传递 指针 才能让 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 */
}
如 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 ...
Please pay attention to the fread()'s definition, The first argumnet need to be one pointer.; And another litter mistake is we need to make use of "->" to get the element in printf() Function.
Below are my modification:
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);
}
这段代码有几个问题。其中一些会阻止编译,而另一些可能会导致不稳定的行为。由于不稳定的行为是您可能不会注意到的,我将首先介绍它。
在尝试使用它之前,您应该始终检查 malloc
的 return 值。 例如:
Product *obuff = malloc(sizeof *obuff);
if (obuff == NULL) {
/* obuff can't be used because allocation failed */
return;
}
在相关说明中,正如 MikeCAT 所建议的那样,当您完成 malloc
',realloc
' 或 calloc
'...
在另一个相关说明中,您也不应使用值 obuff->code
、name
、quality
和 price
,除非 return 值为 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);
这将编译,并向您说明 do 需要此处的 & 符号,但是话虽如此 short int
和 double
可能在不同的系统上有不同的表示。 您需要通过 序列化 这些字段在文件中形成一致的表示。序列化是一个冗长的主题,更适合作为软件设计书籍的一个章节,因此为了简洁起见,我将继续讨论,除非在此提出有关该主题的进一步具体问题。
#pragma pack(2)
这是不可移植的,在您提供的代码中没有真正需要它。
printf("%s %s %d %.2f\n", obuff.code, obuff.name, obuff.quantity, obuff.price);
预计%s
对应的是一个指向字符串的指针;字符串是在第一个'[=34=]'
字符处结束的字符序列.但是,您的代码没有明确分配任何 '[=34=]'
字符,因此我们不能保证 obuff.code
和 obuff.name
是 字符串。如果不是,则行为未定义(或 不稳定 ,正如我喜欢描述的那样)。也许您打算分别使用 %15s
和 %50s
来表示它们 可能 是字符串,但如果不是,则有最大长度?
这也是你编译错误的来源。请注意,在之前的代码片段中,您如何引用 obuff->code
、obuff->name
等 ,而在此片段中,您如何引用 obuff.code
、等? .
运算符访问结构的字段,而 ->
运算符访问指向结构的字段...也许您打算在这里使用 ->
运算符?
我有一个名为 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;
您必须传递 指针 才能让 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 */
}
如 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 ...
Please pay attention to the fread()'s definition, The first argumnet need to be one pointer.; And another litter mistake is we need to make use of "->" to get the element in printf() Function.
Below are my modification:
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);
}
这段代码有几个问题。其中一些会阻止编译,而另一些可能会导致不稳定的行为。由于不稳定的行为是您可能不会注意到的,我将首先介绍它。
在尝试使用它之前,您应该始终检查 malloc
的 return 值。 例如:
Product *obuff = malloc(sizeof *obuff);
if (obuff == NULL) {
/* obuff can't be used because allocation failed */
return;
}
在相关说明中,正如 MikeCAT 所建议的那样,当您完成 malloc
',realloc
' 或 calloc
'...
在另一个相关说明中,您也不应使用值 obuff->code
、name
、quality
和 price
,除非 return 值为 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);
这将编译,并向您说明 do 需要此处的 & 符号,但是话虽如此 short int
和 double
可能在不同的系统上有不同的表示。 您需要通过 序列化 这些字段在文件中形成一致的表示。序列化是一个冗长的主题,更适合作为软件设计书籍的一个章节,因此为了简洁起见,我将继续讨论,除非在此提出有关该主题的进一步具体问题。
#pragma pack(2)
这是不可移植的,在您提供的代码中没有真正需要它。
printf("%s %s %d %.2f\n", obuff.code, obuff.name, obuff.quantity, obuff.price);
预计%s
对应的是一个指向字符串的指针;字符串是在第一个'[=34=]'
字符处结束的字符序列.但是,您的代码没有明确分配任何 '[=34=]'
字符,因此我们不能保证 obuff.code
和 obuff.name
是 字符串。如果不是,则行为未定义(或 不稳定 ,正如我喜欢描述的那样)。也许您打算分别使用 %15s
和 %50s
来表示它们 可能 是字符串,但如果不是,则有最大长度?
这也是你编译错误的来源。请注意,在之前的代码片段中,您如何引用 obuff->code
、obuff->name
等 ,而在此片段中,您如何引用 obuff.code
、等? .
运算符访问结构的字段,而 ->
运算符访问指向结构的字段...也许您打算在这里使用 ->
运算符?