如何以更简洁的方式处理 C 命令行参数标志?

How to handle C command line argument flags in a neater way?

我有一小段 C 代码,它采用一组命令行参数 --help-h-d-o(每个对应地代表“Help”、“Hexadecimal”、“Decimal”、“Octal”),我根据传递的参数调用某些函数,-h 将调用 hexaFlag()-dh 将调用hexaFlag()decFlag()。但是,为了做到这一点,我使用了一个混乱的 if else 块。有没有更简单的方法来实现这一目标?我被告知要使用 switch 语句,但考虑到我每次都检查不同的条件,我不知道如何在这里使用它。

main()函数我指的代码:

int main(int argc, char* argv[]){

        if(argc == 1){
                printf("%s",usage());
                printf("Use --help for more options.\n");
        }
        else if(strcmp(argv[1], "--help") == 0){
                printf("%s", usage());
                printf("Options are:\n  -h = Hexadecimal values\n  -d = Decimal values\n  -o = Octal values\n  --help = Shows this message\n");
        }
        else if(strchr(argv[1], '-') != NULL){
                if(strchr(argv[1], 'h') != NULL){
                        hexaFlag(argc, argv);
                }
                if(strchr(argv[1], 'd') != NULL){
                        decFlag(2, argc, argv);
                }
                if(strchr(argv[1], 'o') != NULL){
                        octaFlag(argc, argv);
                }
        }
        else {
                decFlag(1, argc, argv);
        }
        return 0;
}

我的基本开关处理(示例),非常实用但可能不美观,是:

int main (int argc, char *argv[])
{
  int i=0, number, files=0;

  /* process switches;  other prms are considered files  (2)
     that are opened for input/output.  Files not  specified
     are taken as stdin and stdout. Prms can be in any order.
  */

  while (++i < argc)
    switch (argv[i][0]) {
      case '-': while (*++argv[i])
                  switch (*argv[i]) {
                  case 'N':
                        ++argv[i]; number= 0;
                        while (isdigit(*argv[i]))
                            number = number *10 + *argv[i]++ - '0';
                        argv[i]--;
                        break;

                    case 'P' : printf ("Prm: P\n"); break;
                    case 'O' : printf ("Prm: O\n"); break;
                    case 'o' : printf ("Prm: o\n"); break;
                  default :
                    printf ("Bad switch %c, ignored.\n",*argv[i]);
                  }
                break;

      default :
        switch (files) {
        case 0: if ((inf=fopen(argv[i],"r")) == 0)
                    pexit("Error opening input file %s.", argv[i]);
                files++; break;
        case 1: if ((outf=fopen(argv[i],"w")) == 0)
                    pexit ("Error creating output file %s.", argv[i]);
                files++; break;
        case 2: fprintf (stderr,"Too many file arguments: %s ignored.\n",argv[i]);
                break;
        } /* end switch files */
      } /* end switch argc */

    if (files <1) inf = stdin;
    if (files <2) outf = stdout;

我认为您应该稍微修改函数签名以使它们保持一致。这将允许你做类似的事情:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>

void hexaFlag(int x, int argc, char **argv) { printf("%d:%s\n", x, __func__); }
void decFlag(int x, int argc, char **argv)  { printf("%d:%s\n", x, __func__); }
void octaFlag(int x, int argc, char **argv) { printf("%d:%s\n", x, __func__); }

struct args {
        void (*f)(int, int, char **);
        int x;
};

void
parse_args(int argc, char *argv[], struct args *A) 
{
        int c;
        if( argc == 1 || !strcmp(argv[1], "--help") ){
                printf("usage: %s [-hdo] [--help] arg [arg...]\n",
                        basename(argv[0]));
                exit(EXIT_SUCCESS);
        }
        A->f = decFlag;
        A->x = 1;

        while( (c = getopt(argc, argv, "hdo")) != -1 ) {
                switch( c ){
                case 'h': A->f = hexaFlag; break;
                case 'd': A->f = decFlag; A->x = 2; break;
                case 'o': A->f = octaFlag; break;
                default:  exit(EXIT_FAILURE);
                }
        }
}

int
main(int argc, char* argv[])
{
        struct args A;
        parse_args(argc, argv, &A);
        A.f(A.x, argc, argv);
        return 0;
}

您可能不应该将 argc/argv 直接传递给辅助函数,但应该从它们中提取您需要的内容到 parse_args() 中的结构参数中。