linux/Unix系统调用之getopt()

来源:互联网 发布:淘宝店铺背景音乐推荐 编辑:程序博客网 时间:2024/06/06 03:42

getopt()解析命令行参数

使用前提:

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

函数说明:

       getopt()解析给定在参数argc和argv中的命令行参数集合。这两个参数通常是从main()函数的参数列表中获取。(当然也可以自行定义)参数optstring指定了函数应处理的命令行选项集合。此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母。如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,全域变量optarg 即会指向此额外参数。如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符,如果不希望getopt()印出错信息,可将全域变量opterr设为0或在optstring的选项字符集之前加上 ‘ : ’ 即可。

短参数定义:

      getopt()使用optstring所指的字串作为短参数列表,像"1ac:d::"就是一个短参数列表。短参数的定义是一个'-'后面跟一个字母或数字,象-a, -b就是一个短参数。每个数字或字母定义一个参数。 
  其中短参数在getopt定义里分为三种:
  1. 不带值的参数,它的定义即是参数本身。
  2. 必须带值的参数,它的定义是在参数本身后面再加一个冒号。
  3. 可选值的参数,它的定义是在参数本身后面加两个冒号 。
  在这里拿上面的"1ac:d::"作为样例进行说明,其中的1,a就是不带值的参数,c是必须带值的参数,d是可选值的参数。
  在实际调用中,'-1 -a -c cvalue -d', '-1 -a -c cvalue -ddvalue', '-1a -ddvalue -c cvalue'都是合法的。这里需要注意三点:
  1. 不带值的参数可以连写,象1和a是不带值的参数,它们可以-1 -a分开写,也可以-1a或-a1连写。
  2. 参数不分先后顺序,'-1a -c cvalue -ddvalue'和'-d -c cvalue -a1'的解析结果是一样的。
  3. 要注意可选值的参数的值与参数之间不能有空格,必须写成-ddvalue这样的格式,如果写成-d dvalue这样的格式就会解析错误。

返回值:

   getopt()每次调用会逐次返回命令行传入的参数。
   当没有参数的最后的一次调用时,getopt()将返回-1。
   当解析到一个不在optstring里面的参数,或者一个必选值参数不带值时,返回'?'。
   当optstring是以':'开头时,缺值参数的情况下会返回':',而不是'?' ,并且此时不会打印错误信息
-----------------------------------------------------------------------------------------------------------------------------------------------------
以上内容来自51cto博客http://blog.51cto.com/vopit/440453
-----------------------------------------------------------------------------------------------------------------------------------------------------
补充内容:
一、执行程序时,如果参数中有 ‘--’作为单独参数,那么getopt()函数会将其之后的所有参数当做非选项参数。
例如:
$ grep -- -k filename
并不会将‘-k’当做grep的选项,而是作为PATTERN,来匹配filename所代表文件中的内容
二、getopt的错误处理:
     getopt()在处理选项列表时,可能出现两种错误:
1.当遇到某个在optstring中没有指定的选项时;
2.当某一个选项需要一个参数,但是却没有提供参数时;
     处理方式:
1.默认情况下,getopt()在标准错误输出打印一条错误消息,并将字符‘?’作为返回值返回。这种情况下,全局变量optopt会返回出现错误的选项字符(即未能识别出来的或者缺少参数的那个选项)。
2.全局变量opterr可用来禁止显示有getopt()打印出来的错误消息。默认情况下,opterr值为1。如果我们将它设为0,那么getopt()将不会打印错误消息。这时程序可以通过检查函数是否为‘?’,并配合全局变量optopt打印用户自定义的错误信息。此外还有一种方法可以用来禁止显示错误信息:在optstring中将第一个字符设为 ‘:’ 。此时错误上报同将opterr设为0时一样,只是这时因缺失参数而导致的错误,会使函数返回‘:’,而不再是‘?’。如下表:
 

三、如果getopt()返回了-1,则表示此时没有更多的选项可以解析了。但如果此时optind比argc小,说明仍有非选项的参数需要处理。此时optind的值就是第一个非选项参数的值。
注:在getopt()的man page中有这样一句话:"By  default, getopt() permutes the contents of argv as it scans, so that eventually all the nonoptions are at the end."。即在默认情况下,函数会重新排列argv这个数组的内容,最终那些非选项参数将会被放到最后。即如果有如下命令:(假设abc均为cmd的合法选项)
$ cmd file1 file2 -a -b -c 
也就是argv数组的内容为:
{"file1","file2","-a","-b","-c"}
在循环调用getopt()之后,会将argv的各元素重新排序为
{"-a","-b","-c","file1","file2"}
这样一来,当getopt返回-1,则表示"-a","-b","-c"均已被解析出来,现在剩下"file1","file2"还没有处理,此时,optind会被设置为"file1"在argv中的当前的索引值,即optind==4。此后保证optind<argc的前提下,即可通过改变optind的值来读取argv中非选项参数进行处理。

测试代码:
#include<unistd.h>#include<stdio.h>int main(int argc,char *argv[]){int choice,i;extern char*optarg;extern int optind;printf("argv is {");for (i = 1; i < argc; i++)printf("\"%s\",",argv[i]);puts("\b }");while ((choice = getopt(argc, argv, "a::b:1c")) > 0){switch (choice){case 'a':printf("%c with argument:%s\n", choice, optarg);//a是可选参数选项,所以如果没有参数时,optarg会被置为NULLbreak;case 'b':printf("%c with argument:%s\n", choice,optarg);//b必须加参数选项,所以如果没有参数时,程序会报错,此时getopt()会返回‘?’,不会执行这个语句break;case 'c':printf("%c with no argument\n", choice);break;case '1':printf("%c with no argument\n", choice);//SUSv3标准允许使用字母数字作为选项,所以这个也是可以的break;case '?'://发生错误时,发生这种情况printf("!!! ? \n");break;case ':':printf("!!! : \n");//只有在optstring[0]==':'时,才会出现这种情况break;}}printf("argv is {");for (i = 1; i < argc; i++)printf("\"%s\",", argv[i]);puts("\b }");//[\b ]只是用来清楚多余的‘,’printf("the nonoptions is {");for (; optind < argc; optind++)//使用optind就可以获得剩余的非选项参数了printf("\"%s\",", argv[optind]);puts("\b }");return 0;}

运行:
$ ./tmp.out  hello world -aarga -b argvb -c1 -- -d -a



$ ./tmp.out  hello world -aarga -b 


好了,完了。有问题,你讲。

原创粉丝点击