## 7.3 ストリームの書式状態による書式制御

### 7.3.1 書式パラメータ

各ストリームには、書式設定と構文解析の詳細を制御する書式状態変数が付属しています。書式状態変数はストリームの基底クラスである ios_base か basic_ios<charT,traits> から継承したクラスです。書式パラメータには、 任意の値をとるパラメータと、いくつかの限られた値から選択するパラメータがあります。

#### 7.3.1.1 任意の値をとるパラメータ

値は非公開データメンバーとして基底クラスのどれかに格納され、その設定と検索は、その基底クラスから派生した公開メンバー関数で行います。表 5 に示すように、この種のパラメータは 3 つあります。

#### 表 5 -- 任意の値の書式パラメータ

アクセス関数 | 基底クラスに定義 | 結果 | デフォルト
--- | --- | --- | ---
`width()` | ios_base | 最小フィールド幅 | 0
`precision()` | ios_base | 浮動小数点値の精度 | 6
`fill()` | basic_ios <charT,traits> | 埋め込み用の文字 | 空白文字

#### 7.3.1.2 いくつかの限られた値だけをとるパラメータ

通常は、2 つか 3 つの異なる値から選択します。これらのパラメータは、クラス ios_base の、型が`fmtflags` のデータメンバーで、1 つ以上のビットで表します。一般には書式フラグと呼びます。書式フラグは、クラス ios_base の `setf()` 関数で設定し、クリアは `unsetf()` で、検索は `flags()` 関数で行います。

書式設定フラグは、グループになっているものがあります。これは相互に排他的なためです。たとえば、出力フィールド内の出力は左詰めか右詰めにします。また、内部的に指定した位置揃えをすることもできます。対応する書式設定フラグは、 `left`、`right`、`internal` の 3 つですが、そのうちの 1 つだけを設定することができます。3 これらのビットのどれかを 1 に設定するには、残り 2 つを 0 に設定する必要があります。このことが簡単にできるように、ビットグループが用意されていて、主に、1 つのグループ内のすべてのビットをリセットする機能があります。位置揃えに使用するビットグループには `adjustfield` があり、`left | right | internal` と定義されています。

表 6 は、書式設定フラグの概要と、入出力演算子に対するその効果を示したものです (書式設定フラグの入出力演算子に対するはたらきについての詳細は、『標準 C++ クラスライブラリ・リファレンス』の ios_base を参照してください)。以下の表で、最初の列の書式設定フラグは、フラグ名です。たとえば、 `showpos` は `ios_base::showpos` を表します。グループは、相互に排他的なフラグのグループ名です。3 番目の列は、それらのフラグを設定したときの効果を簡単に説明しています。stdio の列は、同等または似た機能を持つ C 関数 `scanf()` や `printf()` の使用する書式設定文字を表します。最後のデフォルトの列には、フラグを明示的に設定しなかった場合の設定を表します。

#### 表 6 -- フラグと演算子に対するその効果

書式設定フラグ | グループ | 効果 | stdio | デフォルト
--- | --- | --- | --- | ---
| `adjustfield` | 一定の生成出力に、位置揃え用の空白詰め文字を追加します。 |  | `left` 脚注 1 参照
`left` |  | 左 | `-` |
`right` |  | 右 | `0` |
`internal` |  | 指定した内部的なポイントに文字を追加します。 | なし |
| `basefield` | 整数入力を変換したり整数出力を生成します。 | `%i` |
    dec
`dec` |  | 10 進ベース | `%d,%u` |
`oct` |  | 8 進ベース | `%o` |
`hex` |  | 16 進ベース | `%x` |
| `floatfield` | 浮動小数点出力を生成します。 | `%g,%G` |
    fixed
`fixed` |  | 固定小数点表記による | `%f` |
`scientific` |  | 科学的表記による | `%e,%E` |
`boolalpha` |  | `bool` 値をアルファベット形式で挿入します。 |  |
    0
