gpt4 book ai didi

c - 将无符号 16 位整数存储到文件的最有效方法

转载 作者:太空宇宙 更新时间:2023-11-03 23:52:41 25 4
gpt4 key购买 nike

我正在用 C 语言制作一个字典压缩器,字典最大大小为 64000。因此,我将我的条目存储为 16 位整数。

我目前在做什么:
为了编码“a”,我得到它的 ASCII 值 97,然后将该数字转换为 16 位整数 97 的字符串表示形式。所以我最终为“a”编码了“0000000001100001”,这显然不是在短期内节省大量空间。

我知道这个算法的更有效版本将从更小的整数大小开始(在我们需要更多之前,更少的存储位),但我想知道是否有更好的方法

  • 将我的整数 '97' 转换为可以存储 16 位数据的固定长度的 ASCII 字符串(97 将是 x 位,46347 也将是 x 位)
  • 写入只能存储 1 和 0 的文件。因为实际上,我似乎正在将 16 个 ascii 字符写入一个文本文件,每个文件都是 8 位......所以这对原因没有多大帮助,是吗?

  • 如果我能以任何方式更清楚,请告诉我。我对这个网站很陌生。谢谢!

    编辑:据我所知,我如何存储字典完全取决于我。我只知道我需要能够轻松地读回编码文件并从中获取整数。

    另外,我可以 仅限 包括我为程序编写的 stdio.h、stdlib.h、string.h 和头文件。

    最佳答案

    请忽略这些建议您“直接写入文件”的人。有很多问题,最终属于“整数表示”的范畴。使用 fwrite 将整数直接写入外部存储似乎有一些令人信服的理由。或者什么不是,这里有一些确凿的事实在起作用。

    瓶颈是外部存储 Controller 。 如果您正在编写网络应用程序,要么是那个,要么是网络。因此,将两个字节写为一个 fwrite , 或作为两个不同的 fputc s,应该是大致相同的速度,前提是您的内存配置文件适合您的平台。您可以调整 FILE * 的缓冲量。 s 在一定程度上使用 setvbuf (注意:必须是 2 的幂),所以我们总是可以根据我们的分析器告诉我们的内容对每个平台进行微调,尽管这些信息可能应该通过温和的建议优雅地漂浮到标准库的上游,以便对其他项目有用,也。

    当今计算机之间的基础整数表示是不一致的。 假设你写 unsigned int s 直接使用系统 X 使用 32 位整数和大端表示的文件,您最终会在使用 16 位整数和小端表示的系统 Y 或使用 64- 的系统 Z 上读取该文件时遇到问题具有混合字节序表示和 32 个填充位的位整数。如今,我们拥有这种 15 年前的计算机组合,人们用 ARM big.Little SoC、智能手机和智能电视、游戏机和 PC 来折磨自己,所有这些都有自己的怪癖,超出了标准 C 的范围,特别是在整数表示、填充等方面。

    C 的开发考虑到了抽象,允许您以可移植的方式表达您的算法,因此您不必为每个操作系统编写不同的代码!这是读取四个十六进制数字并将其转换为 unsigned int 的示例值(value),便携:

    unsigned int value;
    int value_is_valid = fscanf(fd, "%04x", &value) == 1;
    assert(value_is_valid); // #include <assert.h>
    /* NOTE: Actual error correction should occur in place of that
    * assertioon
    */

    我应该指出我选择 %04X的原因而不是 %08X或者更现代的东西......如果我们今天提出的问题, 不幸的是,有些学生使用的教科书和编译器已经超过 20 年... 他们的 int是 16 位的,从技术上讲,他们的编译器在这方面是兼容的(尽管他们真的应该在整个学术界插入 gcc 和 llvm)。考虑到可移植性,这是我编写该值的方式:
    value &= 0xFFFF;
    fprintf(fd, "%04x", value);
    // side-note: We often don't check the return value of `fprintf`, but it can also become \
    very important, particularly when dealing with streams and large files...

    假设您的 unsigned int值占用两个字节,这就是我如何使用大端表示法读取这两个字节的方式:
    int hi = fgetc(fd);
    int lo = fgetc(fd);
    unsigned int value = 0;
    assert(hi >= 0 && lo >= 0); // again, proper error detection & handling logic should be here
    value += hi & 0xFF; value <<= 8;
    value += lo & 0xFF;

    ...这就是我如何按照大端顺序编写这两个字节的方式:
    fputc((value >> 8) & 0xFF, fd);
    fputc(value & 0xFF, fd);
    // and you might also want to check this return value (perhaps in a finely tuned end product)

    也许你对小端更感兴趣。整洁的事情是,代码真的没有那么不同。这是输入:
    int lo = fgetc(fd);
    int hi = fgetc(fd);
    unsigned int value = 0;
    assert(hi >= 0 && lo >= 0);
    value += hi & 0xFF; value <<= 8;
    value += lo & 0xFF;

    ...这是输出:
    fputc(value & 0xFF, fd);
    fputc((value >> 8) & 0xFF, fd);

    对于大于两个字节的任何内容(即 long unsignedlong signed ),您可能需要 fwrite((char unsigned[]){ value >> 24, value >> 16, value >> 8, value }, 1, 4, fd);或者例如,减少样板文件。考虑到这一点,形成预处理器宏似乎并没有滥用:
    #define write(fd, ...) fwrite((char unsigned){ __VA_ARGS__ }, 1, sizeof ((char unsigned) { __VA_ARGS__ }), fd)

    我想人们可能会认为这就像选择两个弊端中的一个更好:预处理器滥用或魔数(Magic Number) 4在上面的代码中,因为现在我们可以 write(fd, value >> 24, value >> 16, value >> 8, value);没有 4被硬编码......但对于初学者来说: 副作用可能会让人头疼,所以不要在 write 的参数中引起任何类型的修改、写入或全局状态更改。 .

    好吧,这就是我今天对这篇文章的更新……社交延迟的极客现在退出。

    关于c - 将无符号 16 位整数存储到文件的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15529994/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com