Chinaunix首页 | 论坛 | 博客
  • 博客访问: 300424
  • 博文数量: 82
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 490
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-13 10:58
文章分类

全部博文(82)

文章存档

2018年(2)

2017年(9)

2016年(71)

我的朋友

分类: C/C++

2016-10-20 21:25:23

原型

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


argc
    argv中传入命令行参数数目

argv
    命令行参数指针数组

optstring(短选项)

    定义的快捷键选项,如”hc:k::W;”,表示定义了3个快捷键选项-h, -c-k。其中的c后边接一个冒号,表示c需要参数;k后边接两个冒号,表示k后边可以接参数,也可以不要参数。需要的所有快捷键必须在这里定义,否则其它快捷键将是非法的。 如果只有长选项,则optstring只能是空字符串"",不能是NULL。其中的”W;”选项由POSIX.2保留用于实现扩展,加上它的意思是可用-Whelp--help选项。

    如果选项前边有'+',如”+hc”,表示若出现参数前边没有选项的情况,则getopt_long()直接返回-1,不进行任何命令解析;如果选项前边有'-',如”-hc” 表示若出现参数前边没有选项的情况,则将该参数视为一个选项,并且getopt_long()直接返回1;如果optstring最前边是':'(当有'+''-'时,':'应该在它们后边),比如”:hc”或者”+:hc”,则当选项未带参数时,getopt_long()返回':'

    短选项若需要参数,则两种表示方式,-h arg或者-harg,中间有无空格无所谓。
    

longopts(长选项)

    longopts是一个二维数组,数组的每个元素是一个定义好的选项数组。其原型如下:
        
struct option {
        
const char *name;
        
int  has_arg;
        
int  *flag;
        
int  val;
        
};
    name表示长选项的名字,比如我们常用的--helphelphas_arg表示该选项后边是否应该接参数,0(或者no_argument)表示不跟参数,1(或者required_argument)表示必须跟参数,2(或者optional_argument)表示可以跟也可以不更参数。 flag是一个地址指针,若falg0,则getopt_long()返回val值;若flag不为0,而是一个整型变量的地址,则getopt_long()返回0,且*flag=val

    长选项若需要参数,则两种表示方式,--help arg或者--help=arg
    

longindex

    当longindex不为NULL时,*longindex指向一个整型变量。当解析过长选项时,*longindex的值就是该长选项在longopts数组的位置。
    

其它变量
    (1)optopt,如果--x之类的参数无法使识别,则optopt=0;如果-x之类的非法参数,optopt='x'
    (2)optarg,必选参数选项的参数的字符串指针。奇怪的是,当可选参数选项带有参数时,optarg并没有指向其参数。
    
(3)optind,下一个需要解析的选项的位置,开始解析时默认为1getopt_long()解析完所有选项之后,所有没有选项的参数将排到argv数组的最后,这时optind会指向argv数组中第一个没有选项的参数位置。
    
返回值
    解析完毕,getopt_long()返回-1;如果输入短选项正确,则返回短选项字符;如果输入不存在的选项,则返回’?’。其它返回值则参考上边介绍的optstring参数和longopts参数。

