Page 165
Modify the pattern finding program of Chapter 5 to take its input from a set of named files or, if no files are named as arguments, from the standard input. Should the file name be printed when a matching line is found?
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define MAXLINE 1000
#define MAXFILES 16
#define STDIN "stdin"
int main(int argc, char *argv[])
{
char line[MAXLINE];
long lineno = 0;
int c, found = 0;
bool except = false, number = false;
char *file_names[MAXFILES];
char **fn = file_names;
char *pattern = NULL;
*fn = STDIN;
if (argc < 2) {
puts("error: not enough arguments");
return 1;
}
while (--argc > 0) {
if ((*++argv)[0] == '-') {
while ((c = *++argv[0])) {
switch (c) {
case 'x':
except = 1;
break;
case 'n':
number = 1;
break;
default:
printf("error: illegal option %c\n", c);
argc = 0;
found = -1;
break;
}
}
} else if (pattern == NULL) {
pattern = *argv;
} else {
*fn++ = *argv;
}
}
FILE *fp;
int file_count = fn - file_names;
for (int i = 0; i < file_count; i++) {
lineno = 0;
if (strcmp(file_names[i], STDIN) == 0) {
fp = stdin;
} else {
fp = fopen(file_names[i], "r");
}
if (fp == NULL) {
printf("error: unable to read file %s\n",
file_names[i]);
} else {
while (fgets(line, MAXLINE, fp) != NULL) {
lineno++;
if ((strstr(line, pattern) != NULL) != except) {
if (number) {
printf("%ld:", lineno);
}
printf("%s", line);
found++;
}
}
}
}
}