fread() c 中的结构

2024-02-03

对于我的作业,我需要使用 fread/fwrite。我写

#include <stdio.h>
#include <string.h>

struct rec{
    int account;
    char name[100];
    double balance;
};

int main()
{
    struct rec rec1;
    int c;

    FILE *fptr;
    fptr = fopen("clients.txt", "r");

    if (fptr == NULL)
        printf("File could not be opened, exiting program.\n");
    else
    {
        printf("%-10s%-13s%s\n", "Account", "Name", "Balance");
        while (!feof(fptr))
        {
            //fscanf(fptr, "%d%s%lf", &rec.account, rec.name, &rec.balance);
            fread(&rec1, sizeof(rec1),1, fptr);
            printf("%d %s %f\n", rec1.account, rec1.name, rec1.balance);
        }
        fclose(fptr);
    }
    return 0;
}

客户.txt 文件



100 Jones 564.90
200 Rita 54.23
300 Richard -45.00
  

output



Account   Name         Balance
540028977 Jones 564.90
200 Rita 54.23
300 Richard -45.00╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠ü☻§9x°é -92559631349317831000000000000000000000000000000000000000000000.000000

Press any key to continue . . .
  

我可以使用 fscanf (我已经注释掉)来做到这一点,但我需要使用 fread/fwrite。

  1. 为什么琼斯的帐户以大量数字开头?
  2. 为什么之后有垃圾? feof 不应该阻止这一切吗?
  3. 使用这种方法有什么缺点吗?或者fscanf方法?

我该如何解决这些问题? 提前谢谢了


正如评论所说,fread读取文件中的字节而不进行任何解释。文件clients.txt由 50 个字符组成,第一行 16 个,第二行 14 个,第三行 18 个,再加上两个换行符。 (您的clients.txt在第三行之后不包含换行符,您很快就会看到。)换行符是一个字节\n在 UNIX 或 Mac OS X 机器上,但是(可能)两个字节\r\n在 Windows 计算机上 - 因此为 50 或 51 个字符。以下是十六进制的 ASCII 字节序列:

3130 3020 4a6f 6e65 7320 3536 342e 3930     100 Jones 564.90
0a32 3030 2052 6974 6120 3534 2e32 330a     \n200 Rita 54.23\n
3330 3020 5269 6368 6172 6420 2d34 352e     300 Richard -45.
3030                                        00

Your fread语句将这些字节直接复制到您的文件中,无需任何解释rec1数据结构。该结构开始于int account;,它表示将前四个字节解释为int。正如其中一条评论指出的,您正在小端机器(很可能是英特尔机器)上运行程序,因此最低有效字节是第一个,最高有效字节是第四个。因此,你的fread表示解释四个 ASCII 字符的序列"100 "作为四字节整数0x20303031,以十进制表示,等于540028977。你的结构的下一个成员是char name[100];,这意味着接下来的 100 个字节的数据rec1将是name。但是fread被告知要读书sizeof(rec1)=112字节(4 字节帐户,100 字节名称,8 字节余额)。由于您的文件只有 50(或 52)个字符,fread将只能填充那么多字节rec1。返回值fread,如果您没有丢弃它,则会告诉您读取未达到您请求的字节数而停止。自从你击中 EOF 以来,feof调用在第一次传递后中断循环,一次性消耗了整个文件。

您的所有输出都是由第一个也是唯一一个调用生成的fprintf。编号540028977及以下空间由"%d "rec1.account争论。接下来的部分只是部分确定的,你很幸运:"%s"说明符和相应的rec1.name参数将以 ASCII 形式打印接下来的字符,直到\0字节被发现。因此,输出将以50-4 (or 52-4)文件的剩余字符(包括两个换行符)并可能永远继续,因为没有\0文件(或任何文本文件)中的字节,这意味着在打印文件的最后一个字符后,您看到的是自动变量中发生的任何垃圾rec1当你的程序开始时。 (这种无意的输出类似于 OpenSSL 中著名的 heartbleed bug。)你很幸运,垃圾包括\0仅几十个字符之后的字节。注意printf无从得知rec1.name被声明为只是一个 100 字节数组——它只得到了指向开头的指针name——你有责任保证这一点rec1.name包含终止\0字节,而你从来没有这样做过。

