Namespaces
Variants

std::num_put<CharT,OutputIt>:: put, std::num_put<CharT,OutputIt>:: do_put

From cppreference.net
std::num_put
Member functions
num_put::put num_put::do_put
定义于头文件 <locale>
(1)
public :

iter_type put ( iter_type out, std:: ios_base & str,

char_type fill, bool val ) const ;
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, long val ) const ;
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, long long val ) const ;
(C++11 起)
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, unsigned long val ) const ;
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, unsigned long long val ) const ;
(C++11 起)
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, double val ) const ;
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, long double val ) const ;
iter_type put ( iter_type out, std:: ios_base & str,
char_type fill, const void * val ) const ;
(2)
protected :

virtual iter_type do_put ( iter_type out, std:: ios_base & str,

char_type fill, bool val ) const ;
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, long val ) const ;
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, long long val ) const ;
(C++11 起)
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, unsigned long val ) const ;
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, unsigned long long val ) const ;
(C++11 起)
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, double val ) const ;
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, long double val ) const ;
virtual iter_type do_put ( iter_type out, std:: ios_base & str,
char_type fill, const void * val ) const ;
1) 公开成员函数,调用最终派生类的受保护虚成员函数 do_put
2) 将表示 val 值的字符写入输出序列 out ,其格式由格式化标志 str. flags ( ) 以及流 str 所植入区域设置的 std::numpunct std::ctype 平面共同决定。此函数被所有格式化输出流运算符调用,例如 std:: cout << n ;

转换发生在四个阶段:

目录

阶段 1:转换说明符选择

  • I/O格式标志的获取,如同通过
fmtflags basefield = ( str. flags ( ) & std:: ios_base :: basefield ) ;
fmtflags uppercase = ( str. flags ( ) & std:: ios_base :: uppercase ) ;
fmtflags floatfield = ( str. flags ( ) & std:: ios_base :: floatfield ) ;
fmtflags showpos = ( str. flags ( ) & std:: ios_base :: showpos ) ;
fmtflags showbase = ( str. flags ( ) & std:: ios_base :: showbase ) ;
fmtflags showpoint = ( str. flags ( ) & std:: ios_base :: showpoint ) ;
说明:由于所有内容都包含在C++代码标签中,根据要求保留了所有C++代码和术语的原始形式,仅对HTML结构外的说明性文字进行了翻译。但当前提供的文本中所有内容均为C++代码,因此无需进行翻译处理。
  • val 的类型为 bool
    • boolalpha == 0 ,则将 val 转换为 int 类型并执行整数输出。
    • boolalpha ! = 0 ,则当 val == true 时获取 std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . truename ( ) ,当 val == false 时获取 std:: use_facet < std:: numpunct < CharT >> ( str. getloc ( ) ) . falsename ( ) ,并将该字符串的每个连续字符 c 通过 * out ++ = c 输出到 out 。此情况下不进行进一步处理,函数返回 out
  • val 的类型为整数类型,则按以下顺序选择首个适用的选项:
    • basefield == oct ,将使用转换说明符 % o
    • basefield == hex && ! uppercase ,将使用转换说明符 % x
    • basefield == hex ,将使用转换说明符 % X
    • val 的类型为有符号类型,将使用转换说明符 % d
    • val 的类型为无符号类型,将使用转换说明符 % u
  • 对于整数类型,必要时会向转换说明添加长度修饰符: l 用于 long unsigned long ll 用于 long long unsigned long long (C++11 起)
  • val 的类型为浮点类型,则按以下顺序选择首个适用的选项:
(C++11 前)
(C++11 起)
(C++11 起)
  • 如果 ! uppercase ,将使用转换说明符 % g
  • 否则,将使用转换说明符 % G
