はじめての C

C programming note*1
1つめの 課題が 思っていたより むずかしいので、行の始めに 番号をつける オプションだけを 追加して、プログラムを つくってみました*2
その前に keyword.txt を 作成、

$ vi keyword.txt
として、予約語を いくつか 記入、
while
if
for
こんなかんじで、コマンドライン上に 指定します、
$ ./find2r -n -f keyword.txt find2r.c
できあがった プログラムは こちら、
/* find2r.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE (80 + 1 + 1) /* plus '\n' + '\0' */
#define MAX_KEY_SIZE (40 + 1 + 1) /* plus '\n + '\0' */
#define MAX_KEY_COUNT 256
#define YES 1
#define NO 0

void find();
int readkey();
void freekey();
void usage();
void cant();

char *keyword[MAX_KEY_COUNT];
int key_n;
int n_flag = NO;

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

key_n = -1;
while (--argc > 0 && **++argv == '-') {
for (s = *argv + 1; *s != '\0'; s++) {
switch (*s) {
case 'n':
n_flag = YES;
break;
case 'f':
if (--argc > 0) {
if )((fp = fopen(*++argv, "r"))( == NULL)
cant(*argv); /* no return */
else {
key_n = readkey(keyword, fp);
fclose(fp);
}
}
break;
default:
freekey(key_n, keyword);
usage(); /* no return */
}
}
}

if (key_n == -1) {
if (argc <= 0)
usage(); /* no return */
--argc;
keyword[0] = strdup(*argv++);
key_n = 1;
}

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

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

cnt = 1;
while (fgets(buf, MAX_SIZE, fp) != NULL) {
cnt++;
for (i = 0; i < n; i++) {
if (strstr(buf, word[i])) {
if (n_flag == YES)
fprintf(stdout, "%04d: ", cnt);
fputs(buf, stdout);
break;
}
}
}
}

int readkey(char **key, FILE *fp)
{
char buf[MAX_KEY_SIZE];
int n;

n = 0;
while (fgets(buf, MAX_KEY_SIZE, fp) != NULL) {
buf[strlen(buf) - 1] = '\0';
key[n++] = strdup(buf);
}
return n;
}

void freekey(int n, char **key)
{
int i;

for (i = 0; i < n; i++)
free(key[i]);
}

void usage(void)
{
fprintf(stderr, "Usage: ./find2r keyword [file ... ]\n");
fprintf(stderr, " ./find2r -f keyfile [file ... ]\n");
fprintf(stderr, " ./find2r -n (display line number)\n");
exit(1);
}

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

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

*2:あとは 宿題と いうことで ...