名稱空間
變體
操作

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

來自 cppreference.com
< cpp‎ | locale‎ | num put
 
 
 
 
std::num_put
成員函式
num_put::putnum_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) 將字元寫入輸出序列 out,這些字元表示 val 的值,根據格式化標誌 str.flags() 以及流 str 中所注入區域設定的 std::numpunctstd::ctype 方面(facet)所請求的格式進行格式化。所有格式化輸出流運算子都會呼叫此函式,例如 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);
  • 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(),並按 *out++ = c 將該字串的每個連續字元 c 輸出到 out。在此情況下不再進行進一步處理,函式返回 out
  • val 的型別為整數型別,則選擇以下第一個適用的選項
    • basefield == oct,將使用轉換說明符 %o
    • basefield == hex && !uppercase,將使用轉換說明符 %x
    • basefield == hex,將使用轉換說明符 %X
    • val 的型別為有符號,將使用轉換說明符 %d
    • val 的型別為無符號,將使用轉換說明符 %u
  • 對於整數型別,必要時會向轉換說明新增長度修飾符:l 用於 longunsigned longll 用於 long longunsigned 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::showbasestd::oct 組合產生)不計為填充字元。

當將浮點值格式化為十六進位制浮點(即當 floatfield == (std::ios_base::fixed | std::ios_base::scientific))時,不使用流的精度;相反,始終以足夠的精度列印數字以精確表示該值。

(C++11 起)

[編輯] 示例

使用方面(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 過載使用了不存在的成員
truenamefalsenamestd::ctype
使用這些成員
std::numpunct
LWG 231 C++98 精度修飾符僅在以下情況新增
(flags & fixed) != 0str.precision() > 0
刪除了這些條件
LWG 282 C++98 千位分隔符僅在以下情況新增
階段 2 中用於整數型別
也插入用於
浮點型別
LWG 4084 C++11 無法列印 "NAN""INF" 它們可以列印

[編輯] 另見

插入格式化資料
(std::basic_ostream<CharT,Traits> 的公有成員函式) [編輯]