1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 命令行参数解析函数 getopt getopt_long

命令行参数解析函数 getopt getopt_long

时间:2018-07-22 19:44:44

相关推荐

命令行参数解析函数 getopt getopt_long

getopt 函数在头文件 <unistd.h> 中,它可以解析我们传入的命令行参数。 可以实现类似gcc -orm -rf等命令。

man 3 getopt。在线版:/?topic=getopt&section=3

#include <unistd.h>int getopt(int argc, char * const argv[],const char *optstring);extern char *optarg;extern int optind, opterr, optopt;#include <getopt.h>int getopt_long(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);int getopt_long_only(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);Feature Test Macro Requirements for glibc (see feature_test_macros(7)):getopt(): _POSIX_C_SOURCE >= 2 || _XOPEN_SOURCEgetopt_long(), getopt_long_only(): _GNU_SOURCE

使用说明:getopt函数在main()函数中argv携带的参数中进行匹配,以-为标记。

短参数:-a-ab-a -b。其中短参数如果有值的话,可以使用空格分隔,也可以写在一起。例如head -n10等效head -n10。长参数 :--version。长参数后面如果携带值,可以使用空格分隔,或使用=链接。

getopt

#include <unistd.h>int getopt(int argc, char * const argv[],const char *optstring);extern char *optarg;extern int optind, opterr, optopt;

对于 getopt() 函数而言,argc和argv参数通常直接从main()的参数直接传递而来。optstring是预处理的可选选项组成的字符串。

optstring:

getopt函数会在argv中进行字符匹配,匹配所使用的参数集合是定义在optstring 中的字母。

如果选项字符串里的字母后接着冒号":",则表示还有相关的参数,全域变量optarg 即会指向此额外参数。如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt 设为"?"字符, 如果不希望getopt()印出错信息,则需要将全域变量opterr 设为0 。如果后面两个冒号,表示后面可以有参数也可以没有参数,但是如果有参数,参数和选项之间不能有空格

当给定getopt()命令参数的数量 (argc)、指向这些参数的数组 (argv) 和选项字串 (optstring) 后,getopt() 将返回第一个选项,并设置一些全局变量。使用相同的参数再次调用该函数时,它将返回下一个选项,并设置相应的全局变量。如果不再有可识别的选项,将返回 -1,此任务就完成了。

getopt() 所设置的全局变量包括:

char *optarg

当前选项参数字串(如果有)。int optind

argv的当前索引值。当getopt()在while循环中使用时,循环结束后,剩下的字串视为操作数,在argv[optind]至argv[argc-1]中可以找到。int opterr

这个变量非零时,getopt()函数为“无效选项”和“缺少参数选项,并输出其错误信息。int optopt

当发现无效选项字符之时,getopt()函数或返回’?‘字符,或返回’:'字符,并且optopt包含了所发现的无效选项字符。

需要知道的是,getopts会默认将argv排列,使得选项在前,而非选项的参数放在最后。这样当getopts读取完所有的选项以后,optind会指向非选项的参数。

#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main (int argc, char **argv){for(int i = 0; i < argc; ++i)printf("%s ",argv[i]);printf("\n");int c;while( -1 != (c = getopt (argc, argv, "abc:"))){;}for(int i = 0; i < argc; ++i)printf("%s ",argv[i]);printf("\n");return 0;}

示例程序:

#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>intmain (int argc, char **argv){int aflag = 0;// 如果输入 -aint bflag = 0;// 如果输入-bchar *cvalue = NULL;// 输入 -c xxxx,保存c选项对应的值int index;int c;opterr = 0;// 错误标记:标记“无效选项”和“缺少参数选项”while ((c = getopt (argc, argv, "abc:")) != -1)switch (c){case 'a':aflag = 1;break;case 'b':bflag = 1;break;case 'c':cvalue = optarg;// 接收c选项的对应的值,如果没有值则下一次getopt返回‘?’break;case '?':if (optopt == 'c')fprintf (stderr, "Option -%c requires an argument.\n", optopt);else if (isprint (optopt))// 检测一个字符是否是可打印字符fprintf (stderr, "Unknown option `-%c'.\n", optopt);else// 如果不可打印,输出其ascii值fprintf (stderr,"Unknown option character `\\x%x'.\n",optopt);return 1;default:abort ();}// getopt 匹配完毕,输出参数获取情况printf ("aflag = %d, bflag = %d, cvalue = %s\n",aflag, bflag, cvalue);// 将剩余的没有匹配到的参数打印出来for (index = optind; index < argc; index++)printf ("Non-option argument %s\n", argv[index]);return 0;}

编译并执行:

gcc -Wall -o opt opt.c./opt

1.无参、-a、-b、-ab、-a -b

2.使用c参数。参数c在代码中设置为c:需要对应数值。

