我正在尝试实现一个霍夫曼树。
我想做一个简单测试的简单.txt文件的内容:
aaaaabbbbccd
字符频率:a:5,b:4,c:2,d:1
代码表:(数据类型 1 s且 0 s:字符串)
a:0
d:100
c:101
b:11
我想写成二进制文件的结果:(22位)
0000011111111101101100
如何将 逐位 将此结果的每个字符作为二进制文件写入“.dat”文件? (不是字符串)
答案 0 :(得分:4)
答案:你不能。
您可以写入文件(或从中读取)的最小金额为char
或unsigned char
。出于所有实际目的,char只有8位。
您将需要一个char缓冲区,以及它所拥有的位数的计数。当该数字达到8时,您需要将其写出,并将计数重置为0.您还需要一种方法来在最后刷新缓冲区。 (不是你不能将22位写入文件 - 你只能写16或24.你需要一些方法来标记最后哪些位未被使用。)
类似的东西:
struct BitBuffer {
FILE* file; // Initialization skipped.
unsigned char buffer = 0;
unsigned count = 0;
void outputBit(unsigned char bit) {
buffer <<= 1; // Make room for next bit.
if (bit) buffer |= 1; // Set if necessary.
count++; // Remember we have added a bit.
if (count == 8) {
fwrite(&buffer, sizeof(buffer), 1, file); // Error handling elided.
buffer = 0;
count = 0;
}
}
};
答案 1 :(得分:0)
如何将此结果的每个字符逐位写为“.dat”文件的二进制文件? (不是字符串)
你不能,这就是为什么......
记忆模型
为C ++抽象机器定义计算机内存存储的语义。
C ++程序可用的内存是
bytes
的一个或多个连续序列。内存中的每个字节都有一个唯一的地址。<强>字节强>
byte
是最小的可寻址内存单位。它被定义为一个连续的位序列,大到足以保存任何UTF-8代码单元(256个不同的值)和{em}基本执行字符集的任何成员{/ 1}}的值 (需要(since C++14)
的96个字符。与C类似,C ++支持大小为8位且更大的single-byte
。类型
bytes
,char
和unsigned char
使用一个字节表示存储和值。一个字节中的位数可以signed char
或CHAR_BIT
访问。
std::numeric_limits<unsigned char>::digits
您可以在此处找到此页面:cppreference:memory model
这来自2017-03-21:标准
©ISO / IEC N4659
4.4 C ++内存模型 [intro.memory]
- C ++内存模型中的基本存储单元是字节。一个字节至少足以包含基本执行字符集(5.3)的任何成员和Unicode UTF-8编码形式的八位代码单元,并由一个连续的位序列组成, 4 < / sup>其数量是实现定义的。最低有效位称为低位;最重要的位称为高位。 C ++程序可用的内存由一个或多个连续字节序列组成。每个字节都有一个唯一的地址。
- [注意:类型的表示形式在6.9中描述。 - 结束记录]
- 内存位置是标量类型的对象,或者是具有非零宽度的相邻位域的最大序列。 [注意:该语言的各种功能,例如引用和虚函数,可能涉及程序无法访问但由实现管理的其他内存位置。 - 结束注释]两个或多个执行线程(4.7)可以访问单独的内存位置而不会产生干扰 彼此。
- [注意:因此,位字段和相邻的非位字段位于不同的存储单元中,因此可以通过两个执行线程同时更新而不会产生干扰。这同样适用于两个位字段,如果一个在嵌套的结构声明中声明而另一个未声明,或者两者是由零长度位字段声明分隔,或者它们是由非位分隔 - 现场声明。如果它们之间的所有字段也是非零宽度的位字段,则同时更新同一结构中的两个位字段是不安全的。 - 结束记录]
- 醇>
[示例:声明为
的结构cppreference.com
包含四个独立的内存位置:字段a和位字段d和e.ee是每个单独的内存 位置,并且可以同时修改而不会相互干扰。位域b和c 一起构成第四个记忆位置。位字段b和c不能同时修改,但是 例如,b和a可以。 - 结束示例]
<小时/> 4)一个字节中的位数由标题struct { char a; int b:5, c:11, :0, d:8; struct {int ee:8;} e; }
中的宏 CHAR_BIT 报告。
此版本标准可在此处找到:
第8页上的www.open-std.org部分<climits>
&amp; 9。
对于标准字节,可以在程序中写入的最小可能存储器模块是8个连续位或更多位。即使使用位字段,§ 4.4
要求仍然有效。您可以在1 byte
内操纵,切换,设置各个位,但不能单独编写byte
。
可以做的是使用bits
缓冲区写入位数。写入所需位后,您需要将剩余的未使用位标记为byte
或padding
。
修改强>
[注意:] - 使用un-used buffer bits
或bit fields
时,您必须考虑的一件事是{{1}特定架构。
答案 2 :(得分:0)
您好,根据我的经验,我找到了一种简单的方法。对于此任务,您需要定义自己和字符数组(例如,仅需要1个字节,它可以更大)。之后,您必须定义函数以从任何元素访问特定位。例如,如何编写表达式以从C ++中的char中获取第3位的值。
*/*position is [1,..,n], and bytes
are in little endian and index from 0`enter code here`*/
int bit_at(int position, unsigned char byte)
{
return (byte & (1 << (position - 1)));
}*
现在您可以像这样想象字节数组 [b1,...,bn]
现在我们在内存中实际拥有的是8 * n位内存 我们可以尝试像这样可视化它。 注意:数组归零! | 0000 0000 | 0000 0000 | ... | 0000 0000 |
现在,您或任何人想要了解如何操纵它以从此数组中获取特定位。当然会有某种转换,但这不是问题。 最后,对于您提供的编码,即: a:0 d:100 c:101 b:11
我们可以对消息“ abcd”进行编码, 并创建一个包含位的数组 消息,使用元素 数组作为位数组,例如:
| 0111 0110 | 0000 0000 |
您可以将此内容写入内存,最多可以有7位多余的空间。 这是一个简单的示例,但可以扩展到更多示例。 我希望这能回答您的问题。