【发布时间】:2018-08-14 10:30:57
【问题描述】:
我遇到了一个问题,C++ 试图读取一个以十六进制形式填充有符号整数并将它们解析为向量的文本文件。我使用 C++ 流到变量重定向(流 >> var),似乎没有正确解析负数 - 变量获取值 0,并且设置了流失败标志。
如果我尝试使用 strtol() 函数转换字符串,结果与预期一致。同样,如果我尝试首先将流重定向到无符号整数,然后将变量转换为有符号整数,结果再次正确并且不会报告流错误。
我在 Debian 9.1 (x64) 上使用 gcc 6.3.0,在 Xeon E5-2643 v3 系统上运行。
还有其他人遇到过这个问题吗?我希望转换的工作方式与 strtol 函数相同,并且不会报告任何流错误。我是否缺少一些流设置/忘记调用某些函数或在这里设置一些标志?
任何建议将不胜感激。
下面附上一个演示此问题的示例 C++ 程序。
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
int main()
{
const char* minus_one = "0xffffffff";
std::stringstream ss;
ss << minus_one;
std::cout << "input string : " << ss.str() << "\n"; // outputs "0xffffffff"
// C-style conversion
int32_t cint;
cint = strtol(ss.str().c_str(), NULL, 0);
std::cout << "strtol conv : " << cint << " (" << std::hex << cint << ")\n"; // outputs "-1 (ffffffff)"
std::cout << std::dec;
// C++-style conversion
int32_t cppint;
ss >> std::hex >> cppint;
std::cout << std::dec << "ssextr conv : " << cppint << " (" << std::hex << cppint << ")\n"; // outputs "0 (0)" <- ERROR
std::cout << std::dec;
if (ss.fail()) std::cout << "Error converting number.\n";
// C++-style conversion with cast
uint32_t cppuint;
int32_t cppint2;
ss.clear();
ss.str(minus_one);
ss >> std::hex >> cppuint;
cppint2 = (int32_t)cppuint;
std::cout << std::dec << "ssextr cast conv: " << cppint2 << " (" << std::hex << cppint2 << ")\n"; // outputs "-1 (0xffffffff)"
std::cout << std::dec;
if (ss.fail()) std::cout << "Error converting number.\n";
exit(EXIT_SUCCESS);
}
【问题讨论】:
-
不存在负十六进制数。可以将十六进制值的位模式解释为有符号整数并获得负值,但这是另一回事。您尝试读取的数字
4294967295不适合 32 位有符号整数,因此转换失败。如果您使用uint32_t,它可以正常工作,然后您可以随心所欲地解释这些位。 -
我假设我已经明确表示我正在尝试将十六进制数解释为有符号的 32 位整数,我并不是字面上的意思是负十六进制数。这里提到的数字(4294967295 或十六进制的 0xffffffff)适合 32 位,因此它应该适合有符号和无符号整数 - 正如示例程序所演示的,当解释为有符号数时,即 -1。是的,我已经知道我可以将它读入 uint32_t,然后将其转换为 int32_t 并得到正确的结果,但我不应该这样做。
-
您希望能够将
4294967295读入int32_t 吗?试试看,它也会失败,因为该值太大而无法在该类型中正确表示。 -
您明确表示您希望它以某种方式运行,但实际上并非如此。如果您尝试将值读入语言知道不能表示该值的类型,那么就会出现问题。问题是您希望忽略该问题,而 c++ 不会忽略它。使用更大的 int,或者像你一样保持一个演员表。注意,您依赖于溢出有符号数字,这是未定义的行为。
标签: c++ stream hex negative-integer