如何fread()结构?

Pig*_*Pig 4 c io file-io struct file

struct book
{
    unsigned short  size_of_content;
    unsigned short  price;
    unsigned char  *content;
};
Run Code Online (Sandbox Code Playgroud)

假设我有包含多个books的文件,每个文件都有不同的size_of_content,pricecontent.我怎样才能一次阅读一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 \n");
}
Run Code Online (Sandbox Code Playgroud)

这就是我到目前为止所拥有的.每当我读取结构时,我都会尝试打印.但是,当我尝试使用5个结构的输入文件时,它将打印15次...

谢谢.

ste*_*eha 7

让我们看看你的struct想法,并考虑它有多大.

struct book {
    unsigned short  size_of_content;
    unsigned short  price;
    unsigned char  *content;
};
Run Code Online (Sandbox Code Playgroud)

第一项是unsigned short,没问题,sizeof(unsigned short)可能是2,如2字节.同样是下一个.

但那第三个.这是一个指向unsigned char...你的磁盘记录不太可能保存指针.你有一个字段size_of_content...我的猜测是磁盘记录包含size_of_content,然后是price,然后是实际的内容.

我不会为你编写完整的代码,但在伪代码中它会是这样的:

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)
Run Code Online (Sandbox Code Playgroud)

如果你没有关于内容有多大的硬性规范,只要假设它不能超过十亿或类似的东西,并确保数量至少不是那么大!始终检查错误.

由于只有两个字段struct,因此fread()每个字段都很容易.如果你有一个更复杂的结构,使用结构可能是值得的:

struct book_header {
    unsigned short  size_of_content;
    unsigned short  price;
};

struct book {
    struct book_header header;
    unsigned char *content;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用fread()sizeof(book_header)读取整个头一气呵成.在处理波形音频文件等二进制文件时,我写了很多这样的代码.


您可能不需要担心这一点,但如果文件是在"big-endian"计算机上编写并在"little-endian"计算机上读取,反之亦然,则会出现问题.

http://en.wikipedia.org/wiki/Endianness

如果确实遇到了这个问题,那么解决方案就是标准化.选择一个(little-endian或big-endian)并使用C库函数来确保使用该endian-ness编写和读取数字.例如,htonl()库函数在写入时和ntohl()读取时.

http://linux.die.net/man/3/htonl

但正如我所说,你可能不需要担心这一点.