`showpos` |  | `+` 記号を非負数の生成数値出力に生成します。 | `+` |
    0
`showpoint` |  | 浮動小数点出力で常に小数点を生成します。 | `.n` 脚注 2 参照 |
    0
`showbase` |  | 生成された整数出力の数値ベースを示す接頭辞を生成します。 | `#` |
    0
`skipws` |  | 一定の入力演算で、先頭の空白をスキップします。 | なし |
    1
`unitbuf` |  | 書式設定演算後の出力をフラッシュします。 | なし |
    0
`uppercase` |  | 生成される出力で、一定の小文字をその大文字に変換します。 | `%X` `%E` `%G` |
    0

1 | 最初は、どのビットも設定されていません。それでもほぼ left と同じことになります。
2 | ここで n は桁数を表します。

設定した書式パラメータは、基本的にはそのまま維持されます。すなわち、設定したパラメータは、明示的に変更するまで有効です。ただし、フィールド幅だけは例外です。フィールド幅を使用する入出力演算後に、幅は自動的にデフォルト値 0 にリセットされます。次に例を示します。

>     int i; char* s[11];
>     cin >> setw(10) >> i >> s;                                    //1
>     cout << setw(10) <<i << s;                                    //2

//1 | 整数の抽出は指定したフィールド幅とは無関係に行われます。整数に対して、抽出子は常に整数の全桁数を抽出します。整数の抽出では、フィールド幅の設定を使用しないため、続けて文字シーケンスを抽出するときもフィールド幅 10 はそのまま有効です。この場合は、10 文字だけが抽出されます。抽出後は、フィールド幅は 0 にリセットされます。
//2 | 整数に対する挿入子では、指定したフィールド幅を使用し、必要に応じてフィールドに空白詰め文字を追加します。挿入が終わると、フィールド幅は 0 にリセットされます。そのため、その後の文字列の挿入では、 10 文字未満の文字列に対して空白詰め文字によるフィールドの埋め込みは行われません。

> 注: フィールド幅は例外ですが、他の書式パラメータの設定はすべてそのまま維持されます。フィールド幅パラメータは使用するたびにリセットされます。

次のコード例は、パラメータを使用した書式設定の制御例を示したものです。

>     #include <iostream>
>     using namespace ::std;
>     //
>     ios_base::fmtflags original_flags = cout.flags();             //1
>     cout<< 812<<'|';
>     cout.setf(ios_base::left,ios_base::adjustfield);              //2
>     cout.width(10);                                               //3
>     cout<< 813 << 815 << '\n';
>     cout.unsetf(ios_base::adjustfield);                           //4
>     cout.precision(2);
>     cout.setf(ios_base::uppercase|ios_base::scientific);          //5
>     cout << 831.0 << ` ` << 8e2;
>     cout.flags(original_flags);                                   //6

//1 |
//2 | 位置揃えを、デフォルトの `right` から `left` に変更します。
//3 | フィールド幅を、デフォルトの `0` から `10` に変更します。フィールド幅が `0` のとき、空白詰め文字は使用されません。どの挿入操作でも、これがデフォルトの動作です。
//4 | 位置揃えフラグをクリアします。
//5 | 浮動小数点の精度を、デフォルトの `6` から `2` に変更し、さらに浮動小数点の値に関係のある残り 2 つの書式設定フラグも設定します。
//6 | 元のフラグを復元します。

出力は次のとおりです。

>     812|813       815
>     8.31E+02 8.00E+02

### 7.3.2 マニピュレータ

書式の制御では、ストリームのメンバー関数を呼び出す必要があります。この呼び出しは、個々のシフト式に割り込みます。シフト式で書式を変更する必要が発生した場合でも、入出力ストリームではそれが可能です。次のようなコードを書く代わりに

>     cout<< 812 << '|';
>     cout.setf(ios_base::left,ios_base::adjustfield);
>     cout.width(10);
>     cout<< 813 << 815 << '\n';

次のようなコードを書きます。