3.关于参数对应的值,我们可以将他们紧挨着一起写,也可以使用空格分隔开。同时我们发现如果多次调用 -c 参数,cvalue的值会被覆盖(每次optarg匹配一个值,为了避免被覆盖我们可以使用数据结构将其保存起来,例如st.push(optacg))。

全部执行情况:

% ./optaflag = 0, bflag = 0, cvalue = (null)% ./opt -a -baflag = 1, bflag = 1, cvalue = (null)% ./opt -abaflag = 1, bflag = 1, cvalue = (null)% ./opt -c fooaflag = 0, bflag = 0, cvalue = foo% ./opt -cfooaflag = 0, bflag = 0, cvalue = foo% ./opt arg1aflag = 0, bflag = 0, cvalue = (null)Non-option argument arg1% ./opt -a arg1aflag = 1, bflag = 0, cvalue = (null)Non-option argument arg1% ./opt -c foo arg1aflag = 0, bflag = 0, cvalue = fooNon-option argument arg1% ./opt -a -- -baflag = 1, bflag = 0, cvalue = (null)Non-option argument -b% ./opt -a -aflag = 1, bflag = 0, cvalue = (null)Non-option argument -

示例2:写一个程序,要求从命令行传入数据,将其累加结果输出到屏幕上。

#include <iostream>#include <cstring>#include <vector>using namespace std;// 对vector元素求和int add(vector<int>& vec){int sum = 0;for(const int & v : vec){sum += v;}return sum;}int main(int argc, char* argv[]){if(argc <= 1){cout << "please input list-nums. \n ./add 1 2 3 4" << endl;return 0;}vector<int> vec;for(int i = 0; i < argc; ++i){if(strspn(argv[i], "0123456789") != strlen(argv[i]))continue;// 只接受数字int num = stoi(argv[i]); // 将‘1’转为1vec.push_back(num); // 添加到vec中}if(!vec.empty()){cout << "total sum = " << add(vec) << endl;}return 0;}

如果将它改造成,接收以-开头的参数,则代码应该这样写。

#include <iostream>#include <unistd.h>#include <cstring>#include <vector>using namespace std;// 帮助字符串,提示该程序的参数const char* helpstr ={R"(Help:Example "-l": ./opt -l 1 2 3 4 5 6Output: total sum = 21Example "-v":./opt -l 1,2,3,4,5,6Output: nums:{ 1, 2, 3, 4, 5, 6 }total sum = 21)"};// 从命令行接收数据,print 参数表示是否在录入数据时打印到屏幕上void input(vector<int>& vec, int argc, char* argv[], bool print = false){if(print) cout << "nums:{ " ;for(int i = optind - 1; i < argc; ++i){if(strspn(argv[i], "0123456789") != strlen(argv[i]))continue;// 只接受数字int num = stoi(argv[i]); // 将‘1’转为1vec.push_back(num); // 添加到vec中if(print) cout << num << ", "; // 根据参数决定是否打印}if(print) cout << "\b\b }" << endl;}// 对vector元素求和int add(vector<int>& vec){int sum = 0;for(const int & v : vec){sum += v;}return sum;}int main(int argc, char* argv[]){if(argc <= 1){cout << "please input list-nums. \n ./opt -l 1 2 3 4" << endl;return 0;}vector<int> vec;bool list_flag = false;// 是否输入了 -lbool view_flag = false;// 是否输入了 -vint opt;// 接收命令行 `-` 开头的参数while ((opt = getopt (argc, argv, "hvl::")) != -1)switch(opt){case 'h':cout << helpstr << endl;break;case 'v': // 显示输入的元素,即vec的元素view_flag = true;break;case 'l': // 使用 ./opt -l 1 2 3 4 5 6 的方式输入元素list_flag = true;break;case '?':case ':':default:break;}if(list_flag){// 如果使用了 -l 参数,计算求和结果input(vec, argc, argv, view_flag);cout << "total sum = " << add(vec) << endl;}return 0;}

-h、-l、-v参数展示

getopt_long

#include <getopt.h>int getopt_long(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);int getopt_long_only(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);

getopt long()函数的工作原理与getopt()类似,只是它也接受以两个减号开始的长选项。(如果程序只接受长选项,那么optstring应该指定为空字符串(""),而不是NULL。)

如果缩写是唯一的,或者与某个已定义的选项精确匹配,则长选项名称可以缩写。长选项可以带有一个形式为--arg=param--arg param的参数。

Longopts是指向<getopt.h>中声明的struct option数组的第一个元素的指针

struct option {const char *name;int has_arg;int *flag;int val;};

不同字段的含义是:

name :是长选项的名称。

has_arg :如果选项不带参数,则使用no_argument(或0);

如果选项需要参数,则使用required_argument(或1);

如果该选项带有可选参数,则使用optional_argument(或2)

flag :Flag指定如何返回长选项的结果。

如果flag为NULL,那么getopt_long()返回val。(例如,调用程序可能将val设置为等效的短选项字符)。

