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 3CC4
name定義済みの
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
クラスでは、operator
void
*()
が定義されており、エラーが起こった場合は 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
での相対位置を指定します。
enum
seek_dir
{ beg=0, cur=1, end=2 }
fstream aFile
の位置再設定の例を次に示します。
streampos
original
=
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 3CC4
name
iostream
の用語
iostream
ライブラリの説明では、一般のプログラミングに関する用語と同じでも意味が異なる語を多く使用します。次の表では、それらの用語がiostream
ライブラリの説明で使用される場合の意味を定義します。
サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |