getopt_long()----命令行参数解析函数使用详解

来源:互联网 发布:电脑弹钢琴软件 编辑:程序博客网 时间:2024/05/17 22:21

为什么需要命令行解析函数?

当一个用C语言编写的Linux或UNIX程序运行时,它是从main函数开始的。函数声明可以如下:

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

其中argc是程序参数的个数,argv是一个代表参数自身的字符串数组。无论操作系统何时启动一个新程序,参数argc和argv都被设置并传递给main。这些参数通常由另一个程序提供,这个程序一般是shell,它要求操作系统启动该程序。shell接收用户输入的命令行,将命令行分解成单词,然后把这些单词放入argv数组。

例如,如果我们给shell输入如下命令:

$./myprog left right 'and center'

程序myprog将从main函数开始,main的参数值是:

argc:4    argv:{"myprog", "left", "right", "and center"}

注意:参数个数包括程序名自身,argv数组也包含程序名并将它作为第一个元素argv[0]。因为我们在shell命令里使用了引号,所以第四个参数是一个包含了空格的字符串。

在编程的时候,当命令行参数个数较多时,如果按照顺序一个一个定义参数含义很容易造成混乱;如果程序只按顺序处理参数的话,一些“可选参数”的功能将很难实现。为了解决此类问题,GNU C库提供了函数以简化C/C++程序中的解析工作。

getopt_long(int argc, char* argv[], const char *optstring, const struct option *longopts, int *longindex);

注意:getopt头文件为unistd.h,getopt_long额外支持长参数解析,头文件为getopt.h

参数optstring:负责处理短参数。也称为选项指定符字符串,该字符串告诉getopt哪些选项可用,以及它们是否有关联值。optstring只是一个字符列表,每个字符代表一个单字符选项。如果一个字符后面紧跟一个冒号,则表明该选项有一个关联值作为下一个参数。

例:

char *optstring = “abcd:”; 
上面这个optstring在传入之后,getopt函数将依次检查命令行是否指定了 -a, -b, -c及 -d(需要多次调用getopt函数,直到其返回-1),当检查到上面某一个参数被指定时,函数会返回被指定的参数名称(即该字母) 
最后一个参数d后面带有冒号,:表示参数d是可以指定值的,如 -d 100 或 -d user

参数longopts负责处理长参数。指向一个由option结构体组成的数组,那个数组的每一个元素都指明了一个长参数(形如”–name”的参数)名称和性质

struct option {    const char* name;    int has_arg;    int *flag;    int val;}
struct option的解析:

name:参数名称

has_arg:指明是否带参数值,数值可选:

no_argument(即 0)表明这个长参数不带参数(即不带数值,如:--name)required_argument (即 1) 表明这个长参数必须带参数(即必须带数值,如:--name Bob)optional_argument(即 2)表明这个长参数后面带的参数是可选的,(即--name和--name Bob均可)
flag:设置为NULL表示当找到该选项时,getopt_long返回在成员val里给出的值。否则,getopt_long返回0,并将val的值写入flag指向的变量。

val:getopt_long为该选项返回的值。


参数longindex:如果longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值。

外部变量optarg:在getopt_long循环处理选项时,如果选项有一个关联值,则外部变量optarg指向这个值。

外部变量optind:下一个要读取的参数的下标位置


test.c 完整范例:

/*在linux下编写的,没安装中文输入法,所以用蹩脚的英文写的注释,懒得删除了*/#include <stdio.h>#include <getopt.h>int main(int argc, char *argv[]){/*getopt_long(int argc, char* argv[], const char* optstring, const struct option* longopts, int longindex)*//*optstringthe ':" after char means it can add a argument字符后面的 : 表示后面可以加参数比如 -u 100*/char *optstring = "u:d:l:r:t";int up = 0;int down = 0;int left = 0;int right = 0;int turn = 0;/*longopts1. name : argument name2. has_arg : whether need a argument3. flag : when it is NULL,getopt_long() will return the 'val';or getopt_long() will set the flag with 'val4. val : which will use with flag这里就是定义一个结构option数组,第一个参数是名字第二个参数是选择是否需要加参数,选择是了就可以比如 -up 100 第三个参数flag, 如果是空值,getopt_long()就会返回第四个参数val;如果给的有地址,比如&turn,getopt_long()就会把val的值写入这个地址,返回0第四个参数val*/struct option long_opts[] = {{"up", required_argument, NULL, 'u'},{"down", required_argument, NULL, 'd'},{"left", optional_argument, NULL, 'l'},{"right", required_argument, NULL, 'r'},{"turn", no_argument, &turn, 1},{NULL, no_argument, NULL, 0}  };int opt = 0;int options_index = 0;/*反复循环来解析参数,getopt_long执行一次会解析一个参数,如果没有参数就返回-1如果该参数有值,比如-u 100,则optarg = 100, optind会指向下一个要解析的参数的数组下标*/while((opt = getopt_long(argc, argv, optstring, long_opts, &options_index)) != EOF){//optarg is not nullif (optarg)printf("opt = %d,optarg = %d,optind = %d\n", opt, atoi(optarg), optind);elseprintf("opt = %d\n", opt);switch(opt){case 0 :break;case 'u' : if(optarg)up = atoi(optarg);break;case 'd' :if(optarg)down = atoi(optarg);break;case 'l' :if(optarg)left = atoi(optarg);break;case 'r' : if(optarg)right = atoi(optarg);break;case 't' :turn = 1;break;}}if(turn)printf("turn,up %d step,down %d step,left %d step,right %d step\n", up, down, left, right);elseprintf("no turn,up %d step,down %d step,left %d step,right %d step\n", up, down, left, right);}
运行截图:

在测试的时候我发现一个问题,把option的has_arg的值设为optional_argument时候,并没有成为可选,而是没法识别后面的参数,大家可以试一下。

如果有知道为什么的希望可以告知~谢谢!!!

参考文章:http://blog.csdn.net/feglass/article/details/51468857


1 0
原创粉丝点击