第3回 標準入力・標準出力(4月22日)

今日の課題

■ 標準入力・標準出力

情報の窓口

大きなプログラムを作るには、部品となる小さなプログラムを組み合わせて作るので、部品間の情報の受け渡しがスムーズなほうが良い。そこで、UNIXのプログラミングには、「標準入力」と「標準出力」というものがある。

C言語での扱い(stdin/stdout)

C言語では、標準入力を「stdin」、標準出力を「stdout」と書く。ファイルの入力や出力をするとき、ファイルディスクリプタ(FILE *)を使う。stdin や stdout はファイルディスクリプの一種である。

コマンドライン上で「man fgets」を実行すると、C言語の関数「fgets」の使い方が表示される。「FILE *stream」という引数のところに、stdin や stdout を記入する。

次のプログラムでは、コマンドラインから「abcd」と「リターン」を入力すると、一文字表示し改行する、ということを繰り返す。「リターン」を入力しているので、最後に空行が2つ入る。 ⇒ list0301.c

なお、putchar や printf など指定のない出力は、標準出力に出力する。

標準入力の切り替え

list0301.c をコンパイル後、コマンドライン上で「./a.out < list0301.c」と実行すると、「/* list03」までの9文字が表示される。「<」という記号は、標準入力を指定する意味である。この実行では、ファイル list0301.c の中身が標準入力の内容となる。

標準出力は「>」という記号を使う。たとえば、「./a.out < list0301.c > tmp1」とするとファイル tmp1 に情報が出力される。「less tmp1」や「cat tmp1」コマンドによりファイルの中身を確認しよう。

■ コマンドラインとパイプ

cal コマンドと wc コマンド

コマンド「cal」は、今月のカレンダーを表示するコマンドである。

実行例
% cal
      4月 2004
日 月 火 水 木 金 土 
             1  2  3
 4  5  6  7  8  9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30

コマンド「wc」は、入力の行数、単語数、および、文字数を数えるコマンドである。

コマンド1の標準出力とコマンド2の標準入力を繋ぐ(パイプ「|」)

今月のカレンダーの単語数を数えるためには、コマンドライン上で次のように実行する。

% cal | wc
     8      39     140

出力の意味は、8が行数、39が単語数、140が文字数、である。月と年、それから、曜日名の表示で 9 単語ぶんあるので、単語数から 9 を引くと 30となり、日数がわかる。

ある月の日数を出力するプログラムを作りなさい、という課題があるとき、閏年の計算方法を考える必要はなく、既存のプログラムを組み合わせるだけで実現できる。

具体的には、3つの数字のうち、2番目の数字から 9 を引くプログラムを作るだけでよい。たとえば、そのプログラムを「prac0301.c」として、コンパイルした結果を「a.out」とすると、コマンドライン上で、

% cal | wc | ./a.out

とすれば、日数が表示される。

■ fgets と sscanf

入力を受け取る関数 fgets

使用例:

char s[BUFSIZ];
fgets(s,BUFSIZ,stdin);

fgets関数で格納サイズを「10」と指定すると、最後のヌル文字「\0」のぶんがあるので、最大で9文字しか入らない。

任意の行数の入力を処理するサンプル:行番号を付けるプログラム ⇒ list0303.c

実行方法
% gcc list0303.c
% ./a.out < list0303.c

標準入力の終わりを判定するには、fgetsの返り値が NULL であるかどうかを調べる。

セキュリティーホール

★ 文字列を解析する関数 sscanf

使用例:

s = " 12 34 56";
sscanf(s, "%d %d %d",&a,&b,&c);

スペースが区切文字として解釈されて、a = 12、b = 34、c = 56 が代入される。

⇒ list0302.c

□ 課題1

ある年・月の日数を数えるプログラムを作れ。ただし、コマンドライン上で幾つかコマンドを組み合わせて良いこととする。(prac0301.c)

□ 課題2

曜日の順序、日付の順序を降順で表示する「いぢ悪カレンダー」を出力するプログラムを作成せよ。(prac0302.c)

実行例
% gcc prac0302.c
% cal 5 2004 | ./a.out
      5月 2004
土 金 木 水 火 月 日
 1
 8  7  6  5  4  3  2
15 14 13 12 11 10  9
22 21 20 19 18 17 16
29 28 27 26 25 24 23
               31 30

■ 宿題

課題1、および、課題2プログラムをプリントアウトし、各行にコメントを手書きする。コメント付きプログラムリストを提出せよ。

来週(5月6日)の授業開始時に集めます。


2004.4.19 by tokuhisa