第9回
制御構造と変数(5)~forとwhileに関するあれこれ

入出力の切り替え~リダイレクトとパイプ

プログラムの入力と出力を自在に切り替える機能について説明しておきましょう。また、これらの機能を使わないで画面表示を一時停止するプログラムも作ってみます。

リダイレクト

UNIX系OSやDOSのコンソールモードでは、データのやりとりに標準入力・標準出力という仕組みを使います。標準入力とはキーボード、標準出力とはディスプレイで、これらはディスクに記録されたファイルと同じ扱いとなります。

この仕組みの便利な点は、標準入力や標準出力をテキストファイルに切り替えられることです。そのために用いる記号が、先に紹介した“>”と“|”です。他に“<”があります。

例えば、先の例のように
ex0901.exe > kuku.txt
とすれば、本来ディスプレイに送られるex0901.exeの処理結果はテキストファイル“kuku.txt”に送られるようになります。このとき、kuku.txtが存在していなければ新たに作成され、存在していれば内容が上書きされます。

また、キーボードからデータを受け取るtest.exeというプログラムがあったとして、そこにあらかじめ作成したdata.txtの内容を読み込ませるなら、以下のようにします。
test.exe < data.txt

さらにこの処理結果をresult.txtに受け取るなら、以下のようなコマンドラインとなります。
test.exe < data.txt > result.txt

このように標準入出力を切り替えることを『リダイレクト(redirect)』と呼び、そのために用いる“<”と“>”をリダイレクト記号といいます。

パイプとフィルタ

“<”と“>”によるリダイレクトは、プログラムとデータファイルとをつなぐ役割をしますが、“|”記号を使うとプログラムの出力を別のプログラムに送ることができます。これを『パイプ(pipe)』と呼びます。

先の
C:\>ex0901.exe | more
がパイプを使った例で、本来ディスプレイに送られるex0901.exeの出力はmoreという別のプログラムに送られ、その入力となります。moreは、先述したように受け取ったテキストデータを1画面ごとに切り分けて標準出力に送るプログラムなので、結果としズラズラーっとスクロールされるex0901.exeの処理結果が1画面ごとに停止して表示される訳です。

moreのようにパイプを使ってプログラムの処理結果やテキストファイルを加工するプログラムをフィルタ(filter)と呼びます。

9行ごとに区切って表示するプログラム

リダイレクトやパイプを使えば、こうして長い出力をファイルに書き出したり画面単位で切り分けたりできます。しかし、画面表示にこんなに手間がかかるのは考え物です。

プログラムのレベルで、九九をわかりやすく表示できるよう、ソースをリスト4のように書き換えてみましょう。単純に1つの段(9行分)を表示したら以下の1行によってEnterの入力を待つ――という形です。
  (void)getchar();

getchar関数は入力された1文字を受け取るための関数ですが、先頭に (void)を付けることによって入力された値を捨て、単に入力終了を示すEnterキーが押されるのを待つだけの機能となります。

このようにすれば、先のmoreを使ったフィルタと同じような処理がプログラムだけで実現できます。実行結果は画面3のようになります。

リスト4:9行表示するたびに Enterキーを待つ(ex0902.cex0902.exe)
#include <stdio.h>

int	main(void)
{
	int i, j;

	for (i = 1; i <= 9; i++) {
	  printf("◆ %d の段\n", i);
	  for (j=1; j<=9; j++) {
		printf("%d x %d = %d\n", i, j, i * j);
	  }
	  printf("----------------\nPress Enter", i);
	  (void)getchar();
	}
	return (0);
}