5

首先,我为我会犯的任何英语错误道歉,但是 15 岁和法语并没有帮助......

我正在尝试借助文件格式规范(http://www.libpng.org/pub/png/spec/1.2/PNG-Contents.html)对 PNG 解码器进行编程,但我遇到了一个奇怪的问题。

规范说 PNG 文件的前 8 个字节总是包含以下(十进制)值:137 80 78 71 13 10 26 10。

当我测试这个简单的程序时:

int main() 
{
    ifstream file("test.png");

    string line;
    getline(file, line);

    cout << line[0] << endl;
}

输出是“ë”,它代表 ascii 表中的 137。很好,它匹配第一个字节。

但是,当我这样做时int ascii_value = line[0];,输出值为 -119,这不是正确的 ascii 值。

当我用另一个字符(如“e”)尝试同样的事情时,它确实输出了正确的 ascii 值。

有人可以解释我做错了什么以及解决方案是什么?我个人认为这是扩展 ascii 表的问题,但我不确定。

谢谢大家 !我会将签名的字符转换为未签名的字符

4

6 回答 6

10

您的系统char类型是有符号的,这就是它的值可以为负数的原因。

您需要明确并放弃标志:

const unsigned char value = (unsigned char) line[0];

请注意,您的机器似乎正在使用二进制补码中的-119 = 137。所以这些位本身确实是正确的,这一切都是为了正确地解释它们。

于 2013-01-28T15:52:46.977 回答
5

char在 C++ 中,既可以是有符号的也可以是无符号的1),这取决于它的实现。对于您的编译器(实际上是大多数情况),它似乎已签名:

任何大于 128 的字符值都表示为负数。-119 恰好对应于无符号字符值 137。换句话说,以下成立:

unsigned char c = 137;
assert(static_cast<signed char>(c) == -119);

但请注意,这是特定于实现的,因此您通常不能依赖这些值。


1) And 与 and 都是不同的类型signed charunsigned char

于 2013-01-28T15:52:13.987 回答
4

ASCII 仅涵盖 0 .. 127。ASCII 表中没有 137。

也没有“扩展的 ASCII 表”之类的东西。有几十个(相互不兼容的)ASCII 扩展。哎呀,从技术上讲,即使是 Unicode 也是“扩展的 ASCII”。

您得到 -119 是因为在您的编译器char中是有符号类型,涵盖从 -128 到 127 的值。(-119 是 137 - 256)。您可以通过显式转换为来获得您期望的值unsigned char

int value = static_cast<unsigned char>(line[0]);
于 2013-01-28T15:52:54.313 回答
0

当您允许符号扩展时,就会发生这种情况。扩展 ASCII 表中的字符设置了它们的高位(符号位)。

-119 是0x89. 137也是0x89

尝试

int ascii_value = line[0] & 0x00FF;

或者

int ascii_value = (unsigned char)line[0];
于 2013-01-28T15:52:29.683 回答
0

137 = -119 = 0x89。如果你 cast (unsigned) (unsigned char)(line[0]),你会得到它来打印整数值 137。

类型char(它是 的基本类型std::string)[通常]是一个有符号值,范围为 -128-127。任何高于 127 的都是负数。

于 2013-01-28T15:53:37.513 回答
0

C++ 没有指定char是有符号类型还是无符号类型。这意味着“扩展”的 ASCII 字符(0..127 范围之外的字符,其最高位设置)可能被解释为负值;看起来这就是你的编译器所做的。

要获得您期望的无符号值,您需要将其显式转换为unsigned char类型:

int ascii_value = static_cast<unsigned char>(line[0]); // Should be 137
于 2013-01-28T15:57:13.713 回答