我们可以多说一点。号码-9.2559631349317831e61(这在"%f"格式)的值是rec1.balance。 8 个字节doubleIEEE 754 机器(如英特尔和所有现代计算机)上的值以十六进制表示0xcccccccccccccccc。六十四奇特符号出现在"%s"输出对应于rec1.name,而 100 个字符中只剩下 100-46 = 54 个字符,所以你的"%s"输出已结束rec1.name,并包括rec1.balance讨价还价,我们了解到您的终端程序解释了非 ASCII 字符0xcc as 。有很多方法可以解释大于 127 (0x7f) 的字节;在 latin-1 中它会是&Igrave;例如。图形字符是古代 MS-DOS 字符集中 0xcc (204) 字节的表示,Windows 代码页 437。您不仅在 Intel 机器上运行,它还是 Windows 机器(当然最有可能的可能性是开始) 。

这回答了你的前两个问题。我不确定我是否理解你的第三个问题。我希望“缺点”是显而易见的。

至于如何修复它,没有相当简单的方法来读取和解释文本文件fread。为此,您需要复制其中的大部分代码libc fscanf功能。唯一明智的方法是首先使用fwrite创建一个二进制文件;然后fread会很自然地读回来。所以必须有两个程序——一个用于编写二进制文件clients.bin文件,然后再读回它。当然,这并不能解决第一个程序的数据首先应该来自哪里的问题。它可能来自阅读clients.txt using fscanf。或者它可以包含在源代码中fwrite程序,例如通过初始化数组struct rec像这样:

struct rec recs[] = {{100, "Jones", 564.90},
                     {200, "Rita", 54.23},
                     {300, "Richard", -45.00}};

或者它可能来自读取 MySQL 数据库,或者......它不太可能起源于一个二进制文件(很容易)可读fread.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