>     cout<< 812 << '|' << left << setw(10) << 813 << 815 << endl;

この例では、`left`、`setw`、`endl` などのオブジェクトをマニピュレータと呼びます。マニピュレータは、一定の型のオブジェクトを指します。これを、ここでは `manip` 型と呼びます。`manip` 型の `basic_istream <charT,traits>:: operator>>()` と `basic_ostream <charT,traits>:: operator<<()` には、オーバーロードバージョンがあります。そのため、マニピュレータは、シフト演算子を定義した他のオブジェクトとともに、ストリームに対する抽出や挿入を行うことができます (マニピュレータの機能と、固有のマニピュレータを実装する方法の詳細については、7.3.2 節を参照してください)。

実際にストリームに対する入出力を行うことは、マニピュレータには求められていません。ほとんどのマニピュレータが、上記の書式フラグのどれか 1 つを設定するだけです。その他のストリーム操作を行うものもあります。たとえば次の式は、

>     cout << left;

次の式と同じように機能します。

>     cout.setf (ios_base::left, ios_base::adjustfield);.

ストリームには何も挿入されていません。ただ、出力を左揃えする書式設定フラグが設定されるだけです。

一方、マニピュレータ `endl` では、ストリームに復帰改行文字が挿入され、基本ストリームバッファにフラッシュされます。次の式は、

>     cout << endl;

次の式と同じように機能します。

>     cout << '\n'; cout.flush();

`setw(int)` など、マニピュレータによっては引数を使用するものがあります。`setw` マニピュレータでは、フィールド幅を設定します。次の式は、

>     cout << setw(10);

次の式と同じようにはたらきます。

>     cout.width(10);

一般に、マニピュレータとはストリームを操作するために、ストリームに対して挿入や抽出を行うことができるオブジェクトだとみなすことができます。

マニピュレータの中には出力ストリームにだけ使用するものがあり、また入力ストリームにだけ使用するものがあります。ほとんどのマニピュレータでは、ストリーム基底クラスである ios_base か basic_ios<charT,traits> の書式ビットだけを変更します。これらは、入出力ストリームに適用することができます。

表 7 は、入出力ストリームで定義する全マニピュレータの概要です。最初の列のマニピュレータには名前を示します。マニピュレータは、すべて名前空間 `::std` に定義したクラスです。2 番目の列の用途は、マニピュレータを istreams (`i`) と ostreams (`o`) のどちらか、またはその両方 (`io`) に使用するかを指定します。3 番目の列の効果は、マニピュレータの効果を要約したものです。最後の列の等価では、ストリームのメンバー関数に対応する呼び出しを示します。

2 番目の列は、マニピュレータの本来の用途を示しているだけです。多くのクラスで、出力マニピュレータを入力ストリームに使用したり、その反対の操作をすることは可能です。一般的に、このように本来の用途と異なる操作は、実行しても無効であるという意味で害はありません。たとえば、出力マニピュレータ `showpoint` を入力ストリームに使用すると、その操作は単に無視されるだけです。ただし、入力時に出力マニピュレータを双方向ストリームに使用すると、その操作は現在の入力演算ではなく、その後の出力演算に反映されます。

#### 表 7 -- マニピュレータ1

