[英]How to use std::string to store bytes (unsigned chars) in a right way?
我正在编写 LZ77 压缩算法,但无法在字符串中存储无符号字符。 要压缩任何文件,我使用它的二进制表示,然后将其作为chars
(因为 1 个字符等于 1 个字节,afaik)读取到std::string
。 使用chars
一切正常。 但是经过一段时间的谷歌搜索后,我了解到char
并不总是 1 个字节,所以我决定将它换成unsigned char
。 事情开始变得棘手:
所以,我的问题是 - 有没有办法将无符号字符正确保存到字符串中?
我尝试使用typedef basic_string<unsigned char> ustring
并将所有相关函数交换为与unsigned char
一起使用的基本替代方法,但我仍然丢失了 3 个字节。
更新:我发现 3 个字节(符号)丢失不是因为 std::string,而是因为
std::istream_iterator
(我用它代替std::istreambuf_iterator
)来创建无符号字符字符串(因为std::istreambuf_iterator
的参数是字符,而不是无符号字符)
那么,有没有解决这个特定问题的方法?
例子:
std::vector<char> tempbuf(std::istreambuf_iterator<char>(file), {}); // reads 112782 symbols
std::vector<char> tempbuf(std::istream_iterator<char>(file), {}); // reads 112779 symbols
示例代码:
void LZ77::readFileUnpacked(std::string& path)
{
std::ifstream file(path, std::ios::in | std::ios::binary);
if (file.is_open())
{
// Works just fine with char, but loses 3 bytes with unsigned
std::string tempstring = std::string(std::istreambuf_iterator<char>(file), {});
file.close();
}
else
throw std::ios_base::failure("Failed to open the file");
}
所有形式的char
(以及std::byte
,它与unsigned char
同构)始终是系统支持的最小可能类型。 C++ 标准定义sizeof(char)
及其变体应始终为 1。
“一个”什么? 那是实现定义的。 但是系统中的每种类型的sizeof(char)
都是sizeof(char)
倍数。
所以你不应该太担心char
不是一个字节的系统。 如果您在CHAR_BITS
不是 8 的系统下工作,那么该系统根本无法直接处理 8 位字节。 因此unsigned char
为此目的不会有任何不同/更好。
至于你的问题的细节, istream_iterator
与istreambuf_iterator
迭代器istreambuf_iterator
根本的不同。 后者的目的是允许迭代器访问作为值序列的实际流。 istream_iterator<T>
的目的是允许访问流,就像通过执行带有T
值的operator >>
调用的重复序列一样。
因此,如果您正在执行istream_iterator<char>
,那么您是在说您想像读取流一样读取stream >> some_char;
每个迭代器访问的变量。 直接访问流的字符实际上并不是同构的。 具体来说, 像operator>>
这样的FormattedInputFunctions可以执行诸如跳过空格之类的operator>>
,具体取决于您设置流的方式。
istream_iterator
正在使用operator>>
读取,它通常会跳过空格作为其功能的一部分。 如果你想禁用这种行为,你必须这样做
#include <ios>
file >> std::noskipws;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.