注意事项

    (1optstringlongopts一个表示短选项命令,一个表示长选项命令,他们是不相关的。可以只有长选项,也可以只有短选项。

    (2getopt_long()函数,每解析一个选项,在argv数组中的参数顺序就会变动一次,被解析过的选项(包括需要参数的选项的参数)会排到argv数组的前边,未解析过的选项和参数会排到后边。当解析完所有选项之后,没有选项的参数会全部排到argv数组的最后。

 
测试代码

  1. #include <iostream>
  2. #include <getopt.h>
  3. #include <cstdlib>

  4. int main(int argc, char **argv)
  5. {
  6.     int flag = 0;
  7.     const char * event[] = {"A1", "A2", "A3"};
  8.     
  9.     const char * opt_string = "hs:v::W;";
  10.     //const char* opt_string = "hs:v::"; //最前边加两点后,当选项未带参数时,getopt_long返回':'
  11.     static struct option long_options[] = {
  12.         {"go2", 0, 0, 'g'},
  13.         {"go3", 1, 0, 'o'}, //如果第三个参数falg=0,当输入长选项时第四个参数val是getopt_long返回的值,这里输入--go3,则返回'o'
  14.         {"size", 0, 0, 'g'},
  15.         {"unin", 2, 0, 'u'},
  16.         {"event1", 1, &flag, 0}, //如果第三个参数falg!=0,当输入长选项时第四个参数val的值将保存在第三个参数地址指向的变量中。
  17.         {"event2", 0, &flag, 1},
  18.         {"event3", 1, &flag, 2}
  19.     };
  20.     
  21.     //打印argv
  22.     std::cout << "(1)\n";
  23.     std::cout << "argv: ";
  24.     for (int i = 0; i < argc; ++i) {
  25.         std::cout << argv[i] << " ";
  26.     }
  27.     std::cout << "\n";
  28.     
  29.     int longindex;
  30.     int ch;
  31.     int count = 0;
  32.     std::cout << "\n(2)\n";
  33.     while(true)
  34.     {
  35.         std::cout << "[" << ++count << "]" << "\n";
  36.         ch = getopt_long(argc, argv, opt_string, long_options, &longindex);
  37.         if(ch == -1) {
  38.             std::cout << "break\n";
  39.             break;
  40.         }         
  41.         
  42.         //optind始终指向下一个选项
  43.         std::cout << "optind[" << optind << "] ";
  44.         if (argv[optind]) {
  45.             std::cout << argv[optind] << std::endl;        
  46.         } else {
  47.             std::cout << std::endl;
  48.         }

  49.         std::cout << "argv: ";
  50.         for (int i = 0; i < argc; ++i) {
  51.             std::cout << argv[i] << " ";
  52.         }
  53.         std::cout << "\n";
  54.         
  55.         //flag处不为0,即该处存放一个整型的指针,这个选项只能使用长选项--event1、--event2和--event3。
  56.         //使用该选项后,ch返回0,且val的值存储在flag中,通过val的值可以激发相应事件
  57.         if (ch == 0) {
  58.             std::cout << "getoption:";
  59.             std::cout << "< flag = " << flag << " , " << event[flag] << ">" << std::endl;
  60.         } else if(ch == 's') {
  61.             std::cout << "getoption:";
  62.             std::cout << "< -s , " << optarg << ">" << std::endl;
  63.         } else if(ch == 'h') {
  64.             std::cout << "getoption:";
  65.             std::cout << "< -h >" << std::endl;
  66.         } else if(ch == 'g') {
  67.             std::cout << "getoption:";
  68.             std::cout << "< --go2 > or < --size > " << std::endl;
  69.         } else if(ch == 'o') {
  70.             std::cout << "getoption:";
  71.             std::cout << "< --go3 , " << optarg << ">"
  72.                      << "< longindex, " << longindex << ">" << std::endl;
  73.         } else if(ch == 'u') {
  74.             std::cout << "getoption:";
  75.             std::cout << "< --unin >" << std::endl;
  76.         } else if(ch == 'v') {
  77.             std::cout << "getoption:";
  78.             std::cout << "< -v >" << std::endl;
  79.         } else if(ch == 1) {
  80.             std::cout << "getoption:";
  81.             std::cout << "< - >" << std::endl;
  82.         } else if(ch == '?') {
  83.             std::cerr << "error opt["<< char(optopt) //如果--x之类的参数无法使识别,则optopt=0;如果-x之类的非法参数,optopt='x'
  84.              << "], invalid option\n";
  85.             exit(1);
  86.         } else if(ch == ':') {
  87.             std::cerr << "opt["<< char(optopt)
  88.                      << "], missing option argument ':'\n";
  89.             exit(1);
  90.         } else {
  91.             std::cerr << "other option\n";
  92.             exit(1);
  93.         }
  94.         std::cout << "\n";
  95.     }

  96.     std::cout << "\n(3)\n";
  97.     //多余的参数会被移动到argv最后边,且optind指向多余的第一个参数
  98.     std::cout << "argv: ";
  99.     for (int i = 0; i < argc; ++i) {
  100.         std::cout << argv[i] << " ";
  101.     }
  102.     std::cout << "\n";

  103.     for(int i = optind; i < argc; ++i) {
  104.         std::cout << "optind[" << i << "] " << argv[i] << "\n"; //这里可以收集没有选项的参数
  105.     }    
  106.     std::cout << "\n";
  107.     
  108.     return 0;
  109. }

测试 "hs:v:: "

即替换const char * opt_string = "hs:v::W;";

1-h选项,无参数

[root@192 ch-16]# ./main  -h

(1)

argv: ./main -h

 

(2)

[1]

optind[2]

argv: ./main -h

getoption:< -h >

 

[2]

break

 

(3)

argv: ./main -h

 

2-s选项,有参数

[root@192 ch-16]# ./main  -s  kk

(1)

argv: ./main -s kk

 

(2)

[1]

optind[3]

argv: ./main -s kk

getoption:< -s , kk>  #optarg获得了参数

 

[2]

break

 

(3)

argv: ./main -s kk

 

-s选项,无参数,getopt_long()返回?,且打印一句错误信息

[root@192 ch-16]# ./main  -s

(1)

argv: ./main -s

 

(2)

[1]

./main: option requires an argument -- 's'  #打印的需要参数的错误信息

optind[2]

argv: ./main -s

error opt[s], invalid option  #返回问号, 错误选项在optopt全局变量中

 

3-v 参数可选选项,有参数。解析完之后,optind全局变量指向了abc参数。这里很奇怪,因为-v是可选参数,既然添加了参数就应该将abc视为-v的参数。而最后optind指向了abc,表示在这里将-v视为了无参数选项。

[root@192 ch-16]# ./main -v abc

(1)

argv: ./main -v abc

 

(2)

[1]

optind[2] abc

argv: ./main -v abc

getoption:< -v >

 

[2]

break

 

(3)

argv: ./main -v abc

optind[2] abc  #abc被视为了无选项的参数

 

  -v 参数选项可选,无参数。

[root@192 ch-16]# ./main  -v

(1)

argv: ./main -v

 

(2)

[1]

optind[2]

argv: ./main -v

getoption:< -v >

 

[2]

break

 

(3)

argv: ./main -v

 

测试 ‘:’

即替换const char * opt_string = ":hs:v::W;";

1-s 参数必选参数选项,无参数。因为opt_string最前边有冒号,所以当必选参数选项未带参数时,getopt_long()函数并不返回’?’,而是返回’:’

[root@192 ch-16]# ./main -s

(1)

argv: ./main -s

 

(2)

[1]

optind[2]

argv: ./main -s

opt[s], missing option argument ':'  #必选参数选项-s未带参数,getopt_long()函数返回冒号

 

测试 ‘+’

即替换const char * opt_string = "+:hs:v::W;";

1-s 参数必选参数选项,无参数。因为opt_string最前边有冒号,且冒号在+号之后,所以当必选参数选项未带参数时,getopt_long()函数并不返回’?’,而是返回’:’

[root@192 ch-16]# ./main –s

(1)

argv: ./main -s

 

(2)

[1]

optind[2]

argv: ./main -s

opt[s], missing option argument ':'  #必选参数选项-s未带参数,getopt_long()函数返回冒号

 

2)因为opt_string最前边有’+’号,所以当出现参数时,getopt_long()函数并不返回直接返回-1。从下边的例子可以看到abc后边的-h没有执行,就直接返回-1了。

[root@192 ch-16]# ./main  abc  -h

(1)

argv: ./main abc -h

 

(2)

[1]

break  #直接返回-1,退出

 

(3)

argv: ./main abc -h

optind[1] abc

optind[2] -h

 

测试 ‘-’

即替换const char * opt_string = "-:hs:v::W;";

1)当短选项最前边有’-’时,getopt_long()会将没有选项的参数视为选项,且getopt_long()会返回1

