11

当使用 scanf() 及其变体时,格式说明符%i将接受十六进制(前缀为“0x”)、八进制(前缀为“0”)或十进制(无前缀)的数据,例如字符串“0x10”、“020” ", 和 "16" 都转换为十进制值为 16 的整数。

这可以通过std::istream::operator>>格式化输入来完成吗?

使用>> i没有 i/o 操纵器的普通“0x10”被转换为零(或者更确切地说,前导 0 是,“x10”部分不被处理),“020”到 20。 和操纵器的hex行为分别类似于,oct和。我正在寻找一个像.dec%x%o%d%i

有趣的是,hex操纵器可能同时接受“0x10”和“10”转换为十进制的 16。

如果您想知道,我正在实现一个表达式求值器,并且我希望使用 C/C++ 前缀约定允许整数操作数为十六进制、八进制或十进制。当前的实现 usingsscanf()自动执行此操作%i,我很好奇是否可以将其修改为使用 iostream 而无需显式解析数字格式。

4

2 回答 2

11

格式标志中的基本字段basic_istream指示如何解释数字。该字段可以设置为dec和。默认情况下,它设置为. 如果它没有设置为任何一个,将表现得像'标志:octhexdecbasic_istreamscanf%i

// automatically detect the base, depending on prefix
std::cin.unsetf(std::ios_base::basefield);
于 2010-12-18T07:16:39.910 回答
1

与其直接重置基域,一个稍微更直观的解决方案是使用setbase(int base)操纵器:

#include <iomanip>
#include <iostream>

int main()
{
  int i;
  std::cin >> std::setbase(0) >> i;
  std::cout << i << std::endl;
}

引用 cppreference:

非 8、10 或 16 的基值会将基域重置为零,这对应于十进制输出和依赖于前缀的输入。

于 2018-08-03T12:04:52.443 回答