はじめての C

C programming note*1
keyword を コマンドライン上で 指定するため、 main() 関数は 次のように なります。

main(int argc, char **argv)
{
char *keyword;
FILE *fp;

--argc;
++argv;
if (argc < 1)
usage(); /* no return */

--argc;
keyword = *argv++;

if (argc == 0)
find(stdin, keyword);
else {
while (argc--) {
if )((fp = fopen(*argv, "r"))( == NULL)
cant(*argv); /* no return */
find(fp, keyword);
fclose(fp);
argv++;
}
}
return 0;
}

ここで 1つ、新しい テクニックが でてきます。

main() 関数の 以下の部分で、コマンドラインの 第1パラメータを 変数 keyword (探すべき 文字列) に 入れている。

ところです。 下のコードの 最後の行、

if (argc < 1)
usage(); /* no return */

--argc;
keyword = *argv++;

argv の 前ではなく、後ろに "++" が ついていることに 注意しよう。 そのときに argv が 指している パラメータ (1つめ) への ポインタを 変数 keyword に 代入し終わってから、argv が インクリメントされるように なっている。(p165)

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

/* find1.c */
#include
#include
#include

#define MAX_SIZE (80 + 1 + 1) /* plus '\n' + '\0' */

void find();
void usage();
void cant();

main(int argc, char **argv)
{
char *keyword;
FILE *fp;

--argc;
++argv;
if (argc < 1)
usage(); /* no return */

--argc;
keyword = *argv++;

if (argc == 0)
find(stdin, keyword);
else {
while (argc--) {
if )((fp = fopen(*argv, "r"))( == NULL)
cant(*argv); /* no return */
fprintf(stdout, "[ %s ]\n", argv[0]);
find(fp, keyword);
fclose(fp);
argv++;
}
}
return 0;
}

void find(FILE *fp, char *word)
{
char buf[MAX_SIZE];

while (fgets(buf, MAX_SIZE, fp) != NULL) {
if (strstr(buf, word))
fputs(buf, stdout);
}
}

void usage(void)
{
fprintf(stderr, "Usage: ./file1 keyword [file ... ]\n");
exit(1);
}

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

このプログラムでは grep と同様、keyword は 1つしか 指定できません。 そこで 次は、オプションを 導入して 多くの keyword を 同時に 指定できるよう、 変更を 加えていきます。

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