如何fread()结构? [英] How to fread() structs?
问题描述
struct book
{
unsigned short size_of_content;
未签名的空头价格;
unsigned char * content;
};
假设我有一个包含多个 book
每个都有不同的 size_of_content
, price
和 content
。我怎么能一次读一本 book
,并确定它是哪本书(例如检查价格)?
size_t nread2;
struct book * buff = malloc(sizeof(struct book));
while((nread2 = fread(buff,sizeof(struct book),1,infp))> 0)
{
printf(read a struct once \\\
);
}
到目前为止,我试图打印,每当我读一个结构。然而,当我尝试了5个结构的输入文件,它将打印15次...
谢谢。
struct book {
unsigned short size_of_content;
未签名的空头价格;
unsigned char * content;
};
第一项是 unsigned short
,没问题, sizeof(unsigned short)
可能会是2,就像2个字节一样。同样下一个。
但是那第三个。这是一个指针无符号字符
...您的磁盘记录不可能保存指针。你有一个字段 size_of_content
...我的猜测是磁盘记录包含 size_of_content
,那么 price
,然后是实际的内容。
我不会为你写完整的代码,但是在伪代码中,像这样:
$ b $ pre $ code fread(& size_of_content,sizeof(size_of_content),1,infp)
sanity-check价值size_of_content并处理任何错误
fread(& price,sizeof(price),1,infp)
理智检查价格的价值并处理任何错误
buff->内容= malloc(size_of_content)
检查malloc错误并处理任何错误
fread(buff-> content,size_of_content,1,infp)
如果你没有硬性规定内容的大小,只要假设它不能超过十亿或类似的东西那么,确保这个数字至少不是那么大!总是检查错误。
由于 struct
中只有两个字段,所以<$ code> fread()每一个。如果你有一个更复杂的结构,可能值得使用一个struct:
struct book_header {
unsigned短的size_of_content;
未签名的空头价格;
};
struct book {
struct book_header header;
unsigned char * content;
$ / code>
然后您可以使用 fread()
与 sizeof(book_header)
一起读取整个标题。在处理像wave音频文件这样的二进制文件时,我写了很多类似的代码。
不必担心这个问题,但如果这个文件是写在big-endian计算机上的,而且是在little-endian的计算机上阅读,反之亦然,那将会是一个问题。
http://en.wikipedia.org/wiki/Endianness
如果确实有这个问题,解决方法是标准化。选择一个(little-endian或big-endian),并使用C库函数来确保使用该endian-ness写入和读取数字。例如,在写入时, htonl()
库函数,读取时 ntohl()
。 b
$ b
http://linux.die.net/man/3 / htonl
但是正如我所说的,您可能不需要担心这一点。
struct book
{
unsigned short size_of_content;
unsigned short price;
unsigned char *content;
};
Assume I have file that contains multiple book
s, each has different size_of_content
, price
and content
. How can I read them one book
at a time and identify which book it is (check price, for example)?
size_t nread2;
struct book *buff = malloc(sizeof(struct book));
while( (nread2 = fread(buff, sizeof(struct book), 1, infp)) > 0 )
{
printf("read a struct once \n");
}
This is what I have so far. I tried to print whenever I read a struct. However, when I tried a input file with 5 structs, it will print 15 times...
Thanks.
Let's look at your struct
and think about how big it is.
struct book {
unsigned short size_of_content;
unsigned short price;
unsigned char *content;
};
The first item is an unsigned short
, no problem, sizeof(unsigned short)
probably will be 2, as in 2 bytes. Likewise the next one.
But that third one. That's a pointer to unsigned char
... your disk records are not likely saved pointers. You have a field size_of_content
... my guess is that the disk records contain the size_of_content
, then the price
, and then the actual content.
I won't write the complete code for you, but in pseudocode it goes something like this:
fread(&size_of_content, sizeof(size_of_content), 1, infp)
sanity-check the value of size_of_content and handle any error
fread(&price, sizeof(price), 1, infp)
sanity-check teh value of price and handle any error
buff->content = malloc(size_of_content)
check for error on malloc and handle any error
fread(buff->content, size_of_content, 1, infp)
If you don't have a hard-and-fast spec for how big the content can be, just assume it can't be more than a billion or something like that, and make sure the number at least isn't that huge! Always check for errors.
Since there are only two fields in the struct
, it's pretty easy to just fread()
each one. If you had a more complex structure, it might be worth it to use a struct:
struct book_header {
unsigned short size_of_content;
unsigned short price;
};
struct book {
struct book_header header;
unsigned char *content;
}
Then you can use fread()
with sizeof(book_header)
to read the whole header in one go. I've written a lot of code like this when working with binary files like wave audio files.
You probably don't need to worry about this, but it would be a problem if the file was written on a "big-endian" computer and read on a "little-endian" computer, or vice-versa.
http://en.wikipedia.org/wiki/Endianness
If you did have that problem, the solution is to standardize. Pick either one (little-endian or big-endian) and use a C library function to make sure the numbers are written and read using that endian-ness. For example, the htonl()
library function when writing, and ntohl()
when reading.
http://linux.die.net/man/3/htonl
But as I said, you probably don't need to worry about this.
这篇关于如何fread()结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!