此外:
  • 如果 val 的类型是 long double ,将在转换说明符前添加长度修饰符 L
  • 如果 val 的类型是浮点类型 floatfield ! = ( ios_base :: fixed | ios_base :: scientific ) (C++11 起) ,将添加精度修饰符并设置为 str. precision ( ) 。否则,不指定精度。
  • 对于整数和浮点类型,若设置了 showpos ,则前置修饰符 +
  • 对于整数类型,若设置了 showbase ,则前置修饰符 #
  • 对于浮点类型,若设置了 showpoint ,则前置修饰符 #
  • val 的类型为 void * ,将使用转换说明符 % p
  • 窄字符串的创建方式类似于在 "C" 区域设置中调用 std:: printf ( spec, val ) ,其中 spec 为选定的转换说明符。

阶段 2:本地化特定转换

阶段 3:填充

  • 调整标志位的获取方式为 std :: fmtflags adjustfield = ( flags & ( std:: ios_base :: adjustfield ) ) ,并通过以下规则确定填充位置:
  • str. width ( ) 非零(例如刚使用过 std::setw )且阶段2后的 CharT 字符数小于 str. width ( ) ,则会在填充位置插入 fill 字符的副本,使序列长度达到 str. width ( )

在任何情况下,都会调用 str. width ( 0 ) 来取消 std::setw 的效果。

阶段 4:输出

从阶段3的 CharT 字符序列中,每个连续的字符 c 都会通过 * out ++ = c 的方式输出。

参数

out - 指向待覆写首字符的迭代器
str - 用于获取格式化信息的流
fill - 当结果需要填充至字段宽度时使用的填充字符
val - 待转换为字符串并输出的值

返回值

out

注释

由转换说明符 #o 生成的前导零(例如由 std::showbase std::oct 组合产生)不计作填充字符。

当以十六进制浮点格式格式化浮点数值时(即当 floatfield == ( std:: ios_base :: fixed | std:: ios_base :: scientific ) ),流对象的精度设置不会被使用;取而代之的是,数值总是以能够精确表示该值所需的足够精度进行输出。

(since C++11)

示例

直接使用facet输出数字,并演示用户自定义facet:

#include <iostream>
#include <locale>
// this custom num_put outputs squares of all integers (except long long)
struct squaring_num_put : std::num_put<char>
{
    iter_type do_put(iter_type out, std::ios_base& str,
                     char_type fill, long val) const
    {
        return std::num_put<char>::do_put(out, str, fill, val * val);
    }
    iter_type do_put(iter_type out, std::ios_base& str,
                     char_type fill, unsigned long val) const
    {
        return std::num_put<char>::do_put(out, str, fill, val * val);
    }
};
int main()
{
    auto& facet = std::use_facet<std::num_put<char>>(std::locale());
    facet.put(std::cout, std::cout, '0', 2.71);
    std::cout << '\n';
    std::cout.imbue(std::locale(std::cout.getloc(), new squaring_num_put));
    std::cout << 6 << ' ' << -12 << '\n';
}

输出:

2.71
36 144

用户自定义类型的 operator<< 实现。

#include <iostream>
#include <iterator>
#include <locale>
struct base { long x = 10; };
template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>&
    operator<<(std::basic_ostream<CharT, Traits>& os, const base& b)
{
    try
    {
        typename std::basic_ostream<CharT, Traits>::sentry s(os);
        if (s)
        {
            std::ostreambuf_iterator<CharT, Traits> it(os);
            std::use_facet<std::num_put<CharT>>(os.getloc())
                .put(it, os, os.fill(), b.x);
        }
    }
    catch (...)
    {
        // set badbit on os and rethrow if required
    }
    return os;
}
int main()
{
    base b;
    std::cout << b;
}

输出:

10

缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的C++标准。

缺陷报告 应用于 发布时的行为 正确行为
LWG 34 C++98 bool 重载使用了不存在的成员
truename falsename (属于 std::ctype
改用这些成员
(属于 std::numpunct
LWG 231 C++98 精度修饰符仅在
( flags & fixed ) ! = 0 str. precision ( ) > 0 时添加
移除这些条件
LWG 282 C++98 千位分隔符仅在阶段2中
为整型插入
同时为
浮点类型插入
LWG 4084 C++11 "NAN" "INF" 无法输出 可以输出

参见

插入格式化数据
( std::basic_ostream<CharT,Traits> 的公开成员函数)