╮(╯▽╰)╭,把以前用到的东西粘过来,搞CUI用到
1、 POSIX约定
下面是POSIX标准中关于程序名、参数的约定:
2、 命令行参数解析函数getopt()
getopt()函数声明如下:
#include <unistd.h>
int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg; extern int optind, opterr, optopt; |
该函数的argc和argv参数通常直接从main()的参数直接传递而来。optstring是选项字母组成的字串。如果该字串里的任一字符后面有冒号,那么这个选项就要求有选项参数。
当给定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包含了所发现的无效选项字符。,当optstring开头没有指定’:’时,无效选项 或缺参数都返回’?’
简单例子,测试带参选项与不带参选项,代码opt.c
#include<stdio.h> #include<unistd.h>
int main(int argc, char **argv){ char opc; //option char
while((opc=getopt(argc,argv,"abcd:"))>-1){ switch(opc){ case 'a' : printf("fuck a! optarg:%s optind:%d opterr:%d/n" ,optarg,optind,opterr);break; case 'b' : printf("fuck b! optarg:%s optind:%d opterr:%d/n" ,optarg,optind,opterr);break; case 'c' : printf("fuck c! optarg:%s optind:%d opterr:%d/n" ,optarg,optind,opterr);break; case 'd' : printf("fuck d! optarg:%s optind:%d opterr:%d/n" ,optarg,optind,opterr);break; case '?' : printf("fuck ?! optarg:%s optind:%d opterr:%d/n" ,optarg,optind,opterr);break; } } return; } |
测试结果。注意最后带参选项-d参数缺失时的处理,处理提示可自定义,后面会讲到。
[root@Amanda optest]# ./opt -a fuck a! optarg:(null) optind:2 opterr:1 [root@Amanda optest]# ./opt -a -b fuck a! optarg:(null) optind:2 opterr:1 fuck b! optarg:(null) optind:3 opterr:1 [root@Amanda optest]# ./opt -a -b -c fuck a! optarg:(null) optind:2 opterr:1 fuck b! optarg:(null) optind:3 opterr:1 fuck c! optarg:(null) optind:4 opterr:1 [root@Amanda optest]# ./opt -a -b -c -d ohyeah fuck a! optarg:(null) optind:2 opterr:1 fuck b! optarg:(null) optind:3 opterr:1 fuck c! optarg:(null) optind:4 opterr:1 fuck d! optarg:ohyeah optind:6 opterr:1 [root@Amanda optest]# ./opt -cb fuck c! optarg:(null) optind:1 opterr:1 fuck b! optarg:(null) optind:2 opterr:1 [root@Amanda optest]# ./opt -d ./opt: option requires an argument -- d fuck ?! optarg:(null) optind:2 opterr:1 |
当带参选项检查到无参数输入时,getopt()函数会首先提示” ./opt: option requires an argument -- d” 然后返回字符’?’赋值于opc。
如果不希望输出任何错误信息,或更希望输出自定义的错误信息。可以采用以下两种方法来更改getopt()函数的出错信息输出行为。
(1)在调用getopt()之前,将opterr设置为0,这样就可以在getopt()函数发现错误的时候强制它不输出任何消息;
(2)如果optstring参数的第一个字符是冒号,那么getopt()函数就会保持沉默,并根据错误情况返回不同字符,如下:
“无效选项” —— getopt()返回'?',由于optopt包含了无效选项字符(比如在上例中使用参数 –x等)。
“缺少选项参数” —— getopt()返回':',由于选项缺参(比如使用命令”./opt –d ”)。
如果optstring的第一个字符不是冒号,那么无论是无效选项还是缺少参数,getopt()都返回'?'。注意:存在一个问题是,假如使用”./opt -d -x”,这原本是选项-d参数缺失的情况,但getopt()会错误地把-x认为是-d的参数。
<!--[if !supportLists]-->3、 <!--[endif]-->对长选项的支持getopt_long()
20 世纪 90 年代,UNIX 应用程序开始支持长选项,即一对短横线、一个描述性选项名称,还可以包含一个使用等号连接到选项的参数。比如”-help”。
getopt_long() 是同时支持长选项和短选项的 getopt() 版本。下面是他们的声明:
#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);
struct option{ const char *name; //选项名,前面无短横线如’help version’等 int has_arg;//是否有参数;无0、有1、可选2 int *flag; int val; }; |
getopt_long()的前三个参数与上面的getopt()相同,第4个参数是指向option结构的数组,option结构被称为“长选项表”。longindex参数如果没有设置为 NULL,那么它就指向一个变量,这个变量会被赋值为寻找到的长选项在longopts中的索引值,这可以用于错误诊断。
Option结构中flag字段的含义,如果这个指针为NULL,那么 getopt_long()返回该结构val字段中的数值。如果该指针不为NULL,getopt_long()会使得它所指向的变量中填入val字段中的数值,并且getopt_long()返回0。如果flag不是NULL,但未发现长选项,那么它所指向的变量的数值不变;字段val的的含义,这个值是发现了长选项时的返回值,或者flag不是NULL时载入*flag中的值。典型情况下,若flag不是NULL,那么val是个真/假值,譬如1或0;另一方面,如果flag是NULL,那么 val通常是字符常量,若长选项与短选项一致,那么该字符常量应该与optstring中出现的这个选项的参数相同。
每个长选项在长选项表中都有一个单独条目,该条目里需要填入正确的数值。数组中最后的元素的值应该全是0。数组不需要排序,getopt_long()会进行线性搜索。函数getopt_long()的所有返回值含义如下。
返回值 含 义 0 getopt_long()设置一个标志,它的值与option结构中的val字段的值一样 1 每碰到一个命令行参数,optarg都会记录它 '?' 无效选项 ':' 缺少选项参数 'x' 选项字符'x',在选项中自由设定的 -1 选项解析结束 |
测试用例如下
#include<stdio.h> #include<unistd.h> #include<getopt.h>
int main(int argc, char **argv){ char opc; //option char struct option longopts[]={ {"help",no_argument,NULL,'h'}, {"version",no_argument,NULL,'v'}, {0,0,0,0} };
while((opc=getopt_long(argc,argv,"ab:",longopts,NULL))!=-1){ switch(opc){ case 'a' : printf("fuck a! optarg:%s optind:%d opterr:%d/n", optarg,optind,opterr);break; case 'b' : printf("fuck b! optarg:%s optind:%d opterr:%d/n", optarg,optind,opterr);break; case 'h' : printf("fuck h! optarg:%s optind:%d opterr:%d/n", optarg,optind,opterr);break; case 'v' : printf("fuck v! optarg:%s optind:%d opterr:%d/n", optarg,optind,opterr);break; case '?' : printf("fuck ?! optarg:%s optind:%d opterr:%d/n", optarg,optind,opterr);break; case ':' : printf("fuck :! optarg:%s optind:%d opterr:%d/n", optarg,optind,opterr);break; } } return; } |
测试结果如下:
[root@Amanda optest]# ./optlong -a --version fuck a! optarg:(null) optind:2 opterr:1 fuck v! optarg:(null) optind:3 opterr:1 [root@Amanda optest]# ./optlong --help fuck h! optarg:(null) optind:2 opterr:1 |
当flag不为NULL时,getopt_long*()会为你设置标记变量。如果flag不为NULL,时,getopt_long()可以自动为各选项所对应的标记变量设置标记,这样就能够将switch语句中的情况减少。