【问题标题】:Reading and printing the last number of integers from a binary file to the console [closed]从二进制文件读取最后一个整数并将其打印到控制台[关闭]
【发布时间】:2022-01-31 22:15:49
【问题描述】:
int read_last_ints(const char *file_name, int num_ints) 
{
    FILE *fp = fopen(file_name, "r");
    if (fp == NULL)
    {
        return 1;
    }
    int integers;
    long int size;
    size_t nread;

    fseek(fp, 0, SEEK_END);
    size = ftell(fp);
    rewind(fp);
    size = size - num_ints;
    fseek(fp, size, SEEK_SET);
    
    while ((nread = fread(&integers, 1, sizeof(int), fp)) > 0)
    {
        printf("%d\n", integers);
    }

    fclose(fp);
    return 0;
}

我正在尝试创建一个从二进制文件中读取最后一个整数的函数,但是我的代码没有按预期工作。当我尝试测试我的代码时,它会产生没有意义的随机数。如果有人有任何建议,请分享。谢谢。

【问题讨论】:

  • 请不要将代码作为图像发布 - reasoning。将其作为格式化文本复制到问题中。并且请比“不起作用”更好地描述问题。给出准确的输入、预期结果和实际结果。还要描述你做了什么调试以及你发现了什么。
  • fseek()ftell() 使用以字节为单位的位置。你需要除以sizeof(int)
  • 您可能还需要使用"rb" 而不是"r" 来读取二进制文件。在 Windows 上使用"rb" 是至关重要的;它在类 Unix 系统上是无害的(因为 C 标准要求支持 "rb",即使在 Unix 上不是必需的)。
  • 你需要将size = size - num_ints;改为size = size - num_ints * sizeof(int);(乘以sizeof(int)而不是除以它。
  • @JonathanLeffler 它确实有效。非常感谢。这是我第一次使用 fseek 函数,它的工作方式很奇怪,对我来说几乎没有任何意义。

标签: c io


【解决方案1】:

您需要从文件末尾向后定位 num_ints 整数的大小。

对您的代码的最小更改是:

int read_last_ints(const char *file_name, int num_ints) 
{
    FILE *fp = fopen(file_name, "r");
    if (fp == NULL)
    {
        return 1;
    }
    int integers;
    long int size;
    size_t nread;

    fseek(fp, 0, SEEK_END);
    size = ftell(fp);
    rewind(fp);
    size = size - sizeof(int) * num_ints;  /* MNC — minimum necessary change */
    fseek(fp, size, SEEK_SET);
    
    while ((nread = fread(&integers, 1, sizeof(int), fp)) > 0)
    {
        printf("%d\n", integers);
    }

    fclose(fp);
    return 0;
}

但是,您可以更有效地使用SEEK_END 选项。您可能还应该使用"rb" 而不是"r" 来读取二进制文件。在 Windows 上使用"rb" 是至关重要的;它在类 Unix 系统上是无害的(因为 C 标准要求支持 "rb",即使在 Unix 上没有必要)。此代码还将变量 integers 重命名为单数 integer

int read_last_ints(const char *file_name, int num_ints) 
{
    FILE *fp = fopen(file_name, "r");
    if (fp == NULL)
    {
        return 1;
    }
    int integer;
    size_t nread;

    fseek(fp, -(long)(num_ints * sizeof(int)), SEEK_END);
    
    while ((nread = fread(&integer, 1, sizeof(int), fp)) > 0)
    {
        printf("%d\n", integer);
    }

    fclose(fp);
    return 0;
}

这会保存对fseek()ftell()rewind() 的调用。 rewind() 总是多余的,但您不需要知道文件的实际大小。 fseek() 调用只是寻找文件结尾之前的相关字节数。只有当文件不够大,无法容纳那么多整数时,您才会遇到问题(它会尽其所能,从头开始并尽可能多地读取)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-22
    相关资源
    最近更新 更多