#include <iostream.h> class unsafe_ios { public: // エクスポートされた型 // ストリームのステータスビット
enum io_state { goodbit = 0x00, // ビットは設定されていない: すべて良好 eofbit = 0x01, // ファイルの終わりに位置している failbit = 0x02, // 最後の入出力操作に失敗 badbit = 0x04, // 無効な操作を行おうとした hardfail = 0x80 // 回復不能なエラー };
// ストリーム操作モード enum open_mode { in = 0x01, // 読み取りのためにオープン out = 0x02, // 書き込みのためにオープン ate = 0x04, // 最初のオープン時に EOF までシーク app = 0x08, // 追加モード: EOF にすべて追加 trunc = 0x10, // ファイルがすでに存在する場合ファイルを切り捨て nocreate = 0x20, // ファイルが存在しない場合オープンが失敗 noreplace= 0x40 // ファイルがすでに存在する場合オープンが失敗 };
// ストリームシーク方向 enum seek_dir { beg=0, cur=1, end=2 };
// 書式設定フラグ enum { skipws = 0x0001, // 入力の空白を読み飛ばす left = 0x0002, // 左揃えで出力 right = 0x0004, // 右揃えで出力 internal = 0x0008, // 符号や基数指示子の後ろのパディング dec = 0x0010, // 10 進数変換 oct = 0x0020, // 8 進数変換 hex = 0x0040, // 16 進数変換 showbase = 0x0080, // 基数指示子を出力 showpoint = 0x0100, // 小数点を強制的に使用 (浮動小数点型の出力) uppercase = 0x0200, // 16 進数を大文字で出力 showpos = 0x0400, // 正の整数に '+' を追加 scientific= 0x0800, // 1.2345E2 浮動小数点表記を使用 fixed = 0x1000, // 123.45 浮動小数点表記を使用 unitbuf = 0x2000, // 挿入後すべてのストリームをフラッシュ stdio = 0x4000 // 挿入後、標準出力や標準エラーをフラッシュ };
public: // エクスポートされた関数 // 書式関連の関数 long flags(); long flags(long bits); long setf(long setbits, long field); long setf(long setbits); long unsetf(long unsetbits); int width(); int width(int len); char fill(); char fill(char ch); int precision(int len); int precision(); int skip(int doskip); // 廃止 // 状態関連の関数 int rdstate(); int eof(); int fail(); int bad(); int good(); void clear(int state=0); // その他の関数 ostream* tie(ostream* tiedstream); ostream* tie(); streambuf* rdbuf(); static long bitalloc(); static int xalloc(); long & iword(int index); void* & pword(int index); static void sync_with_stdio(); public: // エクスポートされた演算子と変換関数 operator void* (); int operator ! (); public: // エクスポートされたコンストラクタ、デストラクタ unsafe_ios(streambuf* sbp); virtual ~unsafe_ios(); public: // エクスポートされたデータメンバー static const long basefield; // dec | oct | hex static const long adjustfield; // left | right | internal static const long floatfield; // scientific | fixed protected: // 保護された関数 void init(streambuf* sbp); // 保護されたコンストラクタ unsafe_ios(); void setstate (int); static void (*stdioflush)(); private: // 非公開メンバー (コピー防止のため) unsafe_ios(unsafe_ios&); void operator= (unsafe_ios&); };
class ios : virtual public unsafe_ios, public stream_MT { public: // 書式関連の関数 long flags(); long flags(long); long setf(long setbits, long field); long setf(long); long unsetf(long); int width(); int width(int); char fill(); char fill(char); int precision(); int precision(int); // 状態関連の関数 int rdstate(); int eof(); int fail(); int bad(); int good(); void clear(int state =0); // その他の関数 ostream* tie(); ostream* tie(ostream*); streambuf* rdbuf(); static long bitalloc(); static int xalloc(); long& iword(int); void* & pword(int); static void sync_with_stdio(); public: // エクスポートされた演算子と変換関数 operator void*(); int operator!(); public: // エクスポートされた演算子と変換関数 ios(streambuf* sbp); virtual ~ios(); protected: init(streambuf* sbp); ios(); setstate(int); static void (*stdioflush)(); protected: static stream_rmutex static_mutlock; static int mutex_init_count; private: ios(ios&); void operator=(ios&) ; };
// 定義済みマニピュレータ unsafe_ostream& endl(unsafe_ostream&); unsafe_ostream& ends(unsafe_ostream&); unsafe_ostream& flush(unsafe_ostream&); ostream& endl(ostream&); ostream& ends(ostream&); ostream& flush(ostream&); unsafe_ios& dec(unsafe_ios&); unsafe_ios& hex(unsafe_ios&); unsafe_ios& oct(unsafe_ios&); ios& dec(ios&); ios& hex(ios&); ios& oct(ios&); unsafe_istream& ws(unsafe_istream&); istream& ws(istream&);
クラス ios はすべてのストリームオブジェクトの仮想基底クラスです。ストリームの基本状態と書式設定データを提供します。いくつかの列挙と多数の関数が定義されています。それらを次で説明します。
クラス unsafe_ios はこのクラスのすべての機能を実装します。クラス ios は、unsafe_ios の各メンバー関数に相互排他ロックを実装し、複数のスレッドによるアクセスに対して保護する「ラッパー」クラスです。ただし、保護された (protected) クラスを使用しても MT-安全性は保証されません。アプリケーションを MT-安全にする詳細については、『C++ ライブラリリファレンス』の第 4 章「マルチスレッド環境での従来型の iostream ライブラリの使用」を参照してください。
メンバー関数は、これらの列挙を使用してストリームのエラー状態を追跡します。これらのビットのテスト方法については、後述の「エラー状態」セクションも参照してください。io_state は実際は次のようなビットの集まりです。
この「ビット」は、実際にはどのエラービットもなく、ストリームが正常な状態であることを示します。
このビットは通常、抽出時にファイルの終端に到達すると設定されます。ファイルの終端に達した抽出の成功の結果として設定されるのではなく、さらに抽出を試みている間にファイルの終端に達した場合に設定されます。この意味での「ファイルの終端」とは、そのストリームに関連付けられた streambuf で定義されている抽象的概念です。通常、このビットは出力ストリームに対しては設定されません。
このビットは、抽出または変換が通常予期しない文字によって失敗すると、設定されます。それ以後の抽出の試みはこのビットがクリアされるまで失敗し、不正な入力の後の実行を回避します。通常、ストリームは引き続き使用可能であり、ビットをクリアして、予期しない入力を処理したあとに、抽出を続行できます。
このビットは、関連付けられた streambuf への何らかの操作が失敗したことを示します。通常、ビットをクリアしたあとでもそれ以上の操作の試みは成功しません。状況の例として、出力エラーや、入力操作を試みてすぐのファイルの終端などがあります。
このビットは、ストリームがそれ以上使用できないことを示すために、実装に予約されています。通常、何らかの種類のハードウェア障害を表します。どこからでも (public) アクセス可能な関数によって、このビットをクリアすることはできません。
これらの列挙については、fstream(3CC4) の関数 open() の説明の下で説明しています。
これらの列挙については、sbufpub(3CC4) の関数 seekoff() の説明の下で説明しています。
メンバー関数は、これらの匿名型の列挙を使用して、入出力の書式設定を制御します。後述の「書式制御」セクションを参照してください。
sbp が指す streambuf は、構築される ios に関連付けられている streambuf になります。ポインタは NULL にできません。
これまで、仮想基底クラスにはデフォルトのコンストラクタ (引数を持たないもの) が必要でした。仮想基底クラスのコンストラクタに引数を渡す方法がなかったためです。そのため、クラス ios にはデフォルトのコンストラクタと streambuf へのポインタをとる個別の初期化関数があります。派生クラスは、デフォルトで保護された (protected) コンストラクタ ios() を使用し、初期化関数 init(streambuf*) を呼び出します。init の引数は、構築される ios に関連付けられる streambuf を指し、NULL にできません。例:
class istream : virtual public ios { ... }; istream::istream(streambuf* s) { ios::init(s); // ... }
コピーコンストラクタと代入演算子は、ios オブジェクトのコピーを防止するために private です。そのようなコピーの影響は不明であるからです。通常は、オブジェクトへのポインタをコピーするか、関数への参照を渡したいと考えます。
次のように、いくつかの関数によってエラー状態ビットのテストや調整が可能です。
ストリーム s のエラー状態ビットを int として返します。
その int パラメータをストリーム s のエラー状態として格納します。state の値は、rdstate の戻り値や io_state ビットの組み合わせからのみ派生するようにしてください。ストリーム状態の 1 つのビットだけをクリアするには、s.clear(~ios::failbit & s.rdstate()); などを使用します。
エラー状態が正常、つまりどのビットも設定されていない場合、ゼロ以外を返します。それ以外の場合は、ゼロを返します。特に eofbit が設定されている場合はゼロを返します。
eofbit が設定されている場合は、ゼロ以外を返し、それ以外の場合は、ゼロを返します。
failbit、badbit、または hardfail のいずれかが設定されている場合は、ゼロ以外を返し、それ以外の場合は、ゼロを返します。
badbit または hardfail が設定されている場合は、ゼロ以外を返し、それ以外の場合は、ゼロを返します。
ストリームの状態を直接テストできれば便利なことがあります。一般的な挿入演算子や抽出演算子はストリームへの参照を返すため、演算の戻り値をテストできます。このテストを可能にするために、2 つの演算子が定義されています。
void* へのストリームの明示的なキャストを使用するか、ストリームをブール値のコンテキストで使用して、その状態をテストできます。failbit、badbit、または hardfail のいずれかが設定されている場合、結果は 0 になります。ストリームが正常または eof 状態である場合、結果はゼロ以外のポインタになります。例:
if( cout ) ... // next output will probably succeed if( cin >> x ) ... // input to x succeeded
この演算子は、前述のテストの逆を提供します。failbit、badbit、または hardfail のいずれかが設定されている場合、結果はゼロ以外になり、それ以外の場合は、ゼロになります。例:
if( ! cout ) ... // output will not succeed if( ! (cin >> x) ) ... // input to x failed
ios は、書式設定フラグによって制御される書式状態と fill()、width()、および precision() の 3 つの関数を保持します。書式設定フラグは後述するビットの集まりで、匿名型の列挙として宣言されます。これらの書式状態ビットは long int で保持され、flags() 関数の 2 つのバージョンを介して個別に操作できます。
書式設定フラグは、ほかの操作から独立して設定およびクリアできます。フラグは、プログラマの明示的なアクションによってのみ変更されます。フラグは次のとおりです。
このフラグが設定されている場合、書式付きエクストラクタは先頭の空白をスキップし、設定されていない場合、先頭の空白をスキップしません。このフラグはデフォルトで設定され、自由書式の入力テキストが可能です。書式なしのエクストラクタは、このフラグを調査しません。
これらのフラグは、書式付き演算時にパディングをどのように挿入するかを制御します。これらの 3 つのフラグは、一度に 1 つずつしか設定できません。静的メンバー ios::adjustfield によって、3 つのフラグを一体として処理できます。left が設定されている場合、値はそのフィールド幅に左揃えされ、右側にパディングが追加されることを意味します。right が設定されている場合、値はそのフィールド幅に右揃えされ、左側にパディングが追加されることを意味します。internal が設定されている場合、先頭の基数または符号フィールドの後、値の前にパディングが追加されます。デフォルト (どのフラグも設定されていない) は right です。パディングに使用する充てん文字のデフォルトはスペース文字に設定され、fill 関数によって設定できます。パディングの量は、width 関数によって設定されるフィールド幅によって決定します。manip(3CC4) も参照してください。
これらのフラグは整数データの変換基数を制御します。これらの 3 つのフラグは、一度に 1 つずつしか設定できません。静的メンバー ios::basefield によって、3 つのフラグを一体として処理できます。dec が設定されている場合 10 進数 (基数 10)、oct が設定されている場合 8 進数 (基数 8)、hex が設定されている場合 16 進数 (基数 16) で変換が行われます。どのフラグも設定されていない場合、挿入は 10 進数で行われ、抽出は整数定数を表現するための C++ の規則に従って変換されます。つまり、先頭の「0x」または「0X」は抽出の 16 進数変換になり、先頭の「0」は 8 進数変換になり、先頭の「1」から「9」は 10 進数変換になります。デフォルトではこれらのどのビットも設定されません。セクション「定義済みマニピュレータ」で後述するように、マニピュレータ dec、oct、および hex を使用して、変換の基数を設定することもできます。
このフラグが設定されている場合、変換済みの整数値の挿入は、C++ の整数定数の表現に使われる書式で行われます。つまり、8 進数値は先頭「0」で始まり、16 進数値は先頭「0x」または「0X」で始まります。(後述の「uppercase」を参照してください)。デフォルトは未設定です。
このフラグが設定されている場合、変換済みの正の 10 進数値 (浮動小数点を含む) の挿入に、プラス符号 (+) が追加されます。デフォルトは未設定です。
このフラグが設定されている場合、showbase が設定されていると、変換済みの 16 進数値の挿入で、大文字の「X」が使用され、浮動小数点変換には大文字「E」が使用されます。それ以外の場合は、小文字の「x」と「e」がそれぞれ使用されます。デフォルトは未設定です。
これらのフラグは、挿入のために浮動小数点値を変換する際に使用する変換のタイプを制御します。静的メンバー ios::floatfield によって、2 つのフラグを一体として処理できます。変換で従う規則は、一般に C の標準入出力関数 printf の場合と同じです。(printf(3c) を参照してください)。scientific が設定されている場合、「e」書式が使用されます。fixed が設定されている場合、「f」書式が使用されます。どちらも設定されていない場合「g」書式が使われます。(前述の uppercase も参照してください)。width によって設定されている値がある場合は、printf のフィールド幅の指定として使用されます。precision によって設定されている値がある場合は、printf の精度の指定として使用されます。
このフラグが設定されている場合、浮動小数点値の変換で、末尾のゼロ、または末尾の小数点が表示されます。デフォルトでは、末尾のゼロ、または末尾の小数点は切り捨てられます。
出力ストリームがバッファリングされる場合、バッファーはいっぱいになるか、明示的にフラッシュされた場合にフラッシュされます。これにより、出力が遅延したり、プログラムがクラッシュした場合には出力が失われる可能性があります。ストリームをバッファリングしないで、出力の遅延や損失をなくすこともできますが、文字出力のたびのシステムコールという犠牲が伴います。unitbuf が設定されている場合、完全な挿入のたびに、バッファーがフラッシュされます。そこで妥協策は「単位バッファリング」であり、バッファリングされない出力よりも低コストで頻繁な出力を提供し、プログラムソースで特別な flush 呼び出しも必要ありません。特に単位バッファリングは、コードの選択された場所でほかのソースコードを変更することなくオン/オフにすることができます。デフォルトでこのフラグは設定されません。
このフラグにより、C の標準入出力ファイル stdout および stderr は、ストリームへの挿入のたびに、フラッシュされます。これは、標準ファイル上の C の標準入出力がほかのファイル上の iostreams と混在している場合に便利なことがあります。デフォルトでこのフラグは設定されません。
書式制御関数は次のとおりです。
ストリーム s の現在の書式設定フラグを long で返します。
newflags の long 値を使用して、ストリーム s のすべての書式設定フラグを置き換えます。以前の書式設定フラグを long で返します。
ストリーム s の書式設定フラグに、long 値 newflags に設定されている各ビットが設定されます。残りの書式設定フラグは影響を受けません。以前の書式設定フラグを long で返します。flags 関数はすべてのフラグビットを置き換え、setf 関数は指定されたビットだけを設定することに注意してください。グループに含まれないフラグを設定する場合、このバージョンの setf がもっとも役に立ちます。グループのフラグのいずれかを設定する場合、後述のこの関数の 2 番目の形式を参照してください。
long 値 field に設定されているビットは、long 値 newflags の対応するビットに置き換えられる書式設定フラグをマークします。指定されたフラグの前の値を返します。一般に、field の値として、定数 basefield、adjustfield、または floatfield のいずれかが使用されます。例 - 左揃えに設定し、値を出力して、前の位置揃えを元に戻します。
long oldadjust = cout.setf(ios::left, ios::adjustfield); cout << data; cout.setf(oldadjust, ios::adjustfield);
この技法により、adjustfield ビットのうちの 1 つのビットだけが設定され、以前のステータスの便利な復元が可能です。フィールドの新しい値としてゼロを使用すると、それらのフラグだけがクリアされます。例 - 整数変換の基数をデフォルトの状態にクリアします。
cout.setf(0, ios::basefield);
manip3CC4 のマニピュレータ (setiosflags) と resetiosflags も参照してください。
ストリーム s の書式設定フラグに、long 値 newflags に設定されている各ビットが設定されません。残りの書式設定フラグは影響を受けません。以前の書式設定フラグを long で返します。setf 関数は対応するフラグビットを設定し、unsetf 関数はそれらをクリアします。 manip (3CC4) のマニピュレータ resetiosflags も参照してください。
ストリーム s の現在の充てん文字を返します。充てん文字は、指定したフィールド幅まで挿入をパディングするために使用します。このリリースでは、fill にシングルバイト文字のみをサポートしています。前述の left、right、および internal の説明を参照してください。
ストリーム s の充てん文字を newfill に設定し、古い充てん文字を返します。デフォルトの充てん文字はスペースです。manip3CC4() のマニピュレータ setfill も参照してください。
ストリーム s の現在の「precision」書式状態を返します。これは、浮動小数点の挿入で変換される有効桁数を制御します。前述の scientific と fixed の説明を参照してください。
ストリーム s の「precision」書式状態を newprec に設定し、古い値を返します。デフォルト値は 6 です。manip3CC4() のマニピュレータ setprecision も参照してください。
ストリーム s の現在の「フィールド幅」書式状態を返します。フィールド幅がゼロの場合、インサータは、挿入される値を表すために必要な文字のみを挿入します。フィールド幅が必要な文字の数よりも大きい場合は、前述のようにフィールドが指定された幅まで充てん文字でパディングされます。フィールド幅が必要な文字の数よりも小さい場合は、幅が拡大されます。フィールド幅は最小のフィールド幅を表します。最大のフィールド幅まで切り捨てを提供するために使用することはできません。ワイド文字出力の場合、幅はバイト数ではなく、引き続き文字数で測定されます。
ストリーム s の「フィールド幅」書式状態を newwidth に設定し、古い値を返します。デフォルト値は 0 です。書式付きの挿入または抽出後に、フィールド幅は自動的にゼロにリセットされます。したがって、フィールド幅を必要とする操作のたびに設定をリセットする必要があります。manip3CC4() のマニピュレータ setw も参照してください。
独自のものが必要になる可能性のある派生クラスには、ユーザー定義の書式フラグと変数が用意されています。フラグと変数はクラスに割り当てられると、プログラムの実行時間のあいだ保持されます。複数の独立したクラスで、競合することなく、独自のフラグや変数を割り当てることができます。
この静的メンバー関数は、以前に割り当てられていない 1 つのフラグビットが設定された long を返します。この値は、たとえば setf の呼び出しの中で、クラス固有の目的のためのフラグとして使用できます。割り当てには、少なくとも 16 ビットを使用できます。使用できるビットがない場合、この関数はゼロを返します。
この静的メンバー関数は単語の配列にこれまで使用されていないインデックスを返します。1 つの単語は、long または void* を格納するために十分な大きさがあります。このインデックスを関数 iword または ipword で使用して、予約されているステータス変数への参照を取得できます。
i が ios::xalloc の呼び出しによって返されたインデックス値の場合、これらの関数は、クラス s の i 番目のユーザー定義ステータス変数 (単語) への参照を返します。関数 iword は long として型指定された参照を返し、関数 ipword は void* として型指定された参照を返します。注: 返される参照が無期限で安定していることに依存しないでください。特に、xalloc() を呼び出すと、以前の参照が無効になる場合があります。
ストリームに関連付けられた streambuf へのポインタを返します。これは、ストリームの構築の一部であり、バッファークラスオブジェクトは通常変更されません。この関数を使用して、ストリームオブジェクトと仮定して streambuf 関数に直接アクセスできます。
ストリームは、tie ストリーム変数によって追跡される 1 つの ostream に結合されることがあります。ストリームで追加の入力を取得したり、その出力をフラッシュしたりする必要がある場合、結合されているストリームがあれば、まずそれがフラッシュされます。たとえば、cin は最初に cout に結合されているため、新しい入力を試みる前に、プロンプトなどの保留中の出力がフラッシュされます。この関数は、ストリーム s の tie 変数を入力パラメータ osp が指す ostream に設定し、tie 変数の古い値を返します。シーケンス
ostream* oldosp = s.tie(0); ... do something ... s.tie(oldosp);
は、何らかの作業が行われている間にストリームの結合を解除し、以前の tie に戻します。
tie 変数の現在の値を返します。(上記を参照)。
C の標準入出力および C++ のストリーム操作を同じ標準ファイルで実行すると、同期の問題が発生します。I/O の各スタイルには独自のバッファリングがあるため、プログラムの実行順序で I/O が行われません。この同期の問題を解決するには、標準ストリーム cin、cout、cerr、または clog のいずれかに対して I/O を行う前にこの静的関数を呼び出します。この関数は、標準ストリームを stdiobuf を使用するようにリセットします。これにより、標準入出力とストリームを介した I/O が同期されます。バッファー付きストリーム I/O だけやバッファー付き標準入出力だけを使用する場合と比較して、パフォーマンスはかなり低下します。stdiobuf(3CC4) を参照してください。注: sync_with_stdio は、同じ標準入力、出力、またはエラーファイルに I/O を行う場合にのみ必要です。stdin 上で標準入出力入力関数を排他的に使用し、cout 上でストリーム出力関数を排他的に使用することは、難しくありません。
マニピュレータは、見掛け上、挿入または抽出されたオブジェクトとして使われることがありますが、実際はストリームの状態を変更するだけです。詳細については manip(3CC4) を参照してください。ストリームで使用するために、いくつかのマニピュレータが事前定義されています。
これらは、ストリーム s の変換基数を 10 に設定します。
これらは、ストリーム s の変換基数を 8 に設定します。
これらは、ストリーム s の変換基数を 16 に設定します。
これはストリーム s から空白を抽出し、破棄します。istream(3CC4) を参照してください。
ストリーム s に改行を挿入し、そのストリームをフラッシュします。ostream(3CC4) を参照してください。
ストリーム s に NULL 文字 (\0) を挿入して文字列を終了します。strstream(3CC4) を参照してください。
ストリーム s をフラッシュします。ostream(3CC4) を参照してください。
<manip.h> を取り込むと、追加のマニピュレータが利用できるようになります。manip(3CC4) を参照してください
printf (1) , filebuf (3CC4) , fstream (3CC4) , ios.intro (3CC4) , istream (3CC4) , manip (3CC4) , ostream (3CC4) , printf (3C) , sbufprot (3CC4) , sbufpub (3CC4) , ssbuf (3CC4) , stdiobuf (3CC4) , strstream (3CC4) , stream_locker (3CC4) , stream_MT (3CC4)
『C++ ライブラリリファレンス』の第 3 章「従来型の iostream ライブラリ」および第 4 章「マルチスレッド環境での従来型の iostreams ライブラリの使用」