マニピュレータ | 用途 | 効果 | 等価
--- | --- | --- | ---
`boolalpha` | `io` | `bool` 値をアルファベット形式で入力します。 | `io.setf(ios_base::boolalpha)`
`dec` | `io` | 整数と 10 進表記間の変換を行います。 | `io.setf(ios_base::dec,` `ios_base::basefield)`
`endl` | `o` | 復帰改行を挿入し、バッファをフラッシュします。 | `o.put(o.widen('\n'));` `o.flush()`
`ends` | `o` | 文字列の終わり文字を挿入します。 | `o.put(o.widen('\0'))`
`fixed` | `o` | 浮動小数点値を固定小数点値表記にします。 | `o.setf(ios_base::fixed,` `ios_base::floatfield)`
`flush` | `o` | ストリームバッファをフラッシュします。 | `o.flush()`
`hex` | `io` | 整数と 16 進表記間の変換を行います。 | `io.setf(ios_base::hex,` `ios_base::basefield)`
`internal` | `o` | 指定した内部ポイントに空白詰め文字を追加します。 | `o.setf(ios_base::internal,` `ios_base::adjustfield)`
`left` | `o` | 左揃えのために空白詰め文字を追加します。 | `o.setf(ios_base::left,` `ios_base::adjustfield)`
`noboolalpha` | `io` | 上記の設定をリセットします。 | `io.unsetf(ios_base::boolalpha)`
`noshowbase` | `o` | 上記の設定をリセットします。 | `o.unsetf (ios_base::showbase)`
`noshowpoint` | `o` | 上記の設定をリセットします。 | `o.unsetf (ios_base::showpoint)`
`noshowpos` | `o` | 上記の設定をリセットします。 | `o.unsetf (ios_base::showpos)`
`noskipws` | `i` | 上記の設定をリセットします。 | `i.unsetf(ios_base::skipws)`
`nounitbuf` | `o` | 上記の設定をリセットします。 | `o.unsetf(ios_base::unitbuf)`
`nouppercase` |  | 上記の設定をリセットします。 | `o.unsetf (ios_base::uppercase)`
`oct` | `io` | 8 進表記との変換を行います。 | `io.setf(ios_base::oct,` `ios_base::basefield)`
`resetiosflags` `(ios_base::fmt` `flags mask)` | `io` | ios フラグをクリアします。 | `io.setf((ios_base::fmtflags)` `0, mask)`
`right` | `o` | 右揃えのために空白詰め文字を追加します。 | `o.setf(ios_base::right,` `ios_base::adjustfield)`
`scientific` |  | 浮動小数点値を科学表記にします。 | `o.setf(ios_base::scientific,` `ios_base::floatfield)`
`setbase` `(int base)` | `io` | 整数表記の基底を設定します (基底 = 8, 10, 16) | `io.setf (base ==` `8?ios_base::oct: base == 10` `? ios_base::dec : base == 16` `? ios_base::hex :` `ios_base::fmtflags(0),` `ios_base::basefield)`
`setfill(charT c)` | `io` | 埋め込み用の空白詰め文字を設定します。 | `io.fill(c)`
`setiosflags` `(ios_base::fmt` `flags mask)` | `io` | ios フラグを設定します。 | `io.setf(mask)`
`setprecision` `(int n)` | `io` | 浮動小数点値の精度を設定します。 | `io.precision(n)`
`setw(int n)` | `io` | 最小フィールド幅を設定します。 | `io.width(n)`
`showbase` | `o` | 整数の数値基底を示す接頭辞を生成します。 | `o.setf(ios_base::showbase)`
`showpoint` | `o` | 常に 10 進浮動小数点値を生成します。 | `o.setf(ios_base::showpoint)`
`showpos` | `o` | 非負数値に `+` 記号を生成します。 | `o.setf(ios_base::showpos)`
`skipws` | `i` | 先頭の空白文字をスキップします。 | `i.setf(ios_base::skipws)`
`unitbuf` | `o` | 書式設定演算のたびに出力をフラッシュします。 | `o.setf(ios_base::unitbuf)`
`uppercase` | `o` | 一定の小文字をその大文字に変換します。 | `o.setf(ios_base::uppercase)`
`ws` | `i` | 空白をスキップします。 |

1 | 標準 C++ ライブラリの Rogue Wave 実装では、非標準マニピュレータも指定します。 `__lock` では、マルチスレッドに使用するためストリームをロックします。 `__unlock` では、マルチスレッドに使用するためストリームをロック解除します。

Copyright (c) 1998, Rogue Wave Software, Inc.
このマニュアルに関する誤りのご指摘やご質問は、電子メールにてお送りください。

OEM リリース, 1998 年 6 月