std::num_get<CharT,InputIt>::get, std::num_get<CharT,InputIt>::do_get
public:
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, bool& v ) const;
|
(1) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long& v ) const;
|
(2) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long long& v ) const;
|
(3) | (自 C++11 起) |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned short& v ) const;
|
(4) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned int& v ) const;
|
(5) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned long& v ) const;
|
(6) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned long long& v ) const;
|
(7) | (自 C++11 起) |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, float& v ) const;
|
(8) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, double& v ) const;
|
(9) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long double& v ) const;
|
(10) | |
iter_type get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, void*& v ) const;
|
(11) | |
protected:
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, bool& v ) const;
|
(12) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long& v ) const;
|
(13) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long long& v ) const;
|
(14) | (自 C++11 起) |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned short& v ) const;
|
(15) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned int& v ) const;
|
(16) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned long& v ) const;
|
(17) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err,
unsigned long long& v ) const;
|
(18) | (自 C++11 起) |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, float& v ) const;
|
(19) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, double& v ) const;
|
(20) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long double& v ) const;
|
(21) | |
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, void*& v ) const;
|
(22) | |
do_get。in,并生成类型 v 的值,考虑来自 str.flags() 的 I/O 流格式标志、来自 std::use_facet<std::ctype<CharT>>(str.getloc()) 的字符分类规则以及来自 std::use_facet<std::numpunct<CharT>>(str.getloc()) 的数值标点字符。所有格式化的输入流运算符(如 std::cin >> n;)都会调用此函数。转换分三个阶段进行:
阶段1:转换说明符选择
- I/O 格式标志的获取,如同通过
- fmtflags basefield = ( str. flags ( ) & std:: ios_base :: basefield ) ;
- fmtflags boolalpha = ( str. flags ( ) & std:: ios_base :: boolalpha ) ;
- 若 v 的类型为整数类型,则以下五个选项中的首个适用项将被选中:
- 若 basefield == oct ,将使用转换说明符 % o
- 若 basefield == hex ,将使用转换说明符 % X
- 若 basefield == 0 ,将使用转换说明符 % i
- 若 v 的类型为有符号类型,将使用转换说明符 % d
- 若 v 的类型为无符号类型,将使用转换说明符 % u
- 对于整数类型,如有必要会向转换说明符添加长度修饰符: h 用于 short 和 unsigned short , l 用于 long 和 unsigned long , ll 用于 long long 和 unsigned long long (自 C++11 起)
- 若 v 的类型为 float ,将使用转换说明符 % g
- 若 v 的类型为 double ,将使用转换说明符 % lg
- 若 v 的类型为 long double ,将使用转换说明符 % Lg
- 若 v 的类型为 void * ,将使用转换说明符 % p
- 若 v 的类型为 bool 且 boolalpha == 0 ,则按 v 的类型为 long 的方式处理,但在阶段 3 中存储到 v 的值除外。
-
若
v
的类型为
bool
且
boolalpha
!
=
0
,以下内容将替换阶段 2 和 3:
- 从输入迭代器 in 获取的连续字符,将根据 std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . falsename ( ) 和 std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . truename ( ) 获取的字符序列进行匹配,仅需匹配到能唯一识别为止。输入迭代器 in 仅在需要获取字符时才与 end 进行比较。
- 若目标序列被唯一匹配, v 将被设为对应的 bool 值。否则将向 v 存储 false 并向 err 赋值 std::ios_base::failbit 。若在输入结束前( in == end )未能找到唯一匹配,则执行 err | = std:: ios_base :: eofbit 。
阶段2:字符提取
- 如果
in == end,阶段2立即终止,不再提取字符。 - 下一个字符从
in中提取,如同通过char_type ct = *in;:- 如果该字符匹配
"0123456789abcdefxABCDEFX+-"(直到C++11)"0123456789abcdefpxABCDEFPX+-"(自C++11起)之一,通过std::use_facet<std::ctype<CharT>>(str.getloc()).widen()扩宽为本地环境的char_type,则将其转换为相应的char。 - 如果该字符匹配小数点分隔符(
std::use_facet<std::numpunct<CharT>>(str.getloc()).decimal_point())),则被替换为'.'。 - 如果该字符匹配千位分隔符(
std::use_facet<std::numpunct<CharT>>(str.getloc()).thousands_sep())并且正在使用千位分隔(由std::use_facet<std::numpunct<CharT>>(str.getloc()).grouping().length() != 0确定),则如果小数点'.'尚未累积,记住该字符的位置,但忽略该字符。如果小数点已经累积,则丢弃该字符并终止阶段2。 - 在任何情况下,都要检查从先前步骤获得的
char是否允许出现在由std::scanf(根据阶段1选择的转换说明符)解析的输入字段中。如果允许,则将其累积到临时缓冲区中并重复阶段2。如果不允许,则阶段2终止。
- 如果该字符匹配
阶段3:转换与存储
- 在阶段2中累积的 char 序列将被转换为数值:
|
(C++11 前) |
|
(C++11 起) |
- 若转换函数未能转换整个字段,则将值 0 存入 v 。
- 若 v 为有符号整数类型且转换结果超出其表示范围,则分别存入该类型可表示的最大正值或最小负值至 v 。
- 若 v 为无符号整数类型且转换结果超出其表示范围,则存入该类型可表示的最大正值至 v 。
- 无论何种情况,若转换函数失败,则将 std::ios_base::failbit 赋值给 err 。
-
否则,转换的数值结果将存入
v
。
- 若 v 的类型为 bool 且未设置 boolalpha,则当待存储值为 0 时存入 false ,当待存储值为 1 时存入 true ,对于其他任何值则将 std::ios_base::failbit 赋值给 err 并存入 true 。
- 随后检查数字分组:若在阶段2中被舍弃的千位分隔符位置与 std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . grouping ( ) 所提供的分组规则不匹配,则将 std::ios_base::failbit 赋值给 err 。
- 若阶段2因条件 in == end 而终止,则执行 err | = std:: ios_base :: eofbit 以设置 eof 位。
返回值
in
注释
在 LWG issue 23 和 LWG issue 696 的决议通过之前, v 在发生错误时保持未更改状态。
在
LWG 问题 221
解决之前,表示十六进制整数的字符串(例如
"0xA0"
)会被
do_get(int)
拒绝,即使它们是
strtol
的有效输入,因为阶段 2 会过滤掉字符
'X'
和
'x'
。
在 LWG issue 1169 解决之前,将负数字符串转换为无符号整数可能产生零(因为字符串表示的数值小于目标类型所能表示的范围)。
|
在解决
LWG 问题 2381
之前,即使是指数形式的十六进制浮点数表示字符串(例如
"0x1.23p-10"
)能够作为
strtod
的有效输入,也会被
表示无穷大或非数字的字符串(例如
"NaN"
和
"inf"
)即使能够作为
|
(C++11 起) |
示例
用户自定义类型的
operator>>
实现示例。
#include <iostream> #include <iterator> #include <locale> struct base { long x; }; template<class CharT, class Traits> std::basic_istream<CharT, Traits>& operator >>(std::basic_istream<CharT, Traits>& is, base& b) { std::ios_base::iostate err = std::ios_base::goodbit; try // setting err could throw { typename std::basic_istream<CharT, Traits>::sentry s(is); if (s) // if stream is ready for input std::use_facet<std::num_get<CharT>>(is.getloc()).get(is, {}, is, err, b.x); } catch (std::ios_base::failure& error) { // handle the exception } return is; } int main() { base b; std::cin >> b; }
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 问题报告 | 适用标准 | 发布行为 | 正确行为 |
|---|---|---|---|
| LWG 17 | C++98 | 文本布尔值解析过程存在错误 | 已修正 |
| LWG 18 | C++98 |
接受
get
的
bool
&
参数的重载缺失
|
已添加 |
| LWG 23 | C++98 | 输入溢出导致未定义行为 | 溢出已处理 |
| LWG 154 | C++98 | double 的转换说明符为 % g (与 float 相同) | 改为 % lg |
| LWG 221 | C++98 |
do_get
未解析
'x'
和
'X'
,而
strtol
会解析它们
|
使 'x' 和 'X' 可被解析 |
| LWG 275 | C++98 |
get
存在接受
short
&
参数的重载,而非
float
&
|
已修正 |
| LWG 358 | C++98 | 小数点后的千位分隔符被忽略 | 遇到时终止阶段2 |
| LWG 696 | C++98 | 转换失败时结果保持不变 | 设置为零 |
| LWG 1169 | C++98 | 浮点类型的溢出处理不一致 |
与
strtof
/
strtod
保持一致
|
| LWG 2381 | C++11 |
do_get
未解析
'p'
和
'P'
,而
strtod
会解析它们
|
使 'p' 和 'P' 可被解析 |
另请参阅
|
提取格式化数据
(
std::basic_istream<CharT,Traits>
的公开成员函数)
|