[root@192 ch-16]# ./main  abc  -h

(1)

argv: ./main abc -h

 

(2)

[1]

optind[2] -h

argv: ./main abc -h

getoption:< - >  # 这个输出是当getopt_long()返回1时输出的

 

[2]

optind[3]

argv: ./main abc -h

getoption:< -h >

 

[3]

break

 

(3)

argv: ./main abc -h

 

测试长选项

即替换const char * opt_string = "hs:v::W;";

1--go2 --size,这两个选项在longopts中的has_tagflag字短都为0,表示都不需要参数且getopt_long()返回都是val字段。由于val字段都是’g’,所以返回都相同。

[root@192 ch-16]# ./main  --go2  --size

(1)

argv: ./main --go2 --size

 

(2)

[1]

optind[2] --size

argv: ./main --go2 --size

getoption:< --go2 > or < --size >  #返回了’g’时的打印

 

[2]

optind[3]

argv: ./main --go2 --size  

getoption:< --go2 > or < --size >  #返回了’g’时的打印

 

[3]

break

 

(3)

argv: ./main --go2 --size

 

2)当短选项中有W;时,长选项比如--go2可以由-Wgo2表示

[root@192 ch-16]# ./main --go2 -Wgo2

(1)

argv: ./main --go2 -Wgo2

 

(2)

[1]

optind[2] -Wgo2

argv: ./main --go2 -Wgo2

getoption:< --go2 > or < --size >

 

[2]

optind[3]

argv: ./main --go2 -Wgo2

getoption:< --go2 > or < --size >  #-Wgo2-go2返回结果相同

 

[3]

break

 

(3)

argv: ./main --go2 -Wgo2

 

3--go3必带参数,返回’o’;  --unin参数可选,但这里不知为何,添加参数依然未生效,--unin被当做了没有参数的选项。

[root@192 ch-16]# ./main  --unin  y  --go3  x

(1)

argv: ./main --unin y --go3 x

 

(2)

[1]

optind[2] y

argv: ./main --unin y --go3 x

getoption:< --unin >

 

[2]

optind[5]

argv: ./main --unin y --go3 x

getoption:< --go3 , x>< longindex, 1>

 

[3]

break

 

(3)

argv: ./main --unin --go3 x y

optind[4] y   #optind最后指向了y,说明—unin被当成了无参数选项处理

 

4--event1--event2--event3flag字段都是一个整型变量的地址,所以getopt_long()返回0,且val字段的值被赋给flag指向的地址空间。

[root@192 ch-16]# ./main --event1 x --event2 --event3 y

(1)

argv: ./main --event1 x --event2 --event3 y

 

(2)

[1]

optind[3] --event2

argv: ./main --event1 x --event2 --event3 y

getoption:< flag = 0 , A1>

 

[2]

optind[4] --event3

argv: ./main --event1 x --event2 --event3 y

getoption:< flag = 1 , A2>

 

[3]

optind[6]

argv: ./main --event1 x --event2 --event3 y

getoption:< flag = 2 , A3>

 

[4]

break

 

(3)

argv: ./main --event1 x --event2 --event3 y

 


阅读(1880) | 评论(0) | 转发(0) |
0

上一篇:struct rlimit

下一篇:c/c++编译警告和错误

给主人留下些什么吧!~~