`std::istream::operator>>()`可以接受类似于stdio中的%i格式说明符的整数基数前缀吗?

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++前缀约定表示为十六进制、八进制或十进制。当前使用sscanf()实现自动使用%i来完成这个功能,我很好奇是否可以修改为使用iostream而不必显式解析数字格式。

有趣。+1。不知道C++ IOStreams和Locales书里是否有这种东西... - Billy ONeal
由于我几乎可以确定没有直接等价物,我认为最简洁和最符合要求的解决方案是实现一个新的操纵器,形式为 std::ios_base& integer( std::ios_base& str ); - Clifford
@Johannes已经给出了答案,同时也提供了实现上述操作器的方法。 - Clifford
2个回答

11

basic_istream的格式标志中的基础字段决定了如何解释数字。该字段可以设置为decocthex。默认情况下,它被设置为dec。如果它没有被设置为这些值中的任何一个,basic_istream将像scanf%i标志一样运行:

// automatically detect the base, depending on prefix
std::cin.unsetf(std::ios_base::basefield);

太厉害了!现在我知道如何做了,找到告诉你如何做的文档就容易多了!例如:http://stdcxx.apache.org/doc/stdlibug/28-3.html - Clifford

1

不要直接重置基础字段,稍微更加直观的解决方案是使用setbase(int base)操作器:

#include <iomanip>
#include <iostream>

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

除了8、10、16以外的基数值会将basefield重置为零,这意味着输出十进制数并且输入时需要考虑前缀。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接