「標準出力」というのは、慣用的な出力を行うためのテキストストリームの結合先のことで、多くの場合、画面への表示になっています。画面といっても、Windowsなどで見慣れたウィンドウとかではなく、コマンドライン(Windowsでいえばコマンドプロンプト)です。
しかし、プログラムの呼び出し方しだいで、標準出力は、画面への表示ではなく、ファイルや他のプログラムが操作するストリームに結合することもできます。例えば、CGIでは標準出力への書き込みはブラウザへのレスポンスとなります。また別の状況では標準出力の結合先がシリアルポートになることもあるでしょう。
std::cout
標準出力に書き込むための最も一般的な方法は、std::coutを使用することです。std::coutに対して<:<演算子を用いることで、
0 1 2 3 4 5 6 7 |
#include <iostream> int main() { std::cout << "Hello, World!"; } |
とすれば、<<演算子の右辺に記述したオブジェクトの値が標準出力に書き込まれます。上のサンプルコードでも分かるように、std::coutを使うときは<iostream>ヘッダをインクルードする必要があります。
また、末尾に改行を書き込みたい場合には、’\n’または”\n”を書き込んでもよいのですが、普通はstd::endlを使用します。std::endlを使うと、単に改行するだけではなく、バッファ貯まっている内容を実際に出力します。
0 1 2 |
std::cout << "Hello, World!" << std::endl; |
std::endlは、改行文字’\n’を書き込んだ後、ストリームが管理しているバッファの内容をフラッシュ(実際に吐き出)します。
std::coutを使うメリットは、<<演算子さえ定義してやれば、ユーザー定義型も含めて、どんな型のオブジェクトであっても同じ構文で書き込み処理を記述できる点にあります。デメリットとしては、ややオーバーヘッドが大きいことが挙げられます。ただ、速度面に関しては、元々入出力は遅いものですし、サイズ面に関しては、プログラムの規模がある程度以上大きくなると、その影響は微々たるものになります。std::coutを避ける、または他の方法を用いる積極的な理由がなければ、std::coutを使うようにしましょう。
std::wcout
std::wcoutはstd::coutとよく似ています。何が違うかというと、std::coutに対して書き込むことができる文字はchar型であり、文字列はchar*またはstd::string型なのに対して、std::wcoutに書き込むことができる文字はwchar_t型であり、文字列はwchar_t*またはstd::wstring型だということです。つまり、std::wcoutはワイド文字(列)を扱うためのものです。
std::coutはchar型のようなナロー文字(列)しか扱えません。逆に、std::wcoutはwchar_t型のようなワイド文字(列)しか扱えません。両方を混在させることは原則としてできないのです。どうしても混在させたい場合は、自分で << 演算子を多重定義するなどしなければなりません。 また、ひとつのプログラムの中で、std::coutとstd::wcoutを混在させるべきではありません。
0 1 2 3 4 5 6 7 |
#include <iostream> int main() { std::wcout << L"Hello, World!" << std::endl; } |
なお、処理系によってはstd::wcoutがサポートされていない場合があります。規格上はサポートしなければならないのですが、実際に使う処理系がサポートしないのであれば、使用を控える以外にありません。
なお、std::wcoutを用いて日本語を出力したい場合には、ロケールの設定が必要になります。ロケールを設定するには、std::wcoutのimbueメンバ関数を使用します。このメンバ関数に設定しようとするロケールを渡すことになります。例えば、
0 1 2 3 4 5 6 7 8 9 |
#include <iostream> #include <locale> int main() { std::wcout.imbue(std::locale("")); std::wcout << L"こんにちは、世界!" << std::endl; } |
のようにです。上のサンプルコードでは、ロケールに””を設定しています。日本語のOS環境であれば、多くの場合これで問題ありませんが、もっと明示的に日本語ロケールを設定するには、処理系定義の文字列、例えば”ja”とか”japanese”などを渡す必要があります。
処理系によっては、std::setlocale関数によってグローバルロケールを設定しておかないと誤動作することがあります。また、std::localeクラスのコンストラクタが例外を送出する場合もあるようです。処理系の不具合ですが、ときどき遭遇するので要注意です。
stdout
最後はC言語との互換性のために用意されたstdoutマクロを使う方法です。std::coutの使い方が分からないといった後ろ向きな理由を除けば、std::coutやstd::wcoutではなく、stdoutを使わなければならない状況は多くありません。しかし、例えばFILE*型の他のストリーム(テンポラリファイルやパイプなど)と出力先を切り替えたい場合などは、そうせざるを得ないこともあるでしょう。
stdoutを用いて標準出力に文字列を書き込むには、
0 1 2 3 4 5 6 7 |
#include <cstdio> int main() { std::fputs("こんにちは、世界!n", stdout); } |
のようにします。数値を書き込むには、printfまたはfprintfを使うことになりますが、オブジェクトの型によって異なる書式を指定しなければなりません。
0 1 2 3 4 5 6 7 |
#include <cstdio> int main() { std::printf("%d %fn", 123, 4.56); } |
printf関数等では、第1引数である書式文字列に続く引数の型はまったくチェックされません。また、クラス型のオブジェクトを引数に渡すと未定義の動作を引き起こします。そのため、プログラマの責任で正しい書式を記述しなければなりません。