1

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

  • 压缩纯 .txt 时,一切都按预期工作,我在解压缩之前和之后得到相等的文件(我认为应该是这样,因为我们基本上在字节转换之前和之后处理文本)
  • 但是,当尝试压缩 .bmp 时,与输入文件相比,解压缩文件会丢失 3 个字节(尝试将无符号字符保存到 std::string 时会丢失这 3 个字节)

所以,我的问题是——有没有办法将无符号字符正确保存到字符串中?

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

更新:我发现丢失 3 个字节(符号)不是因为 std::string,而是因为std::istream_iterator(我使用而不是std::istreambuf_iterator)来创建无符号字符的字符串(因为std::istreambuf_iterator的参数是 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");
}
4

2 回答 2

4

char在所有形式中(和std::byte,与 同构unsigned char)始终是系统支持的最小可能类型。C++ 标准定义了它sizeof(char),它的变体应该总是正好为 1。

“一”是什么?这是实现定义的。但是系统中的每种类型的大小都会是数倍sizeof(char)

所以你不应该太担心char不是一个字节的系统。如果您在CHAR_BITS不是 8 的系统下工作,那么该系统根本无法直接处理 8 位字节。因此unsigned char,为此目的不会有任何不同/更好。


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

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

于 2019-11-30T16:31:23.787 回答
1

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

#include <ios>

file >> std::noskipws;
于 2019-11-30T16:56:11.913 回答