Parsing command-line arguments in C?

后端 未结 12 795
眼角桃花
眼角桃花 2020-11-22 16:23

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

12条回答
  •  耶瑟儿~
    2020-11-22 16:58

    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.

提交回复
热议问题