std::num_get<CharT,InputIt>:: get, std::num_get<CharT,InputIt>:: do_get
| (1) | ||
|
public
:
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
|
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long long & v ) const ; |
(自 C++11 起) | |
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned short & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned int & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned long & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned long long & v ) const ; |
(自 C++11 起) | |
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, float & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, double & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long double & v ) const ; |
||
|
iter_type get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, void * & v ) const ; |
||
| (2) | ||
|
protected
:
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
|
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long long & v ) const ; |
(自 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 ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned int & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, unsigned long & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std::
ios_base
::
iostate
&
err,
|
(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 ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, double & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, long double & v ) const ; |
||
|
virtual
iter_type do_get
(
iter_type in, iter_type end,
std::
ios_base
&
str,
std:: ios_base :: iostate & err, void * & v ) const ; |
||
do_get
。
转换分三个阶段进行:
目录 |
阶段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 是否允许出现在由阶段1选定的转换说明符对应的 std::scanf 输入字段中。若允许,则将其累积到临时缓冲区中并重复阶段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>
的公开成员函数)
|