Cではコンソール入出力の際に,printf()やscanf()といった関数を使っていました. C++でも,これらの入出力関数を使うこともできますが,新しいC++スタイルの入出力演算子(>>および<<)を使用することもできます. ここでは,C++の入出力に関連する内容を説明します.
レポートプログラムの雛形ではC言語の入出力関数(scanfとprintf)を使用している. これらを全てC++言語の入出力演算子と定義済みストリームを使用した記述に書き換え,実行せよ. (main.cppの16,17行目,およびMyString.cppのprintString())
includeSrcWithFrame("prog_page1/console1.cpp", 4, "", false, true); ?>
C言語のプログラムでは,ライブラリ関数を使うときにはヘッダファイルをインクルードしていました.例えば,入出力関数用ヘッダファイルのインクルードの際には,プログラムの先頭に以下のように書きました.
#include <stdio.h>
C++でも,このような書き方がサポートされています.しかし,標準C++では,さらに,新しい種類のヘッダが追加されました.新しいスタイルでは,ヘッダファイルではなく,識別子を指定します.".h"が無いことに注意してください.新しいスタイルのヘッダの例として以下のようなものがあります.
<iostream> 入出力関連ヘッダ
<fstream> ファイル入出力関連ヘッダ
※ 識別子とは,変数,関数,クラスなどを個々に識別するためにつける名前のことです.
C言語では,開発するソフトウェアの規模が大きくなるにつれ,他の関数や変数と同じ名前を使用してしまう"名前の競合(もしくは衝突)"の問題が生じました.
C++における"名前空間"は,名前の競合を防ぐ目的で,識別子の名前を局所化するために使用されます.同じ"田中さん"でも"宇都宮の田中さん"と"小山の田中さん"というようにして区別することができますね.この"宇都宮","小山"が名前空間に相当すると考えてください.
さて,Cではライブラリ関数の名前などは,グローバルな名前空間に置かれていました.
新しいスタイルのC++ヘッダの内容は std名前空間に置かれています.std名前空間の関数や変数を使用するには「std::cout」のようにスコープ解決演算子を用いる必要があります.
ここで現れた「std::cout」は,C言語でいうstdout(標準出力=コンソール出力:console out)に当たります.
また,「std::endl」は,改行(end of line)を示します.
C++では出力演算子 << と 入力演算子 >> が定義されています.Cでは<<は左シフト,>>は右シフトでした.C++ではシフト演算子としても使用されますが,入出力の演算子としての役割もあります
どちらの機能になるかは,演算子の左側におかれたオブジェクトの型に依ります.演算子の左が数値型であればシフト,入出力ストリームオブジェクトであれば入出力演算になります.これが「演算子 << が多重定義されている」ということの意味です.
なお,C++の入出力演算子を使うには,<iostream>ヘッダをインクルードする必要があります.
includeSrcWithFrame("prog_page1/console2.cpp", 4, "", false, true); ?>
LIST1-1との違いは,何でしょうか?
以下の文を使用して,std 名前空間をデフォルトで参照可能(可視状態)にすることが出来ます.
using namespace std;
こうすることで,毎回スコープ解決演算子を用いて"std::"と書く必要がなくなります.
つまり,C++スタイルの入出力を使用する場合には,通常,プログラムの先頭に以下のように2行を記述することになります.
#include <iostream>
using namespace std;
もし,C++のコンパイラが古いバージョンで,上記の書き方ではエラーが発生する場合には,次のように1行で書くこともできます.
#include <iostream.h>
この場合はcoutなどはグローバル名前空間におかれます.
.h が付いている点とusing namespace ...の文がない点に注目してください.
includeSrcWithFrame("prog_page1/console3.cpp", 4, "", false, true); ?>
実行例
整数値を入力してください 5 あなたが入力したのは 5 です 実数値を入力してください 3.141592 あなたが入力したのは ******3.14 です 1文字だけ入力してください a あなたが入力したのは a です 文字列を入力してください hello あなたが入力したのは hello です |
入出力演算子(<<および>>)の右側に,文字列や数値の変数を置くことが出来る,ということに注目してください.
これも「演算子 << が多重定義されている」ということの意味です.
右辺に置いた変数(オブジェクト)の型に応じて,適切に表示してくれる,というのがC++スタイル入出力の良いところです.
一方,Cスタイルのprintfでは,書式文字列(%d,%fや%s)と,引数の型(int型,float型,文字列char[]型)が違うとおかしな表示になります.
ストリーム(stream)という英単語の意味は”流れ”ですね.ここでは,情報を流すための論理デバイスのことを言います.論理デバイスが,CやC++の入出力システムによって物理デバイス(キーボードや画面)とリンクされることでデータを入力したり,表示したりすることができるわけです.
Cでは,出力の際に,以下のように記述していました.
int i;
double d;
fprintf(stdout, "あなたが入力したのは %d です\n", i);
fprintf(stdout, "あなたが入力したのは %lf です\n", d);
printf("あなたが入力したのは %d です\n", i);
printf("あなたが入力したのは %lf です\n", d);
これを,C++では以下のように記述することができます.
cout << "あなたが入力したのは" << i << "です\n";
cout << "あなたが入力したのは" << d << "です" << endl;
書式指定子(%d,%lf など)がないですね. 書式指定子を気にしないでよいのはちょっと嬉しいですね.
C++の定義済みストリームを以下の表にまとめます.
意味 | デフォルトデバイス | Cとの対応 | |
cin | 標準入力 | キーボード | stdin |
cout | 標準出力 | 画面 | stdout |
cerr | 標準エラー出力 | 画面 | stderr |
clog | バッファを使うcerr | 画面 |
入出力マニピュレータ(I/O manipulator)とは,入出力ストリームに対して使用できるオブジェクトです.先ほど登場した endl は改行文字(\n)を出力し,ストリームをフラッシュする入出力マニピュレータです.よく使用する入出力マニピュレータと,その使用例,実行結果を以下の表にまとめます.
なお,setw()のように仮引数をとるマニピュレータを使用するには<iomanip>をインクルードしておく必要があります.
目的 | 例 | 実行結果 | |
endl | 改行文字(\n)を出力し, ストリームをフラッシュ |
cout << "hello" << endl; | hello |
hex | hexフラグをオン | cout << hex << 255; | ff |
oct | octフラグをオン | cout << oct << 9; | 11 |
setw(int w) | フィールド幅をwに設定 | cout << setw(5) << 35; | ___35 ※注 |
setprecision(int p) | 精度の桁数をpに設定 | cout << setprecision(3) << 2.5614; | 2.56 |
setfill(int ch) | 充填文字をchに設定 | cout << setfill('*') << setw(4) << 5; | ***5 |
※注 ___ は半角スペース3つを表す.
ファイル入出力の必要がある場合,入力ファイルが1つ・出力ファイルが1つまでであれば,コンソール入出力をファイルにつなぎかえる「リダイレクト機能」により,大抵の用事は済ますことが出来ます.リダイレクトの復習(プログラミング演習Iデバッガ: 工事中)
ただし,ファイルを複数扱う場合や,ファイル中の場所を指定して一部だけを読み書きしたい場合には,プログラムの中でファイルを扱うための「ファイル入出力」の機能を使用する必要があります.