| C++ ライブラリ・リファレンス |
第 3 章
従来型のiostreamライブラリC++ も C と同様に組み込み型の入出力文はありません。その代わりに、入出力機能はライブラリで提供されています。Sun WorkShop 6 C++ コンパイラでは
iostreamクラスに対して、従来型の実装と ISO 標準の実装を両方とも提供しています。
- 互換モード (
-compat[=4]) では、従来型のiostreamクラスはlibCに含まれています。- 標準モード (デフォルトのモード) では、従来型の
iostreamクラスはlibiostreamに含まれています。従来型のiostreamクラスを使用したソースコードを標準モードでコンパイルするときは、libiostreamを使用します。従来型のiostreamの機能を標準モードで使用するには、iostream.hヘッダーファイルをインクルードし、-library=iostreamオプションを使用してコンパイルします。- 標準の
iostreamクラスは標準モードだけで使用でき、C++ 標準ライブラリlibCstdに含まれています。この章では、従来型の
iostreamライブラリの概要と使用例を説明します。この章では、iostreamライブラリを完全に説明しているわけではありません。詳細は、iostreamライブラリのマニュアルページを参照してください。従来型のiostreamのマニュアルページを表示するには、次のように入力します (name にはマニュアルページのトピック名を入力)。
example%man -s 3CC4name定義済みの
iostream定義済み
iostreamsは、cerrを除いて完全にバッファリングされています。「iostream を使用した出力」と 「iostream を使用した入力」を参照してください。
iostream操作の基本構造
iostreamライブラリを使用すると、プログラムで必要な数の入出力ストリームを使用することができます。それぞれのストリームは、次のどれかを入力先または出力先とします。ストリームは、入力のみまたは出力のみと制限して使用することも、入出力両方に使用することもできます。
iostreamライブラリでは、次の 2 つの処理階層を使用してこのようなストリームを実現しています。
- 下層では、単なる文字ストリームであるシーケンスを実現します。シーケンスは、
streambufクラスか、その派生クラスで実現されています。- 上層では、シーケンスに対してフォーマット操作を行います。フォーマット操作は
istreamとostreamの 2 つのクラスで実現されます。これらのクラスはメンバーにstreambufクラスから派生したオブジェクトを持っています。この他に、入出力両方が実行されるストリームに対してはiostreamクラスがあります。標準入力、標準出力、標準エラーは、
istreamまたはostreamから派生した特殊な
クラスオブジェクトで処理されます。
ifstream、ofstream、fstreamの 3 つのクラスはそれぞれistream、ostream、iostreamから派生しており、ファイルへの入出力を処理します。
istrstream、ostrstream、strstreamの 3 つのクラスはそれぞれistream、ostream、iostreamから派生しており、文字型配列への入出力を処理します。入力ストリームまたは出力ストリームをオープンする場合は、どれかの型のオブジェクトを生成し、そのストリームのメンバー
streambufをデバイスまたはファイルに関連付けます。通常、関連付けはストリームコンストラクタで行うので、ユーザーが直接streambufを操作することはありません。 標準入力、標準出力、エラー出力に対しては、iostreamライブラリであらかじめストリームオブジェクトを定義してあるので、これらのストリームについてはユーザーが独自にオブジェクトを生成する必要はありません。ストリームへのデータの挿入 (出力)、ストリームからのデータの抽出 (入力)、挿入または抽出したデータのフォーマット制御には、演算子または
iostreamのメンバー関数を使用します。新たなデータ型 (ユーザー定義のクラス) を挿入したり抽出したりするときは一般に、挿入演算子と抽出演算子の多重定義をユーザーが行います。
従来型の
iostreamライブラリの使用従来型の
iostreamライブラリルーチンを使用するには、ライブラリの使用部分に対応するヘッダーファイルをインクルードしなければなりません。次の表で各ヘッダーファイルについて説明します。
これらのヘッダーファイルすべてをプログラムにインクルードする必要はありません。自分のプログラムで必要な宣言の入ったものだけをインクルードします。互換モード (
-compat[=4]) では、従来型のiostreamライブラリはlibCの一部であり、CCドライバによって自動的にリンクされます。標準モード (デフォルトのモード) では、従来型のiostreamライブラリはlibiostreamに含まれています。
iostreamを使用した出力
iostreamを使用した出力は、通常、左シフト演算子 (<<) を多重定義したもの (iostreamの文脈では挿入演算子といいます) を使用します。ある値を標準出力に出力するには、その値を定義済みの出力ストリームcoutに挿入します。たとえばsomeValueを出力するには、次の文を標準出力に挿入します。
cout << someValue;挿入演算子は、すべての組み込み型について多重定義されており、
someValueの値は適当な出力形式に変換されます。たとえばsomeValueがfloat型の場合、<<演算子はその値を数字と小数点の組み合わせに変換します。float型の値を出力ストリームに挿入するときは、<<をfloat型挿入子といいます。一般にX型の値を出力ストリームに挿入するときは、<<をX型挿入子といいます。出力形式とその制御方法については、ios(3CC4) のマニュアルページを参照してください。
iostreamライブラリでは、ユーザー定義型については検知しません。したがってユーザー定義型を出力したい場合は、ユーザーが自分で挿入子を正しく定義する、すなわち<<演算子を多重定義する必要があります。
<<演算子は反復使用することができます。2 つの値をcoutに挿入するには、次の例のような文を使用することができます。
cout << someValue << anotherValue;上の例では、2 つの値の間に空白が入りません。空白を入れたい場合は、次のようにします。
cout << someValue << " " << anotherValue;<< 演算子は、組み込みの左シフト演算子と同じ優先順位を持ちます。他の演算子と同様に、括弧を使用して実行順序を指定することができます。実行順序をはっきりさせるためにも、括弧を使用するとよい場合がよくあります。次の 4 つの文のうち、最初の 2 つは同じ結果になりますが、後の 2 つは異なります。
cout << a+b; // + は << より優先順位が高いcout << (a+b);cout << (a&y); // << は & より優先順位が高いcout << a&y; // (cout <<a) & y となっておそらくエラーになるユーザー定義の挿入演算子
次のコーディング例では
stringクラスを定義しています。
この例では、挿入演算子と抽出演算子をフレンド定義しておく必要があります。
stringクラスのデータ部が非公開だからです。
ostream& operator<< (ostream& ostr, const string& output){ return ostr << output.data;}
上は、stringクラスに対して多重定義された演算子関数operator<<の定義です。
cout << string1 << string2;
operator<<は、最初の引数としてostream&(ostreamへの参照) を受け取り、同じostreamを返します。このため、次のように 1 つの文で挿入演算子を続けて使用することができます。出力エラーの処理
operator<<を多重定義するときは、iostreamライブラリからエラーが通知されることになるため、特にエラー検査を行う必要はありません。エラーが起こると、エラーの起こった
iostreamはエラー状態になります。そのiostreamの状態の各ビットが、エラーの大きな分類に従ってセットされます。iostreamで定義された挿入子がストリームにデータを挿入しようとしても、そのストリームがエラー状態の場合はデータが挿入されず、そのストリームの状態も変わりません。一般的なエラー処理方法は、メインのどこかで定期的に出力ストリームの状態を検査する方法です。そこで、エラーが起こっていることが分かれば、何らかの処理を行います。この章では、文字列を出力してプログラムを中止させる関数
errorをユーザーが定義しているものとして説明します。関数errorはユーザー定義の関数で、定義済みの関数ではありません。関数errorの内容については、 「入力エラーの処理」を参照してください。iostreamの状態を調べるには、演算子!を使用します。次の例に示すように、iostreamがエラー状態の場合はゼロ以外の値を返します。
if (!cout) error( "output error");エラーを調べるにはもう 1 つの方法があります。
iosクラスでは、operatorvoid*()が定義されており、エラーが起こった場合は NULL ポインタを返します。したがって、次の文でエラーを検査することができます。
if (cout << x) return ; //正常終了のときのみ返すまた、次のように
iosクラスのメンバー関数goodを使用することもできます。
if ( cout.good() ) return ; //正常終了のときのみ返す
enum io_state { goodbit=0, eofbit=1, failbit=2,badbit=4, hardfail=0x80} ;エラー関数の詳細については、
iostreamのマニュアルページを参照してください。出力のフラッシュ
多くの入出力ライブラリと同様、
iostreamも出力データを蓄積し、より大きなブロックにまとめて効率よく出力します。出力バッファをフラッシュしたければ、次のように特殊な値flushを挿入するだけで、フラッシュすることができます。
cout << "This needs to get out immediately." << flush ;
flushは、マニピュレータと呼ばれるタイプのオブジェクトの 1 つです。マニピュレータをiostreamに挿入すると、その値が出力されるのではなく、何らかの効果が引き起こされます。マニピュレータは実際には関数で、ostream&またはistream&を引数として受け取り、そのストリームに対する何らかの動作を実行した後にその引数を返します (「マニピュレータ」を参照してください)。バイナリ出力
ある値をバイナリ形式のままで出力するには、次の例のようにメンバー関数
writeを使用します。次の例では、xの値がバイナリ形式のまま出力されます。
cout.write((char*)&x, sizeof(x));この例では、
&xをchar*に変換しており、型変換の規則に反します。通常このようにしても問題はありませんが、xの型が、ポインタ、仮想メンバー関数、またはコンストラクタの重要な動作を要求するものを持つクラスの場合、上の例で出力した値を正しく読み込むことができません。
iostreamを使用した入力
iostreamを使用した入力は、iostreamを使用した出力と同じです。入力には、抽出演算子>>を使用します。次の例のように、挿入演算子と同様に繰り返し指定することができます。
cin >> a >> b ;この例では、標準入力から 2 つの値が取り出されます。他の多重定義演算子と同様に、使用される抽出子の機能は
aとbの型によって決まります (aとbの型が異なれば、別の抽出子が使用されます)。入力データのフォーマットとその制御方法についての詳細は、ios(3CC4) のマニュアルページを参照してください。通常は、先頭の空白文字 (スペース、改行、タブ、フォームフィードなど) は無視されます。ユーザー定義の抽出演算子
ユーザーが新たに定義した型のデータを入力するには、出力のために挿入演算子を多重定義したのと同様に、その型に対する抽出演算子を多重定義します。
クラス
stringの抽出演算子は次のコーディング例のように定義します。
コード例 3-1 stringの抽出演算子
istream& operator>> (istream& istr, string& input){const int maxline = 256;char holder[maxline];istr.get(holder, maxline, '\n');input = holder;return istr;}
get関数は、入力ストリームistrから文字列を読み取ります。読み取られた文字列は、maxline-1バイトの文字が読み込まれる、新しい行に達する、EOF に達する、のうちのいずれかが発生するまで、holderに格納されます。データholderは NULL で終わります。最後に、holder内の文字列がターゲットの文字列にコピーされます。規則に従って、抽出子は第 1 引数 (上の例では
istream&istr) から取り出した文字列を変換し、常に参照引数である第 2 引数に格納し、第 1 引数を返します。抽出子とは、入力値を第 2 引数に格納するためのものなので、第 2 引数は必ず参照引数でなければなりません。
char*の抽出子この定義済み抽出子は問題が起こる可能性があるため、ここで説明しておきます。この抽出子は次のように使用します。
char x[50];cin >> x;上の例で、抽出子は先頭の空白を読み飛ばし、次の空白文字までの文字列を抽出して
xにコピーします。次に、文字列の最後を示す NULL 文字 (0) を入れて文字列を完成します。ここで、入力文字列が指定した配列からあふれる可能性があることに注意してください。さらに、ポインタが、割り当てられた記憶領域を指していることを確認する必要があります。次に示すのは、よく発生するエラーの例です。
char * p;// 初期化されていないcin >> p;入力データが格納される場所が特定されていません。これによって、プログラムが異常終了することがあります。
1 文字の読み込み
char型の抽出子を使用することに加えて、次に示すいずれかの形式でメンバー関数getを使用することによって、1 文字を読み取ることができます。
char c;cin.get(c); // 入力に失敗した場合は、c は変更なしint b;b = cin.get(); // 入力に失敗した場合は、b を EOF に設定
注 - 他の抽出子とは異なり、char型の抽出子は行頭の空白を読み飛ばしません。
空白だけを読み飛ばして、タブや改行などその他の文字を取り出すようにするには、次のようにします。
int a;do {a = cin.get();while( a == ' ' );バイナリ入力
メンバー関数
writeで出力したようなバイナリの値を読み込むには、メンバー関数readを使用します。次の例では、メンバー関数readを使用してxのバイナリ形式の値をそのまま入力します。次の例は、先に示した関数writeを使用した例と反対のことを行います。
cin.read((char*)&x, sizeof(x));入力データの先読み
メンバー関数
peekを使用するとストリームから次の文字を抽出することなく、その文字を知ることができます。使用例を次に示します。
if (cin.peek() != c) return 0;空白の抽出
デフォルトでは、
iostreamの抽出子は先頭の空白を読み飛ばします。skipフラグをオフにすれば、先頭の空白を読み飛ばさないようにすることができます。次の例では、cinの先頭の空白の読み飛ばしをいったんオフにし、後にオンに戻しています。
cin.unsetf(ios::skipws); //先頭の空白の読み飛ばしをオフに設定. . .cin.setf(ios::skipws); //先頭の空白の読み飛ばしをオンに再設定
iostreamのマニピュレータwsを使用すると、空白の読み飛ばしが現在オンかオフかに関係なく、iostreamから先頭の空白を取り除くことができます。次の例では、iostream istrから先頭の空白が取り除かれます。
istr >> ws;入力エラーの処理
通常は、第 1 引数が非ゼロのエラー状態にある場合、抽出子は入力ストリームからのデータの抽出とエラービットのクリアを行わないでください。データの抽出に失敗した場合、抽出子は最低 1 つのエラービットを設定します。
出力エラーの場合と同様、エラー状態を定期的に検査し、非ゼロの状態の場合は処理の中止など何らかの動作を起こす必要があります。演算子
!は、iostreamのエラー状態を検査します。たとえば次のコーディング例では、英字を入力すると入力エラーが発生します。
クラス
iosには、エラー処理に使用できるメンバー関数があります。詳細はマニュアルページを参照してください。
iostreamとstdioの併用C++ でも
stdioを使用することができますが、プログラムでiostreamとstdioとを標準ストリームとして併用すると、問題が起こる場合があります。たとえばstdoutとcoutの両方に書き込んだ場合、個別にバッファリングされるため出力結果が設計したとおりにならないことがあります。stdinとcinの両方から入力した場合、問題はさらに深刻です。個別にバッファリングされるため、入力データが使用できなくなってしまいます。標準入力、標準出力、標準エラーに関するこのような問題を解決するためには、入出力に先立って次の命令を実行します。次の命令で、すべての定義済み
iostreamが、それぞれ対応する定義済みの標準入出力のFILEに結合されます。
ios::sync_with_stdio();このような結合を行うと、定義済みストリームが結合されたものの一部となってバッファリングされなくなってかなり効率が悪くなるため、デフォルトでは結合されていません。同じプログラムでも、
stdioとiostreamを別のファイルに対して使用することはできます。すなわち、stdioルーチンを使用してstdoutに書き込み、iostreamに結合した別のファイルに書き込むことは可能です。またstdio FILEを入力用にオープンしても、stdinから入力しない限りはcinからも読み込むことができます。
iostreamの作成定義済みの
iostream以外のストリームへの入出力を行いたい場合は、ユーザーが自分でiostreamを生成する必要があります。これは一般には、iostreamライブラリで定義されている型のオブジェクトを生成することになります。ここでは、使用できるさまざまな型について説明します。クラス
fstreamを使用したファイル操作ファイル操作は標準入出力の操作に似ています。
ifstream、ofstream、fstreamの 3 つのクラスはそれぞれ、istream、ostream、iostreamの各クラスから派生しています。この 3 つのクラスは派生クラスなので、挿入演算と抽出演算、および、その他のメンバー関数を継承しており、ファイル使用のためのメンバーとコンストラクタも持っています。
fstreamのいずれかを使用するときは、fstream.hをインクルードしなければなりません。入力だけ行うときはifstream、出力だけ行うときはofstream、入出力を行うときはfstreamを使用します。コンストラクタへの引数としてはファイル名を渡します。
thisFileというファイルからthatFileというファイルへのファイルコピーを行うときは、次のコーディング例のようになります。
fromFileというifstreamオブジェクトをデフォルトモードios::inで生成し、それをthisFileに結合します。thisFileをオープンします。- 生成した
ifstreamオブジェクトのエラー状態を調べ、エラーであれば関数errorを呼び出します。関数errorは、プログラムのどこか別のところで定義されている必要があります。toFileというofstreamオブジェクトをデフォルトモードios::outで生成し、それをthatFileに結合します。fromFileと同様に、toFileのエラー状態を検査します。- データの受け渡しに使用する
char型変数を生成します。fromFileの内容を一度に 1 文字ずつtoFileにコピーします。
注 - ファイルの内容を一度に 1 文字ずつコピーすることは実際にはあまり行われません。このコードはfstreamの使用例として示したにすぎません。実際には、入力ストリームに関係付けられたstreambufを出力ストリームに挿入するのが一般的です。「streambuf」とsbufpub(3CC4)のマニュアルページを参照してください。
オープンモード
オープンモードは、列挙型
open_modeの各ビットのORをとって設定します。open_modeは、iosクラスの公開部で次のように定義されています。
enum open_mode {binary=0, in=1, out=2, ate=4, app=8, trunc=0x10,nocreate=0x20, noreplace=0x40};
注 - UNIX ではbinaryフラグは必要ありませんが、binaryフラグを必要とするシステムとの互換性を保つために提供されています。移植可能なコードにするためには、バイナリファイルをオープンするときにbinaryフラグを使用する必要があります。
入出力両用のファイルをオープンすることができます。たとえば次のコードでは、
someNameという入出力ファイルをオープンして、fstream変数inoutFileに結合します。
fstream inoutFile("someName", ios::in|ios::out);ファイルを指定しない
fstreamの宣言ファイルを指定せずに
fstreamの宣言だけを行い、後にファイルをオープンすることもできます。次の例では出力用のofstream toFileを作成します。
ofstream toFile;toFile.open(argv[1], ios::out);ファイルのオープンとクローズ
fstreamをいったんクローズし、また別のファイルでオープンすることができます。たとえば、コマンド行で与えられるファイルリストを処理するには次のようにします。
ifstream infile;for (char** f = &argv[1]; *f; ++f) {infile.open(*f, ios::in);...;infile.close();}ファイル記述子を使用したファイルのオープン
標準出力は整数
1などのようにファイル記述子が分かっている場合は、次のようにファイルをオープンすることができます。
ofstream outfile;outfile.attach(1);
fstreamのコンストラクタにファイル名を指定してオープンしたり、open関数を使用してオープンしたファイルは、fstreamが破壊された時点 (deleteするか、スコープ外に出る時点) で自動的にクローズされます。attachでfstreamに結合したファイルは、自動的にはクローズされません。ファイル内の位置の再設定
ファイル内の読み込み位置と書き込み位置を変更することができます。そのためには次のようなツールがあります。
streamposは、iostream内の位置を記憶しておくためのデータ型です。tellg(tellp)はistream(ostream)のメンバー関数で、現在のファイル内の位置を返します。istreamとostreamはfstreamの親クラスですので、tellgとtellpもfstreamクラスのメンバー関数として呼び出すことができます。seekg(seekp)はistream(ostream)のメンバー関数で、指定したファイル内の位置を探し出します。- 列挙型
seek_dirは、seekでの相対位置を指定します。
enumseek_dir{ beg=0, cur=1, end=2 }
fstream aFileの位置再設定の例を次に示します。
streamposoriginal=aFile.tellp();// 現在の位置の保存aFile.seekp(0, ios::end);// ファイルの最後に位置を再設定aFile << x;// データをファイルに書き込むaFile.seekp(original);// 元の位置に戻る
seekg(seekp)は、1 つまたは 2 つの引数を受け取ります。引数を 2 つ受け取るときは、第 1 引数は、第 2 引数で指定したseek_dir値が示す位置からの相対位置となります。次に例を示します。この例では、ファイルの最後から 10 バイトの位置に設定されます。
aFile.seekp(-10, ios::end);
aFile.seekp(10, ios::cur);
注 - テキストストリーム上での任意位置へのシーク動作はマシン依存になります。ただし、以前に保存したstreamposの値にいつでも戻ることができます。
iostreamの代入
iostreamでは、あるストリームを別のストリームに代入することはできません。ストリームオブジェクトをコピーすると、出力ファイル内の現在の書き込み位置ポインタなどの位置情報が二重に存在するようになり、それを個別に変更できるという状態が起こります。これは、ストリーム操作を混乱させる可能性があります。
フォーマットの制御
フォーマットの制御については、
ios(3CC4)のマニュアルページで詳しく説明しています。マニピュレータ
マニピュレータとは
、iostreamに挿入したり、iostreamから抽出したりする値で特別な効果を持つもののことです。引数付きマニピュレータとは、 1 つ以上の追加の引数を持つマニピュレータのことです。
マニピュレータは通常の識別子であるため、マニピュレータの定義を多く行うと可能な名前を使いきってしまうので、
iostreamでは考えられるすべての機能に対して定義されているわけではありません。マニピュレータの多くは、この章の別の箇所でメンバー関数とともに説明しています。定義済みマニピュレータは 13 個あり、それぞれについては 表 3-2「iostream の定義済みマニピュレータ」 で説明します。表 3-2 で使用している文字の意味は次のとおりです。
iはlong型です。mはint型です。cはchar型です。istrは 入力ストリームです。ostrは 出力ストリームです。
定義済みマニピュレータを使用するには、プログラムにヘッダーファイル
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 つのマニピュレータを定義して設定することもできます。
引数付きのマニピュレータの使用法
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);}1 つはマニピュレータ部分で、これは引数を 1 つ追加します。この前の例では、
int型の第 2 引数があります。このような関数に対するシフト演算子は定義されていませんので、このマニピュレータ関数を入出力演算子シーケンスに入れることはできません。そこで、マニピュレータの代わりに補助関数 (適用子) を使用する必要があります。もう 1 つは適用子で、これはマニピュレータを呼び出します。適用子は大域関数で、そのプロトタイプをヘッダーファイルに入れておきます。マニピュレータは通常、適用子の入っているソースコードファイル内に静的関数として作成します。マニピュレータは適用子からのみ呼び出されるので、静的関数にして、大域アドレス空間にマニピュレータ関数名を入れないようにします。
ヘッダーファイル
iomanip.hには、さまざまなクラスが定義されています。各クラスには、マニピュレータ関数のアドレスと 1 つの引数の値が入っています。iomanipクラスについては、manip(3CC4)のマニュアルページで説明しています。この前の例では、smanip_intクラスを使用しており、iosで使用できます。iosで使用できるということは、istreamとostreamでも使用できるということです。この例ではまた、int型の第 2 引数を使用しています。適用子は、クラスオブジェクトを作成してそれを返します。この前の例では、
smanip_intというクラスオブジェクトが作成され、そこにマニピュレータと、適用子のint型引数が入っています。ヘッダーファイルiomanip.hでは、このクラスに対するシフト演算子が定義されています。入出力演算子シーケンスの中に適用子関数setfillがあると、その適用子関数が呼び出され、クラスが返されます。シフト演算子はそのクラスに対して働き、クラス内に入っている引数値を使用してマニピュレータ関数が呼び出されます。次の例では、マニピュレータ
print_hexは以下のことを行います。この例は出力専用のため、
omanip_longクラスが使用されています。また、int型でなくlong型でデータを操作します。
strstream:配列用のiostream
strstream(3CC4)のマニュアルページを参照してください。
stdiobuf: 標準入出力ファイル 用のiostream
stdiobuf(3CC4)のマニュアルページを参照してください。
streambuf入力や出力のシステムは、フォーマットを行う
iostreamと、フォーマットなしの文字ストリームの入力または出力を行うstreambufからなります。通常は
iostreamを通してstreambufを使用するので、streambufの詳細を知る必要はありません。ただし、効率をよくするため、またはiostreamに組み込まれているエラー処理やフォーマットのためなどに必要な場合は、直接streambufを使用することができます。
streambufの機能
streambufは文字シーケンス (文字ストリーム) と、シーケンス内を指す 1 つまたは 2 つのポインタとで構成されています。各ポインタは文字と文字の間を指しています。実際には文字と文字の間を指しているわけではありませんが、このように考えておくと理解しやすくなります。streambufポインタには次の種類があります。
streambufは、このどちらかのポインタ、または両方のポインタを持ちます。ポインタの位置
ポインタ位置の操作とシーケンスの内容の操作にはさまざまな方法があります。文字列の操作時に両方のポインタが移動するかどうかは、使用される
streambufの種類によって違います。一般に、キュー形式のstreambufの場合は、get ポインタと put ポインタは別々に移動し、ファイル形式のstreambufの場合は、get ポインタと put ポインタは同時に移動します。キュー形式ストリームの例としてはstrstreamがあり、ファイル形式ストリームの例としてはfstreamがあります。
streambufの使用ユーザーは
streambufオブジェクト自体を作成することはなく、streambufクラスから派生したクラスのオブジェクトを作成します。その例として、filebufとstrstreambufとがあります。この 2 つについてはそれぞれfilebuf(3CC4)およびssbuf(3CC4)のマニュアルページを参照してください。より高度な使い方として、独自のクラスをstreambufから派生させて特殊デバイスのインタフェースを提供したり、基本的なバッファリング以外のバッファリングを行なったりすることができます。sbufpub(3CC4)とsbufprot(3CC4)のマニュアルページでは、それらの方法について説明しています。ユーザー用の特殊な
streambufを作成するとき以外にも、上に示したマニュアルページで説明しているように、iostreamと結合したstreambufにアクセスして公開メンバー関数を使用したい場合があります。また、各iostreamには、streambufへのポインタを引数とする定義済みの挿入子と抽出子があります。streambufを挿入したり抽出したりすると、ストリーム全体がコピーされます。次の例では、先に説明したファイルコピーとは違う方法でファイルをコピーしています。簡単にするため、エラー検査は省略しています。
ifstream fromFile("thisFile");ofstream toFile ("thatFile");toFile << fromFile.rdbuf();入力ファイルと出力ファイルは、以前の例と同じ方法でオープンします。各
iostreamクラスにはメンバー関数rdbufがあり、それに結合したstreambufオブジェクトへのポインタを返します。fstreamの場合、streambufオブジェクトはfilebuf型です。fromFileに結合したファイル全体がtoFileに結合したファイルにコピー (挿入) されます。最後の行は次のように書くこともできます。
fromFile >> (streambuf*)toFile.rdbuf();上の書き方では、ソースファイルが抽出されて目的のところに入ります。どちらの書き方をしても、結果はまったく同じになります。
iostreamに関するマニュアルページC++ では、
iostreamライブラリの詳細を説明する多くのマニュアルページがあります。次に、各マニュアルページの概要を示します。従来型の
iostreamライブラリのマニュアルページを表示するには、次のように入力します (name には、マニュアルページのトピック名を入力)。
example%man -s 3CC4name
iostreamの用語
iostreamライブラリの説明では、一般のプログラミングに関する用語と同じでも意味が異なる語を多く使用します。次の表では、それらの用語がiostreamライブラリの説明で使用される場合の意味を定義します。
|
サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |