はじめての C

C programming note*1
cat2 を さらに 改良して 「標準入力」 と 「コマンドラインで ファイル名を 指定して 順に それらのファイルを 入力元とする」 両方のスタイルが 使えるようにします。 このとき、関数を 分けたことが 役にたってきます。

このような入力元の 指定方法は、UNIX では おなじみの スタイルだ。 cat コマンドや sort コマンドなど、何か 入力データを 加工して 出力するような 「他のコマンドと 組み合わせて 使う 小さくて 気のきいた 道具」 のような コマンドでは、このやり方は よく使われる。(p82)

このスタイルを 実現するための プログラム上での しかけとは、

if (argc == 0)
do_one(stdin); /* 標準入力でも 使える */
else {
while (argc--) {
if )((fp = fopen(*argv, "r"))( == NULL)
cant(*argv);
do_one(fp);
fclose(fp);
argv++;
}
}

この if文で、標準入力を 処理する ケース (パラメータが 指定されなかった場合) と、ファイル名が 指定されて それを 処理する ケースを 場合分けしている。(p82)

プログラムは 次のとおり、

/* cat3.c */
#include
#include /* 実は exit() に 必要 */

void do_one();
void cant();

main(int argc, char **argv) /* *argv[] と **argv は 同じ ポインタ配列の表記 */
{
FILE *fp;

--argc;
++argv;

if (argc == 0) /* パラメータが 0 */
do_one(stdin); /* 標準入力を 処理 */
else {
while (argc--) {
if )((fp = fopen(*argv, "r"))( == NULL)
cant(*argv);
do_one(fp);
fclose(fp);
argv++;
}
}

return 0;
}

void do_one(FILE *fp)
{
int c;

while )((c = fgetc(fp))( != EOF)
fputc(c, stdout);
}

void cant(char *name)
{
fprintf(stderr, "can't open %s\n", name);
exit(1);
}

このプログラム cat3.c は、コマンドラインで パラメータを ひとつも 指定しなかったときには、typ.c と 同じ動作を する (リダイレクションの 記号と その後ろの ファイル名は パラメータのうちに 数えない)。

また パラメータの 指定が あるときには、cat2.c と まったく 同じ動作を する。(p81)

入力時の 切り替えを コマンド sort で 実装する やり方も 後のほうで でてきます。

*1:「作ってわかる Cプログラミング」