C++編【言語解説】 第5章 標準入出力ストリームの基礎

このエントリーをはてなブックマークに追加

この章の概要

この章の概要です。

関連する話題が、以下のページにあります。

標準出力ストリーム

C++ で標準出力への出力を行うには、これまでの章でも登場した std::cout を使います。

#include <iostream>

int main()
{
	std::cout << "Hello, World" << std::endl;
	std::cout << 100 << std::endl;
	std::cout << 1.23 << std::endl;
}

実行結果:

Hello, World
100
1.23

C言語の printf関数(⇒リファレンス)と違い、 型の指定を間違える可能性がないので、安全性が高まっています。

また、プログラマが任意で作った型に対しても適用できる拡張性にも特徴があります。 これについては、第35章で取り上げます。

printf系の関数のときには、"%3d" で3桁表記の整数を出力するといった特別な記法が用意されていました。 std::cout の場合は、マニピュレータという仕組みを使って、こういった特別な出力を実現できます。 マニピュレータについては後述します

標準入力ストリーム

C++ で標準入力から入力を受け取るには、std::cin を使います。

#include <iostream>

int main()
{
	char str[80];
	int n;
	double d;

	std::cin >> str;
	std::cin >> n >> d;

	std::cout << str << std::endl;
	std::cout << n << std::endl;
	std::cout << d << std::endl;
}

実行結果:

abc
100 1.23
abc
100
1.23

std::cin の場合は、std::cout とは使う演算子の向きが逆になります。 入力された値を変数へ格納するという流れになるので、格納先へ向くように >>演算子を使うという訳です。 また、scanf関数(⇒リファレンス)のように、ポインタ変数を指定する必要はありません。

なお、std::cin は、空白文字を読み飛ばします。 ここで言う「空白文字」とは、isspace関数(⇒リファレンス)が 0以外を返す文字を指します。

std::cout と同様、"%d" や "%s" といった scanf関数のようなフォーマット指定が不要になります。 しかし、入力となるとバッファオーバーフローの問題が考えられるので、先ほどのサンプルプログラムのような使い方では問題があります。 例えば、最初の部分で、格納先の配列str は要素数が 80 なので、これを超える長さの入力が行われるとバッファオーバーフローが起こります。

文字列の入力に関して言えば、そもそも char型の配列で受け取ろうとすることが間違いで、C++ ならば std::string を使うべきです。

#include <iostream>
#include <string>

int main()
{
	std::string str;

	std::cin >> str;

	std::cout << str << std::endl;
}

実行結果:

abc
abc

std::string を使って受け取ると、どんなに長い文字列が入力されたとしても、 それに応じて自動的にメモリを割り当ててくれますから、バッファオーバーフローは起こり得ません。

標準エラーストリーム

C++ で標準エラーへの出力を行うには、std::cerr、または std::clog を使います。 2つの違いは、std::cerr はバッファリングされておらず、std::clog はバッファリングされていることです。

使い方に関しても、std::cout と同じです。

#include <iostream>

int main()
{
	std::cerr << "cerr" << std::endl;
	std::clog << "clog" << std::endl;
}

実行結果:

cerr
clog

マニピュレータ

C++ の入出力ストリームでは、マニピュレータを使って、入出力の方法を制御できます。

標準入力ストリーム」のところで、char型の配列に文字列を受け取ろうとすると、 バッファオーバーフローの危険性があると指摘しました。 マニピュレータを使って、受け取る文字数に制限を掛けることで対応してみましょう。

#include <iostream>

int main()
{
	char str[5];

	std::cin >> str;

	std::cout << str << std::endl;
}

実行結果:

abcde
[エラー]

要素数 5 の配列で受け取ると、"abcde" のように 5文字以上入力されるとバッファオーバーフローを起こしてしまいます。 (末尾に '\0' があるので収まりません)。
マニピュレータを使って制限を掛けると、次のようになります。

#include <iostream>
#include <iomanip>

int main()
{
	char str[5];

	std::cin >> std::setw(sizeof(str)) >> str;

	std::cout << str << std::endl;
}

実行結果:

abcde
abcd

ここでは、std::setw というマニピュレータを使いました。 直後の ( ) に最大文字数を指定すれば、その文字数で制限されます。 これは特別な構文ではなくて、単なる引数です。 引数の無いマニピュレータもありますが、その場合には ( ) を付けるとコンパイルエラーになります。
std::setw のように引数を伴うマニピュレータを使うには iomanip をインクルードする必要があります。

マニピュレータは、<< や >> の前後に挟み込むようにして使います。 これらの演算子をデータの流れの方向とみなせば、マニピュレータの項を通過することで、データに何らかの制御が加えられると想像できます。
今回の場合なら、std::cin から入力データが std::setw に送られ、ここで 5文字幅という制限が加えられます。 この制限された結果が変数str へ送られていきます。


実は、これまでもずっと使ってきた std::endl もマニピュレータの一種です。 以前説明した通り、std::endl は、改行文字+フラッシュを意味しています。 ちなみに、改行だけが欲しければ、std::cout << "\n"; のように書けば良いですし、 フラッシュだけが欲しければ、std::cout << std::flush; と書けます。 std::flush もマニピュレータです。


マニピュレータについては数が多いので、言語解説編ではこれ以上扱いませんが、 【標準ライブラリ】第30章で、詳細を取り上げます。

ワイドストリーム

std::cout、std::cin、std::cerr、std::clog はそれぞれ、char型で表現される文字を扱います。

wchar_t型で表現されるワイド文字を扱いたい場合には、それぞれの名前の頭に w を付けたワイドストリーム版を使います。 それぞれ、std::wcoutstd::wcinstd::wcerrstd::wclog となります。 これらの使い方自体に変化はありません。


練習問題

問題@ std::hex、std::oct、std::dec というマニピュレータを使うと、16進数、8進数、10進数での整数出力が可能になります。 適当な整数値を出力して試してみて下さい。

問題A 問題@のマニピュレータを使うだけでは、16進数における 0x や、8進数における 0 といったプレフィックスが付きません。 これを付けるためには、std::showbase が使えます。また、付けないようにする(戻す)ためには、std::noshowbase が使えます。 それぞれ、試してみて下さい。


解答ページはこちら

参考リンク

更新履歴

'2013/12/15 新規作成。



前の章へ

次の章へ

C++編のトップページへ

Programming Place Plus のトップページへ