プログラミング演習 III 中級編 

2014年度担当:大川
演習IIIトップへ戻る

C++スタイルの入出力 (I/O stream)

Cではコンソール入出力の際に、printf()やscanf()といった関数を使っていました。C++でも、これらの入出力関数を使うこともできますが、新しいC++スタイルの入出力演算子(>>および<<)を使用することもできます。ここでは、C++の入出力に関連する内容を説明します。

最も簡単なコンソール出力のサンプルプログラム

LIST1-1 (console1.cpp)

   1 : #include <iostream>
   2 : 
   3 : int main()
   4 : {
   5 :     std::cout << "Hello iostream" << std::endl;
   6 :     return 0;
   7 : }

解説1)C++ヘッダ (#include<iostream>とは)(教科書p.10 Note)

C言語のプログラムでは、ライブラリ関数を使うときにはヘッダファイルをインクルードしていました。例えば、入出力関数用ヘッダファイルのインクルードの際には、プログラムの先頭に以下のように書きました。

#include <stdio.h>

C++でも、このような書き方がサポートされています。しかし、標準C++では、さらに、新しい種類のヘッダが追加されました。新しいスタイルでは、ヘッダファイルではなく、識別子を指定します。".h"が無いことに注意してください。新しいスタイルのヘッダの例として以下のようなものがあります。

<iostream>   入出力関連ヘッダ

<fstream>   ファイル入出力関連ヘッダ

※ 識別子とは、変数、関数、クラスなどを個々に識別するためにつける名前のことです。

解説2)std名前空間 "namespace" [教科書13.1 名前空間]

C言語では、開発するソフトウェアの規模が大きくなるにつれ、他の関数や変数と同じ名前を使用してしまう"名前の競合(もしくは衝突)"の問題が生じました。

C++における"名前空間"は、名前の競合を防ぐ目的で、識別子の名前を局所化するために使用されます。同じ"田中さん"でも"宇都宮の田中さん"と"小山の田中さん"というようにして区別することができますね。この"宇都宮"、"小山"が名前空間に相当すると考えてください。

さて、Cではライブラリ関数の名前などは、グローバルな名前空間に置かれていました。

新しいスタイルのC++ヘッダの内容は std名前空間に置かれています。std名前空間の関数や変数を使用するには「std::cout」のようにスコープ解決演算子を用いる必要があります。

ここで現れた「std::cout」は、C言語でいうstdout(標準出力=コンソール出力:console out)に当たります。

また、「std::endl」は、改行(end of line)を示します。

解説3)出力演算子 << と入力演算子 >> (教科書p.10〜)

C++では出力演算子 << と 入力演算子 >> が定義されています。Cでは<<は左シフト、>>は右シフトでした。C++ではシフト演算子としても使用されますが、入出力の演算子としての役割もあります

どちらの機能になるかは、演算子の左側におかれたオブジェクトの型に依ります。演算子の左が数値型であればシフト、入出力ストリームオブジェクトであれば入出力演算になります。これが「演算子 << が多重定義されている」ということの意味です。

なお、C++の入出力演算子を使うには、<iostream>ヘッダをインクルードする必要があります。

"using namespace"を使用したコンソール出力のサンプルプログラム

LIST1-2 (console2.cpp)

   1 : #include <iostream>
   2 : using namespace std;
   3 : 
   4 : int main()
   5 : {
   6 :     cout << "Hello iostream" << endl;
   7 :     return 0;
   8 : }

LIST1-1との違いは、何でしょうか?

解説4)"using namespace" について (教科書p.397〜)

以下の文を使用して、std 名前空間をデフォルトで参照可能(可視状態)にすることが出来ます。

using namespace std;

こうすることで、毎回スコープ解決演算子を用いて"std::"と書く必要がなくなります。

つまり、C++スタイルの入出力を使用する場合には、通常、プログラムの先頭に以下のように2行を記述することになります。

#include <iostream>
using namespace std;

もし、C++のコンパイラが古いバージョンで、上記の書き方ではエラーが発生する場合には、次のように1行で書くこともできます。

#include <iostream.h>

この場合はcoutなどはグローバル名前空間におかれます。

.h が付いている点とusing namespace ...の文がない点に注目してください。

少し複雑なコンソール入出力のサンプルプログラム

LIST1-3 (console3.cpp)


実行例

整数値を入力してください 5
あなたが入力したのは 5 です
実数値を入力してください 3.141592
あなたが入力したのは ******3.14 です
1文字だけ入力してください a
あなたが入力したのは a です
文字列を入力してください hello
あなたが入力したのは hello です

注目ポイント

入出力演算子(<<および>>)の右側に、文字列や数値の変数を置くことが出来る、ということに注目してください。

これも「演算子 << が多重定義されている」ということの意味です。

右辺に置いた変数(オブジェクト)の型に応じて、適切に表示してくれる、というのがC++スタイル入出力の良いところです。

一方、Cスタイルのprintfでは、書式文字列(%d,%fや%s)と、引数の型(int型、float型、文字列char[]型)が違うとおかしな表示になります。

解説5)C++の定義済みストリーム  (教科書 8章 p.247〜)

ストリーム(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 画面  

解説6)入出力マニピュレータ (manipulator:処理子、操作子)  (教科書p.260〜)

入出力マニピュレータ(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デバッガ)

ただし、ファイルを複数扱う場合や、ファイル中の場所を指定して一部だけを読み書きしたい場合には、プログラムの中でファイルを扱うための「ファイル入出力」の機能を使用する必要があります。

ファイル入出力については、教科書9章以降で扱っているので、余裕のある人は読んでおくと良いでしょう。

課題

課題1−1

課題1−2

課題1−3

課題1−4

おまけ:プログラミング演習コラム by大川

タッチタイピング

情報技術者を志すものであれば、必ず身に着ける必要がある。プログラミングや書類の作成において、必要になる技術なので、身に着けて損はないというか、必ず身に着けるべし。

私はインターネット上のタイピング練習(無料)サイトで身に着けた(あと、当時流行した北斗の拳タイピング)。身に着けることで受ける利益は大変大きい。

C++を学ぶ意義

コンピュータの動きを理解するためにはC言語を学ぶと良い。それは、基本的にマイクロプロセッサが出来る事は「メモリに対して読み書きし演算することだけ」ということが理解できるからである。メモリ上の数値をいじくるだけで、これだけ多彩なことが出来る、という発見は大きな驚きだと思う。

変数はメモリ上に配置されるものである、という理解があれば、ポインタというのはメモリ上に配置された変数のアドレスなのだ、と納得できるであろう。理解が難しいとされるポインタも大したことはない。より納得感を得るためには、アセンブリ言語も学ぶと良い。(情報工学実験Iのマイコン実習の理解を深めればよい)

さてそれでは、C++を学ぶ意義とは何か?

「C++は、1983年にベル研究所のコンピュータ科学者であったビャーネ・ストロヴストルップが、C言語の拡張として開発した。(出典:Wikipedia日本語版)」

その後、長い期間、世界中で使われているからには何らかの理由があるはずである。

自分にとってどのような良いことがあるかは、各自で考えて欲しい。ただここでは、いくつかの情報を示すこととする。

世の中で使われている開発言語(世界編)

TIOBE Programming Community Index May 2014



世の中で使われている開発言語(日本編)

プログラミング言語別 年収・求人数ランキング(2010年版) 【株式会社ワークポート調べ「2010年IT業界の転職市場」】

プログラマーの就職に有利な10のプログラミング言語
トップへ戻る

演習IIIトップへ戻る / 中級編トップに戻る