如何使用 std::string 以正确的方式存储字节(无符号字符)?

How to use std::string to store bytes (unsigned chars) in a right way?

我正在编写 LZ77 压缩算法,但我无法在字符串中存储无符号字符。为了压缩任何文件,我使用它的二进制表示,然后将其读取为 chars(因为 1 个字符等于 1 个字节,afaik)到 std::stringchars 一切正常。但经过一段时间的谷歌搜索后,我了解到 char 并不总是 1 个字节,所以我决定将其换成 unsigned char。事情开始变得棘手了:

So, my question is – is there a way to properly save unsigned chars to a string?

我尝试使用 typedef basic_string<unsigned char> ustring 并将所有相关函数交换为与 unsigned char 一起使用的基本替代函数,但我仍然丢失了 3 个字节。

UPDATE: I found out that 3 bytes (symbols) are lost not because of std::string, but because of std::istream_iterator (that I use instead of std::istreambuf_iterator) to create string of unsigned chars (because std::istreambuf_iterator's argument is char, not unsigned char)

那么,这个问题有什么解决方案吗?

示例:

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 的所有形式(以及与 unsigned char 同构的 std::byte)始终是系统支持的最小可能类型。 C++ 标准定义 sizeof(char) 及其变体应始终正好为 1.

"One"什么?那是实现定义的。但是系统中的每种类型的大小都是 sizeof(char) 的倍数。

所以您不必太担心 char 不是一个字节的系统。如果您在 CHAR_BITS 不是 8 的系统下工作,那么该系统根本无法直接处理 8 位字节。因此 unsigned char 不会是任何 different/better 用于此目的。


至于您的问题的细节,istream_iteratoristreambuf_iterator 迭代器根本不同。后者的目的是允许迭代器访问作为值序列的实际流。 istream_iterator<T> 的目的是允许访问流,就像通过使用 T 值执行重复的 operator >> 调用序列一样。

因此,如果您正在执行 istream_iterator<char>,那么您就是说您想要读取流,就像您对每个迭代器访问执行 stream >> some_char; 变量一样。这实际上与直接访问流的字符不同构。具体来说,FormattedInputFunctions like operator>> 可以执行诸如跳过空格之类的操作,具体取决于您如何设置流。

istream_iterator 正在使用 operator>> 读取,它通常会跳过空格作为其功能的一部分。如果你想禁用该行为,你必须做

#include <ios>

file >> std::noskipws;