I\'m trying to write a program that can compare two files line by line, word by word, or character by character in C. It has to be able to read in command line options
Use getopt(), or perhaps getopt_long().
int iflag = 0;
enum { WORD_MODE, LINE_MODE } op_mode = WORD_MODE; // Default set
int opt;
while ((opt = getopt(argc, argv, "ilw") != -1)
{
switch (opt)
{
case 'i':
iflag = 1;
break;
case 'l':
op_mode = LINE_MODE;
break;
case 'w':
op_mode = WORD_MODE;
break;
default:
fprintf(stderr, "Usage: %s [-ilw] [file ...]\n", argv[0]);
exit(EXIT_FAILURE);
}
}
/* Process file names or stdin */
if (optind >= argc)
process(stdin, "(standard input)", op_mode);
else
{
int i;
for (i = optind; i < argc; i++)
{
FILE *fp = fopen(argv[i], "r");
if (fp == 0)
fprintf(stderr, "%s: failed to open %s (%d %s)\n",
argv[0], argv[i], errno, strerror(errno));
else
{
process(fp, argv[i], op_mode);
fclose(fp);
}
}
}
Note that you need to determine which headers to include (I make it 4 that are required), and the way I wrote the op_mode
type means you have a problem in the function process()
- you can't access the enumeration down there. It's best to move the enumeration outside the function; you might even make op_mode
a file-scope variable without external linkage (a fancy way of saying static
) to avoid passing it to the function. This code does not handle -
as a synonym for standard input, another exercise for the reader. Note that getopt()
automatically takes care of --
to mark the end of options for you.
I've not run any version of the typing above past a compiler; there could be mistakes in it.
For extra credit, write a (library) function:
int filter(int argc, char **argv, int idx, int (*function)(FILE *fp, const char *fn));
which encapsulates the logic for processing file name options after the getopt()
loop. It should handle -
as standard input. Note that using this would indicate that op_mode
should be a static file scope variable. The filter()
function takes argc
, argv
, optind
and a pointer to the processing function. It should return 0 (EXIT_SUCCESS) if it was able to open all the files and all invocations of the function reported 0, otherwise 1 (or EXIT_FAILURE). Having such a function simplifies writing Unix-style 'filter' programs that read files specified on the command line or standard input.