首先,我想解析负值为unsigned
值是错误的。值由std::num_get<char>
根据strtoull()
格式(22.4.2.12第3段,第3阶段,第二子弹)解码。的strtoull()
格式是以C 7.22.1.4定义为相同在C 6.4.4.1整数常量这要求字面值能够通过unsigned
类型来表示。显然,负值不能用unsigned
类型表示。无可否认,我看着C11,我并不真正从C++ 11引用C标准。另外,在编译器中引用标准段落不会解决问题。因此,下面是一种整洁地改变值解码的方法。
您可以设置全局std::locale
,其中std::num_get<...>
方面拒绝以unsigned long
和unsigned long long
的减号开始的字符串。 do_put()
覆盖可以简单地检查第一个字符,然后委托给基类版本,如果它不是'-'
。
下面是一个自定义方面的代码。虽然它有相当多的代码,但实际使用是相当直接的。大部分代码只是样板重写用于解析一个unsigned
数(即,do_get()
成员)的不同virtual
功能。这些都是根据成员函数模板get_impl()
执行的,它检查是否不再有字符或者下一个字符是否为'-'
。在这两种情况下,转换都会失败,方法是将std::ios_base::failbit
添加到参数err
。否则,该函数仅委托给基类转换。
的相应创建面最终被用来构建一个新的std::locale
对象(custom
;注意,如果使用它的最后一个std::locale
对象释放时,分配的positive_num_get
对象会自动释放)。此std::locale
已安装成为全球语言环境。全局语言环境由所有新创建的流使用。在示例std::cin
中,现有流需要使用区域设置为imbue()
d,前提是它应该影响它们。一旦建立了全局区域设置,新创建的流就会选择改变的解码规则,即不需要更改代码。
#include <iostream>
#include <sstream>
#include <locale>
class positive_num_get
: public std::num_get<char> {
typedef std::num_get<char>::iter_type iter_type;
typedef std::num_get<char>::char_type char_type;
// actual implementation: if there is no character or it is a '-' fail
template <typename T>
iter_type get_impl(iter_type in, iter_type end,
std::ios_base& str, std::ios_base::iostate& err,
T& val) const {
if (in == end || *in == '-') {
err |= std::ios_base::failbit;
return in;
}
else {
return this->std::num_get<char>::do_get(in, end, str, err, val);
}
}
// overrides of the various virtual functions
iter_type do_get(iter_type in, iter_type end,
std::ios_base& str, std::ios_base::iostate& err,
unsigned short& val) const override {
return this->get_impl(in, end, str, err, val);
}
iter_type do_get(iter_type in, iter_type end,
std::ios_base& str, std::ios_base::iostate& err,
unsigned int& val) const override {
return this->get_impl(in, end, str, err, val);
}
iter_type do_get(iter_type in, iter_type end,
std::ios_base& str, std::ios_base::iostate& err,
unsigned long& val) const override {
return this->get_impl(in, end, str, err, val);
}
iter_type do_get(iter_type in, iter_type end,
std::ios_base& str, std::ios_base::iostate& err,
unsigned long long& val) const override {
return this->get_impl(in, end, str, err, val);
}
};
void read(std::string const& input)
{
std::istringstream in(input);
unsigned long value;
if (in >> value) {
std::cout << "read " << value << " from '" << input << '\n';
}
else {
std::cout << "failed to read value from '" << input << '\n';
}
}
int main()
{
read("\t 17");
read("\t -18");
std::locale custom(std::locale(), new positive_num_get);
std::locale::global(custom);
std::cin.imbue(custom);
read("\t 19");
read("\t -20");
}
看看的boost :: numerical_cast http://www.boost.org/doc/libs/1_55_0/libs/numeric/conversion/doc /html/boost_numericconversion/improved_numeric_cast__.html –
哇,TIL,只有早上。 – chris
该代码的输出结果应该是什么? – Nawaz