fread() c 中的结构 的相关文章

  • 在动态事件处理程序中引用“this”

    在我的 myClass 类中 我使用 Reflection Emit 为 myClass 类成员之一动态编写事件处理程序 我已经成功地做到了这一点 现在 我想修改事件处理程序以调用 myClass 类中的实例方法之一 但是 我无法弄清楚如何
  • 如何将包含 5000 条记录的 Excel 文件插入到 documentDB 中?

    我有一个 Excel 文件 最初约有 200 行 我能够将 Excel 文件转换为数据表 并且所有内容都正确插入到 documentdb 中 Excel 文件现在有 5000 行 在插入 30 40 条记录后不会插入 其余所有行不会插入到
  • C# 创建函数队列

    我写了一个名为 QueueManager 的类 class QueueManager Queue functionsQueue public bool IsEmpty get if functionsQueue Count 0 return
  • 使用 OpenGL 着色器进行数学计算 (C++)

    我有一个矩阵 例如 100x100 尺寸 我需要对每个元素进行计算 matrix i j tt 8 5例如 我有一个巨大的矩阵 我想使用 OpenGL 着色器来实现该算法 我想使用着色器 例如 uniform float val unifo
  • C# 中四舍五入到偶数

    我没有看到 Math Round 的预期结果 return Math Round 99 96535789 2 MidpointRounding ToEven returning 99 97 据我了解 MidpointRounding ToE
  • 无法从 Web api POST 读取正文数据

    我正在尝试从新的 Asp Net Web Api 中的请求中提取一些数据 我有一个像这样的处理程序设置 public class MyTestHandler DelegatingHandler protected override Syst
  • 是否有像 gccxml 这样的用于生成包装器的 C 标头解析器工具?

    我需要为一种新的编程语言编写一些 C 标头包装器 并且想要类似 gccxml 的东西 但不完全依赖 gcc 以及它在 Windows 系统上带来的问题 只需要读C而不是C 只要有完整的文档记录 任何格式的输出都可以 Linux Solari
  • 如何使用 wpf webbrowser 将数据发布到 Web 服务器

    我想从数据库获取数据并使用它来让用户登录到网站 我有一个包含 Web 浏览器控件的 wpf 页面 我有这样的代码 用于将用户登录到用 php 编写的网站
  • 存储过程上的 OdbcCommand - 输出参数上出现“未提供参数”错误

    我正在尝试执行存储过程 通过 ODBC 驱动程序针对 SQL Server 2005 但收到以下错误 过程或函数 GetNodeID 需要参数 ID 但未提供该参数 ID 是我的过程的 OUTPUT 参数 在存储过程中指定了一个输入 mac
  • 在Python中计算结构体的CRC

    我有以下结构 来自 C 中的 NRPE 守护程序代码 typedef struct packet struct int16 t packet version int16 t packet type uint32 t crc32 value
  • 格式化货币

    在下面的示例中 逗号是小数点分隔符 我有这个 125456 89 我想要这个 125 456 89 其他示例 23456789 89 gt 23 456 789 89 Thanks 看看这个例子 double value 12345 678
  • C#中Enum中定义的value__是什么

    What value 可能在这里 value MSN ICQ YahooChat GoogleTalk 我运行的代码很简单 namespace EnumReflection enum Messengers MSN ICQ YahooChat
  • dropdownlist DataTextField 由属性组成?

    有没有一种方法可以通过 C 使 asp net 中的下拉列表的 datatextfield 属性由对象的多个属性组成 public class MyObject public int Id get set public string Nam
  • 如何用 C 语言练习 Unix 编程?

    经过五年的专业 Java 以及较小程度上的 Python 编程并慢慢感觉到我的计算机科学教育逐渐消失 我决定要拓宽我的视野 对世界的一般用处 并做一些 对我来说 感觉更重要的事情就像我真的对机器有影响一样 我选择学习 C 和 Unix 编程
  • 系统错误 124 - SHFileOperation 的 ERROR_INVALID_LEVEL

    我在使用时遇到问题SHFileOperation SHFileOperation SHFILEOPSTRUCT https stackoverflow com questions 9191415 shfileoperation shfile
  • 设计 Javascript 前端 <-> C++ 后端通信

    在我最近的将来 我将不得不制作一个具有 C 后端和 Web 前端的系统 要求 目前 我对此了解不多 我认为前端将触发数据传输 而不是后端 所以不需要类似 Comet 的东西 由于在该领域的经验可能很少 我非常感谢您对我所做的设计决策的评论
  • .NET JIT 编译的代码缓存在哪里?

    NET 程序首先被编译为 MSIL 代码 当它被执行时 JIT编译器会将其编译为本机机器代码 我想知道 这些JIT编译的机器代码存储在哪里 它只存储在进程的地址空间中吗 但由于程序的第二次启动比第一次快得多 我认为即使在执行完成后 该本机代
  • 如何访问窗口?

    我正在尝试使用其句柄访问特定窗口 即System IntPtr value Getting the process of Visual Studio program var process Process GetProcessesByNam
  • ASP.NET Core Razor Page 多路径路由

    我正在使用 ASP NET Core 2 0 Razor Pages 不是 MVC 构建系统 但在为页面添加多个路由时遇到问题 例如 所有页面都应该能够通过 abc com language 访问segment shop mypage 或
  • 如何设置 CMake 与 clang 交叉编译 Windows 上的 ARM 嵌入式系统?

    我正在尝试生成 Ninja makefile 以使用 Clang 为 ARM Cortex A5 CPU 交叉编译 C 项目 我为 CMake 创建了一个工具链文件 但似乎存在错误或缺少一些我无法找到的东西 当使用下面的工具链文件调用 CM

随机推荐