参数的解析:getopt_long
getopt_long
可以解析短参数(-a -b -c)和长参数(--add --delete --create),其定义在getopt.h中。
函数:
int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *indexptr)
参数:
argv:需要解析的参数字符串
argc:argv中字符串的数量
shortopts: 支持的短参数的字符串
longopts: 支持长参数的struct option集合
indexptr: *indexptr表明参数在longopts中的索引位置。
struct option { const char *name; //长参数名 /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; //no_argument(0),required_argument(1),optional_argument(2)
int *flag; // 如果flag非NULL,则会将val保存至*flag中,当做标志。 int val; // 短参数名 };
全局变量:
(1)optarg:表示当前选项对应的参数值。
(2)optind:表示的是下一个将被处理到的参数在argv中的下标值。
(3)optopt:表示没有被未标识的选项。
完整代码如下:
#include <stdio.h> #include <stdlib.h> #include <getopt.h> /* Flag set by ‘--verbose’. */ static int verbose_flag; opterr = 1; int main(int argc, char **argv) { int c; static struct option long_options[] = { /* These options set a flag. */ {"verbose1", no_argument, &verbose_flag, 1}, {"verbose2", no_argument, &verbose_flag, 2}, {"verbose3", no_argument, &verbose_flag, 3}, {"brief", no_argument, &verbose_flag, 0}, /* These options don’t set a flag. We distinguish them by their indices. */ {"add", no_argument, 0, 'a'}, {"append", no_argument, 0, 'b'}, {"delete", required_argument, 0, 'd'}, {"create", required_argument, 0, 'c'}, {"file", required_argument, 0, 'f'}, {0, 0, 0, 0}}; /* getopt_long stores the option index here. */ int option_index = 0; char shortOpt[512] = {0}; int cnt = 0; for (int i = 0; i < sizeof(long_options) / sizeof(struct option); i++) { if (long_options[i].val >= 'a' && long_options[i].val <= 'z') { shortOpt[cnt++] = long_options[i].val; if (long_options[i].has_arg == required_argument) { shortOpt[cnt++] = ':'; } else if (long_options[i].has_arg == optional_argument) { shortOpt[cnt++] = ':'; shortOpt[cnt++] = ':'; } } } printf("line: [%d] shortOpt[%s]\n", __LINE__, shortOpt); while (1) { c = getopt_long(argc, argv, shortOpt, long_options, &option_index); /* Detect the end of the options. */ if (c == -1) break; printf("optind[%d],argc[%d]\n", optind, argc); printf("optarg=%s\n", optarg); if (optind < argc) { printf("next optarg=%s\n", argv[optind]); } switch (c) { case 0: /* If this option set a flag, do nothing else now. */ if (long_options[option_index].flag != 0) break; printf("option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); break; case 'a': puts("option -a\n"); break; case 'b': puts("option -b\n"); break; case 'c': printf("option -c with value `%s'\n", optarg); break; case 'd': printf("option -d with value `%s'\n", optarg); break; case 'f': printf("option -f with value `%s'\n", optarg); break; case '?': /* getopt_long already printed an error message. */ break; default: abort(); } } /* Instead of reporting ‘--verbose’ and ‘--brief’ as they are encountered, we report the final status resulting from them. */ if (verbose_flag) printf("verbose flag is set:%d\n", verbose_flag); /* Print any remaining command line arguments (not options). */ if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) printf("%s ", argv[optind++]); putchar('\n'); } exit(0); }