C++のマニピュレータ

C++のマニピュレータ
===================

## マニピュレータとは
C++のストリームの形式を変えるための関数などのことをいいます。

マニピュレータはいくつかのヘッダに分かれています。
確認できただけではios, iomanipヘッダに分かれています。

## 一覧
名前空間のstdは省略して記します。

| 名前 | ヘッダ | no-があるか | 動作 |
|:----:|:------:|:-----------:|:-----|
| resetiosflags | &lt;iomanip&gt; | No | 引数で指定したフラグをリセットする(reset ios flags) |
| setiosflags | &lt;iomanip&gt; | No | 引数で指定したフラグをセットする |
| setbase | &lt;iomanip&gt; | No | 基数を設定する。8, 10, 16以外の値が来た場合フラグはリセットされる |
| setfill | &lt;iomanip&gt; | No | 埋める文字を指定する |
| setw | &lt;iomanip&gt; | No | フィールドの幅を指定する |
| put_money | &lt;iomanip&gt; | No | 金額書式で出力する (get_moneyもある。C++11以降)|
| put_time | &lt;iomanip&gt; | No | 日時書式で出力する (get_timeもある。C++11以降)|
| dec | &lt;ios&gt; | No | 10進数で表示する |
| oct | &lt;ios&gt; | No | 8進数で表示する |
| hex | &lt;ios&gt; | No | 16進数で表示する |
| boolalpha | &lt;ios&gt; | Yes | bool値をtrue, falseで表示させる |
| showbase | &lt;ios&gt; | Yes | 基数を示すプレフィックス(0xなど)を表示させる |
| showpoint | &lt;ios&gt; | Yes | 浮動小数点を表示させる |
| showpos | &lt;ios&gt; | Yes | 正符号を表示させる(1を+1) |
| skipws | &lt;ios&gt; | Yes | 入力時に空白を読み飛ばす |
| uppercase | &lt;ios&gt; | Yes | 大文字で表示させる(std::hexなどと一緒に使われる) |
| unitbuf | &lt;ios&gt; | Yes | 出力の都度吐き出す |
| internal | &lt;ios&gt; | No | 両端揃え |
| left | &lt;ios&gt; | No | 左揃え |
| right | &lt;ios&gt; | No | 右揃え |
| fixed | &lt;ios&gt; | No | 小数表記で出力(1.2とか) |
| scientific | &lt;ios&gt; | No | 指数表記で出力 |
| hexfloat | &lt;ios&gt; | No | 16進数の小数表記(C++11以降) |
| defaultfloat | &lt;ios&gt; | No | 小数表記と指数表記の自動切り替え(C++11以降) |

## 実行してみた
```c++:manip.cpp
#include <iomanip>
#include <iostream>

int main() {
    std::cout << "resetiosflags(floatfield): " << std::resetiosflags(std::ios_base::floatfield) << std::endl;
    std::cout << "setiosflags(scientific): " << std::setiosflags(std::ios_base::scientific) << std::endl;
    std::cout << "setbase(8): " << std::setbase(8) << 0123 << ", " << 123 << ", " << 0x123 << std::endl;
    std::cout << "setw(5): " << std::setw(5) << 123 << std::endl;
    std::cout << "setfill('0'): " << std::setw(5) << std::setfill('0') << 123 << std::endl;
#if __cplusplus >= 201103L
    std::cout.imbue(std::locale("en_US.utf8"));
    std::cout << "put_money(300): " << std::put_money(300.) << std::endl;
    std::cout << "put_money(300, true): " << std::put_money(300., true) << std::endl;

    std::cout.imbue(std::locale("ja_JP.utf8"));
    auto tt = std::time(nullptr);
    struct tm t = {};
    ::localtime_r(&tt, &t);
    std::cout << "put_time(300): " << std::put_time(&t, "%EY(%Y)/%m/%d %H:%M:%S") << std::endl;
#else
    std::cout << "put_money and put_time is not supported in this version." << std::endl;
#endif
    std::cout << "dec: " << std::dec << 0123 << ", " << 123 << ", " << 0x123 << std::endl;
    std::cout << "oct: " << std::oct << 0123 << ", " << 123 << ", " << 0x123 << std::endl;
    std::cout << "hex: " << std::hex << 0123 << ", " << 123 << ", " << 0x123 << std::endl;
    std::cout << "boolalpha: " << std::boolalpha << true << std::endl;
    std::cout << "noboolalpha: " << std::noboolalpha << true << std::endl;
    std::cout << "showbase(hex): " << std::hex << std::showbase << 0x123 << std::endl;
    std::cout << "noshowbase(hex): " << std::hex << std::noshowbase << 0x123 << std::endl;
    std::cout << "showpoint: " << std::showpoint << 1.0 << ", " << 1.2 << std::endl;
    std::cout << "noshowpoint: " << std::noshowpoint << 1.0 << ", " << 1.2 << std::endl;
    std::cout << "uppercase: " << std::uppercase << std::hex << 0xbeef << std::endl;
    std::cout << "nouppercase: " << std::nouppercase << std::hex << 0xbeef << std::endl;
    std::cout << std::setfill('-');
    std::cout << "internal(setw(20)): " << std::setw(20) << std::internal << "abcd" << std::endl;
    std::cout << "left(setw(20)): " << std::setw(20) << std::left << "abcd" << std::endl;
    std::cout << "right(setw(20)): " << std::setw(20) << std::right << "abcd" << std::endl;
    std::cout << "fixed: " << std::fixed << 1.2 << std::endl;
    std::cout << "scientific: " << std::scientific << 1.2 << std::endl;
#if __cplusplus >= 201103L
    std::cout << "hexfloat: " << std::hexfloat << 1.2 << std::endl;
    std::cout << "defaultfloat: " << std::defaultfloat << 1.2 << ", " << 120000000.0 << std::endl;
#else
    std::cout << "hexfloat and defaultfloat is not supported in this version." << std::endl;
#endif
}
```

```shell
clang++ -std=c++11 manip.cpp
```

実行結果

```plaintext
resetiosflags(floatfield): 
setiosflags(scientific): 
setbase(8): 123, 173, 443
setw(5):   173
setfill('0'): 00173
put_money(300): 3.00
put_money(300, true): 03.00
put_time(300): 平成30年(2018)/06/12 21:07:42
dec: 83, 123, 291
oct: 123, 173, 443
hex: 53, 7b, 123
boolalpha: true
noboolalpha: 1
showbase(hex): 0x123
noshowbase(hex): 123
showpoint: 1.000000e+00, 1.200000e+00
noshowpoint: 1.000000e+00, 1.200000e+00
uppercase: B,EEF
nouppercase: b,eef
internal(setw(20)): ----------------abcd
left(setw(20)): abcd----------------
right(setw(20)): ----------------abcd
fixed: 1.200000
scientific: 1.200000e+00
hexfloat: 0x1.3333333333333p+0
defaultfloat: 1.2, 1.2e+08
```

## 感想
C++でstd::stringstreamでsprintfみたいなことをしようとするとちょっとめんどくさいけど、`put_time`とかはなんとなく便利そうだなと感じました。
一応やろうと思えばsprintf相当のことはストリームでもできそうです。

## 環境
Linux Mint 18.3(amd64)

```shell
$ clang++ --version
clang version 5.0.0-3~16.04.1 (tags/RELEASE_500/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin
```