マニピュレータとは、iostream に挿入したり、iostream から抽出したりする値で特別な効果を持つもののことです。
引数付きマニピュレータとは、 1 つ以上の追加の引数を持つマニピュレータのことです。
マニピュレータは通常の識別子であるため、マニピュレータの定義を多く行うと可能な名前を使いきってしまうので、iostream では考えられるすべての機能に対して定義されているわけではありません。マニピュレータの多くは、この章の別の箇所でメンバー関数とともに説明しています。
定義済みマニピュレータは 13 個あり、それぞれについては表 3-2 で説明します。表 3-2 で使用している文字の意味は次のとおりです。
i は long 型です。
m は int 型です。
c は char 型です。
istr は 入力ストリームです。
ostr は 出力ストリームです。
表 3-2 iostream の定義済みマニピュレータ
|
定義済みマニピュレータ |
内容 |
---|---|---|
1 |
ostr << dec, istr >> dec |
基数が 10 の整数変換を指定します。 |
2 |
ostr << endl |
復帰改行文字 ('¥n') を挿入して、ostream::flush() を呼び出します。 |
3 |
ostr << ends |
NULL ( 0 ) 文字を挿入。 strstream 使用時に利用し ます。 |
4 |
ostr << flush |
ostream::flush() を呼び出します。 |
5 |
ostr << hex, istr >> hex |
基数が 16 の整数変換を指定します。 |
6 |
ostr << oct, istr >> oct |
基数が 8 の整数変換を指定します。 |
7 |
istr >> ws |
最初に空白以外の文字が見つかるまで (この文字以降は istr に残る)、空白を取り除きます (空白を読み飛ば す)。 |
8 |
ostr << setbase(n), istr >> setbase(n) |
基数が n (0, 8, 10, 16 のみ) の整数変換を指定します。 |
9 |
ostr << setw(n), istr >> setw(n) |
ios::width(n) を呼び出します。フィールド幅を n に設定します。 |
10 |
ostr << resetiosflags(i), istr >> resetiosflags(i) |
i のビットセットに従って、フラグのビットベクトルをクリアします。 |
11 |
ostr << setiosflags(i), istr >> setiosflags(i) |
i のビットセットに従って、フラグのビットベクトルを設定します。 |
12 |
ostr << setfill(c), istr >> setfill(c) |
埋め込み文字 (フィールドのパディング用文字) を c とし ます。 |
13 |
ostr << setprecision(n), istr >> setprecision(n) |
浮動小数点型データの精度を n 桁にします。 |
定義済みマニピュレータを使用するには、プログラムにヘッダーファイル iomanip.h をインクルードする必要があります。
ユーザーが独自のマニピュレータを定義することもできます。マニピュレータには次の 2 つの基本タイプがあります。
引数なしのマニピュレータ
istream&、ostream&、ios& のどれかを引数として受け取り、ストリームの操作が終わるとその引数を返します。
引数付きのマニピュレータ
istream&、ostream&、ios& のどれかと、その他もう 1 つの引数 (追加の引数) を受け取り、ストリームの操作が終わるとストリーム引数を返します。
以下に、それぞれのタイプのマニピュレータの例を示します。
引数なしのマニピュレータは、次の 3 つを実行する関数です。
ストリームの参照引数を受け取ります。
そのストリームに何らかの処理を行います。
その引数を返します。
iostream では、このような関数 (へのポインタ) を使用するシフト演算子がすでに定義されていますので、関数を入出力演算子シーケンスの中に入れることができます。シフト演算子は、値の入出力を行う代わりに、その関数を呼び出します。tab を ostream に挿入する tab マニピュレータの例を示します。
ostream& tab(ostream& os) { return os << '¥t' ; } ... cout << x << tab << y ;
次のコードは、上の例と同じ処理をより洗練された方法で行います。
const char tab = '¥t'; ... cout << x << tab << y;
次に示すのは別の例で、定数を使用してこれと同じことを簡単に実行することはできません。入力ストリームに対して、空白の読み飛ばしのオン、オフを設定したいと仮定します。ios::setf と ios::unsetf を別々に呼び出して、skipws フラグをオンまたはオフに設定することもできますが、次の例のように 2 つのマニピュレータを定義して設定することもできます。
#include <iostream.h> #include <iomanip.h> istream& skipon(istream &is) { is.setf(ios::skipws, ios::skipws); return is; } istream& skipoff(istream& is) { is.unsetf(ios::skipws); return is; } ... int main () { int x,y; cin >> skipon >> x >> skipoff >> y; return 1; }
iomanip.h に入っているマニピュレータの 1 つに setfill があります。setfill は、フィールド幅に詰め合わせる文字を設定するマニピュレータで、次の例に示すように定義されています。
//ファイル setfill.cc #include<iostream.h> #include<iomanip.h> //非公開のマニピュレータ static ios& sfill(ios& i, int f) { i.fill(f); return i; } //公開の適用子 smanip_int setfill(int f) { return smanip_int(sfill, f); }
引数付きマニピュレータは、2 つの部分から構成されます。
1 つはマニピュレータ部分で、これは引数を 1 つ追加します。この前の例では、int 型の第 2 引数があります。このような関数に対するシフト演算子は定義されていませんので、このマニピュレータ関数を入出力演算子シーケンスに入れることはできません。そこで、マニピュレータの代わりに補助関数 (適用子) を使用する必要があります。
もう 1 つは適用子で、これはマニピュレータを呼び出します。適用子は大域関数で、そのプロトタイプをヘッダーファイルに入れておきます。マニピュレータは通常、適用子の入っているソースコードファイル内に静的関数として作成します。マニピュレータは適用子からのみ呼び出されるので、静的関数にして、大域アドレス空間にマニピュレータ関数名を入れないようにします。
ヘッダーファイル iomanip.h には、さまざまなクラスが定義されています。各クラスには、マニピュレータ関数のアドレスと 1 つの引数の値が入っています。iomanip クラスについては、manip(3C++) のマニュアルページで説明しています。この前の例では、 smanip_int クラスを使用しており、ios で使用できます。ios で使用できるということは、 istream と ostream でも使用できるということです。この例ではまた、int 型の第 2 引数を使用しています。
適用子は、クラスオブジェクトを作成してそれを返します。この前の例では、smanip_int というクラスオブジェクトが作成され、そこにマニピュレータと、適用子の int 型引数が入っています。ヘッダーファイル iomanip.h では、このクラスに対するシフト演算子が定義されています。入出力演算子シーケンスの中に適用子関数 setfill があると、その適用子関数が呼び出され、クラスが返されます。シフト演算子はそのクラスに対して働き、クラス内に入っている引数値を使用してマニピュレータ関数が呼び出されます。
下記の例では、マニピュレータ print_hex は次のことを行います。
出力ストリームを 16 進モードにします。
long 型の値をストリームに挿入します。
ストリームの変換モードを元に戻します。
この例は出力専用のため、omanip_long クラスが使用されています。また、int 型でなく long 型でデータを操作します。
#include <iostream.h> #include <iomanip.h> static ostream& xfield(ostream& os, long v) { long save = os.setf(ios::hex, ios::basefield); os << v; os.setf(save, ios::basefield); return os; } omanip_long print_hex(long v) { return omanip_long(xfield, v); }