否则,getopt_long()返回0,并且flag指向一个变量,如果找到该选项则将该变量设置为val,但如果没有找到该选项则保持不变。

val : 是要返回的值,或装入由标志所指向的变量中的值

注意:

数组的最后一个元素必须填充零。如果longindex不是NULL,它指向一个变量,该变量被设置为long选项相对于longopts的索引。

getopt_long_only()类似于getopt_long(),但是’-‘和"–"可以表示一个长选项。如果以’-’(而不是"–")开头的选项不匹配长选项,但匹配短选项,它将被解析为短选项。

#include <stdio.h>/* for printf */ #include <stdlib.h> /* for exit */ #include <getopt.h>int main(int argc, char **argv) {int c;int digit_optind = 0;while (1) {int this_option_optind = optind ? optind : 1;int option_index = 0;static struct option long_options[] = {{"add",required_argument, 0, 0 },// 需要参数,flag=null,则返回val的值0{"append", no_argument, 0, 0 },// 不需要参数,返回val的值0{"delete", required_argument, 0, 0 },// 需要参数,返回val的值0{"verbose", no_argument, 0, 0 },// 不需要参数,返回val的值0{"create", required_argument, 0, 'c'},// 需要参数,返回val的值 ‘c’ 。等效-c选项{"file", required_argument, 0, 0 },// 需要参数,返回val的值 0{0, 0, 0, 0 }// 最后一行元素填充0};c = getopt_long(argc, argv, "abc:d:012",long_options, &option_index);if (c == -1)// 无参数可匹配了break;switch (c) {case 0:// 本例中接收长参数(-create参数除外)printf("option %s", long_options[option_index].name);if (optarg)printf(" with arg %s", optarg);printf("\n");break;case '0':case '1':case '2':if (digit_optind != 0 && digit_optind != this_option_optind)printf("digits occur in two different argv-elements.\n");digit_optind = this_option_optind;printf("option %c\n", c);break;case 'a':printf("option a\n");break;case 'b':printf("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 '?':break;default:printf("?? getopt returned character code 0%o ??\n", c);}}if (optind < argc) {printf("non-option ARGV-elements: ");while (optind < argc)printf("%s ", argv[optind++]);printf("\n");}exit(EXIT_SUCCESS); }

1.接收短参数

2.接收带值的短参

3.长参数映射到 -0 选项。注意,长参数设定为 required_argument 的需要指定一个参数值,使用“=”连接或空格都可以。

4.getopt_long也可以识别长选项的简写,但需要保证简写可以唯一标识某个长选项。例如 --hello 与 --help 这两个长参数无法通过 --he 或 --hel 区分。

示例2:引用自:/p/e46a37d7b776

#include <unistd.h>#include <stdio.h>#include <getopt.h>int main(int argc, char **argv){int opt, lopt, loidx;const char *optstring = "ab:c::d:t";const struct option long_options[] ={// 使用--help等参数后,getopt_long()函数返回0,同时将val对应的值赋值到lopt变量中{"help", no_argument, &lopt, 1},// getopt_long()返回0,lopt被赋值为1{"version", no_argument, &lopt, 2},// ..{"infile", required_argument, &lopt, 3},{"outfile", required_argument, &lopt, 4},{"logfile", optional_argument, &lopt, 5},{"tttt", no_argument, 0 , 't'},// 等价于使用 -t 选项{0, 0, 0, 0}};while((opt = getopt_long(argc, argv, optstring, long_options, &loidx)) != -1){if(opt == 0)// long_options[x].flag非空时,getopt_long()函数返回0opt = lopt;// long_options[x].flag所执行的变量被赋值为long_options[x].val switch(opt){case 'a':printf("opt a==%c\n", opt);break;case 'b':printf("opt b==%c, arg: %s\n", opt, optarg);break;case 'c':printf("opt c==%c, arg: %s\n", opt, optarg);break;case 'd':printf("opt d==%c, arg: %s\n", opt, optarg);break;case 't':printf("opt t==%c\n", opt);printf("\"-t\" equivalent \"--tttt\"\n");break;case 1:printf("opt help==%d\n", opt);break;case 2:printf("opt version==%d\n", opt);break;case 3:printf("opt infile==%d arg: %s\n", opt, optarg);break;case 4:printf("opt outfile==%d arg: %s\n", opt, optarg);break;case 5:printf("opt logfile==%d arg: %s\n", opt, optarg);break;default:printf("error opt %c", opt);return -1;}}return 0;}$ g++ -o test test.cpp$ ./test --helpopt help==1$ ./test --help --infilept help==1./test: option '--infile' requires an argumenterror opt x$ ./test --help --infile 123opt help==1opt infile==3 arg: 123

1.普通短参数

2.长参数 -tttt 和 与之等效的短参数 -t

3.长参数

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。