std::num_get<CharT,InputIt>::get, std::num_get<CharT,InputIt>::do_get
来自cppreference.com
(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, unsigned 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, 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; |
||
1) 公开成员函数,调用最终导出类的成员函数
do_get
。2) 从输入迭代器
in
读取字符,并生成 v
的类型的值,考虑来自 IO 流 str.flags()
的格式化标志,来自 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
- 对于整数类型,若需要则添加长度说明符到转换说明:对于 short 和 unsigned short 为 h ,对于 long 和 unsigned long 为 l ,对于 long long 和 unsigned long long 为 ll
- 若
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 值。否则存储 false 于v
并赋值 std::ios_base::failbit 给err
。若在输入结束( in==end )前无法找到唯一匹配,则执行 err|=std::ios_base::eofbit 。
- 从输入迭代器
阶段 2 :字符提取
- 若 in==end ,则立即终止阶段 2 ,则不再提取更多字符
- 如同以 char_type ct = *in; 从 in 提取下个字符
- 若字符匹配如同用 std::use_facet<std::ctype<charT>>(str.getloc()).widen() 加宽到 locale 的 char_type 的 "0123456789abcdefxABCDEFX+-" 字符之一,则将它转换为对应的 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 序列为数值
- 如同以对有符号整数
v
的 std::strtoll 、对无符号整数v
的 std::strtoull 、对float
v
的 std::strtof 、对double
v
的 std::strtod 或对long double
v
的 std::strtold 分析输入
- 若转换函数无法转换整个域,则存储值 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
。 - 若因测试 in==end 终止阶段 2 ,则执行 err|=std::ios_base::eofbit 设置 eof 位。
返回值
in
注解
C++98/C++03 指定若出现错误则保留 v
不更改。这种行为被并入 C++11 的 LWG23 及 LWG696 更正。
转换负整数字符串为无符号整数时,某些实现产生零(因为字符串所表示的值小于目标类型所能表示的)。这种行为曾被 C++11/14 标准指定,但被 LWG1169 更正。
因为阶段 2 滤出如 'p' 、 'N' 或 'i' 的字符,如 "0x1.23p-10" 的十六进制浮点数和字符串 "NaN" 或 "inf" 可能为 do_get(double)
所拒绝,即使它们它们是对 strtod
的合法输入:此为 LWG 问题 2381 。
示例
用户定义类型的 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 // 设置 err 为能抛出 { typename std::basic_istream<CharT, Traits>::sentry s(is); if (s) // 若流已为输入就绪 { std::use_facet<std::num_get<CharT>>(is.getloc()).get(is, {}, is, err, b.x); } } catch(std::ios_base::failure& error) { // 处理异常 } return is; } int main() { base b; std::cin >> b; }
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
DR | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
LWG 23 | C++98 | 溢出的输入导致未定义行为 | 处理溢出 |
LWG 696 | C++98 | 转换失败时不更改结果 | 设为零 |
LWG 1169 | C++98 | 溢出处理在不同浮点类型间不一致 | 使得与 strtof /strtod 一致
|
参阅
提取带格式数据 ( std::basic_istream<CharT,Traits> 的公开成员函数) |