Oracle® Developer Studio 12.5: C++ ユーザーズガイド

印刷ビューの終了

更新: 2016 年 7 月
 
 

13.7 マニピュレータ

マニピュレータとは、iostream に挿入したり、iostream から抽出したりする値で特別な効果があります。

引数付きマニピュレータとは、1 つ以上の追加の引数を持つマニピュレータのことです。

マニピュレータは通常の識別子であるため、マニピュレータの定義を多く行うと可能な名前を使いきってしまうので、iostream では考えられるすべての機能に対して定義されているわけではありません。マニピュレータの多くは、この章の別の箇所でメンバー関数とともに説明しています。

定義済みの 13 個のマニピュレータを次の表に示します。この表は、次のことを想定しています。

  • ilong 型です。

  • nint 型です。

  • cchar 型です。

  • istr は 入力ストリームです。

  • ostr は 入力ストリームです。

表 27  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 つの引数 (追加の引数) を取り、ストリームで処理を行い、ストリーム引数を返します。

13.7.1 引数なしのマニピュレータの使用法

引数なしのマニピュレータは、次の動作を実行する関数です。

  • ストリームの参照引数を受け取ります。

  • そのストリームに何らかの処理を行います。

  • その引数を返します。

iostream では、このような関数へのポインタを使用するシフト演算子がすでに定義されているので、関数を入出力演算子のシーケンスの中に入れることができます。シフト演算子は、値の入出力を行う代わりに、その関数を呼び出します。tabostream に挿入する tab マニピュレータの例を次に示します。

ostream& tab(ostream& os) {
             return os <<’\t’;
            }
...
cout << x << tab << y;

この例は、次のコードを得るための複雑な方法です。

const char tab = ’\t’;
...
cout << x << tab << y;

次に示すのは別の例で、定数を使用してこれと同じことを簡単に実行することはできません。入力ストリームに対して、空白の読み飛ばしのオン、オフを設定すると仮定します。ios::setfios::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;
}

13.7.2 引数付きのマニピュレータ

iomanip.h に入っているマニピュレータの 1 つに setfill があります。setfill は、フィールド幅に詰め合わせる文字を設定するマニピュレータです。このマニピュレータは次の例に示すように実装されています。

//file setfill.cc
#include<iostream.h>
#include<iomanip.h>

//the private manipulator
static ios& sfill(ios& i, int f) {
         i.fill(f);
         return i;
}
//the public applicator
smanip_int setfill(int f) {
       return smanip_int(sfill, f);
}

引数付きマニピュレータは、2 つの部分から構成されます。

  • マニピュレータ。これは引数を 1 つ追加します。この前の例では、int 型の第 2 引数があります。このような関数に対するシフト演算子は定義されていないので、このマニピュレータ関数を入出力演算子のシーケンスに入れることはできません。そこで、マニピュレータの代わりに補助関数 (適用子) を使用する必要があります。

  • 適用子。これはマニピュレータを呼び出します。適用子は大域関数で、そのプロトタイプをヘッダーファイルに入れておきます。マニピュレータは通常、適用子の入っているソースコードファイル内に静的関数として作成します。マニピュレータは適用子によってのみ呼び出されます。これを静的にした場合、その名前は大域アドレス空間の外側に保持されます。

ヘッダーファイル iomanip.h には、さまざまなクラスが定義されています。各クラスには、マニピュレータ関数のアドレスと 1 つの引数の値が入っています。iomanip クラスについては manip (3CC4) マニュアルページで説明されています。前の例では smanip_int クラスが使用され、これは ios で使用できます。ios で使用できるということは、istreamostream でも使用できるということです。この例ではまた、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);
   }