Linux下 头文件<getopt.h> 及其函数的应用
本文内容摘抄自两篇博客:
https://www.cnblogs.com/qingergege/p/5914218.html
https://blog.csdn.net/pengrui18/article/details/8078813
函数一:
int getopt(int argc, char* argv[], const char* optstring);
参数1、2为 main函数的输入参数,参数3 为选项字符串,函数返回值为选项字符。
<getopt.h 文件内部的参数:
1、 extern char* optarg ; 用于保存选项。
2、 extern int optind, 用来记录下一个检索位置。
3、 extern int opterr, 是否将错误的信息输出到stderr,为0时表示不输出。
4、 extern int optopt, 表示不在选项字符串optstring中的选项。
先来看一条指令: gcc helloworld.c -o helloworld.out; 这条指令中的-o就是命令行的选项,而后面的helloworld.out 就是选项-o选项所携带的参数。 有些选项是不带参数的,而这样不带参数的选项可以写在一起, 比如说有两个选项 -c和-d,这两个选项都不带参数,那么他们是可以写在一起的,即:-cd 。
关于选项字符串: 比如 “a:b:cd::e”,这就是一个选项字符串。对应到命令行就是 -a, -b, -c, -d, -e 。 冒号表示参数,一个冒号就表示这个选项后面必须带有参数。这个参数可以和选项连在一起,也可以用空格隔开,比如:-a123 和 -a 123 ,都表似乎123为-a的参数。两个冒号就表示这个选项的参数是可选的,即可以有参数也可以没有参数,但要注意有参数时参数与选项之间不能有空格。
一个例子:
/* ============================================================================ Name : test.c Author : lgh ============================================================================ */ #include <unistd.h> #include <stdio.h> int main(int argc, char* argv[]) { int ch; printf("\n\n"); printf("optind:%d, opterr:%d\n",optind,opterr); printf("-----------------------------------------------------------\n"); while((ch = getopt(argc, argv, "ab:c:de::")) != -1) { switch(ch) { case 'a': printf("a\n\n"); printf("the argument of -a is %s\n\n",optarg); break; case 'b': printf("b\n\n"); printf("the argument of -b is %s\n\n",optarg); break; case 'c': printf("c\n\n"); printf("the argument of -c is %s\n\n",optarg); break; case 'd': printf("d\n\n"); break; case 'e': printf("e\n\n"); printf("the argument of -e is %s\n\n",optarg); break; case '?': printf("unknown option: %c\n",(char)optopt); break; } printf("下一次起始搜索位置:optind = %d\n",optind); printf("-----------------------------------------------------------\n"); printf("\n\n"); } }
编译后命令执行 ./test -b "hello world"
输出结果为:
optind:1, opterr:1 ----------------------------------------------------------- b the argument of -b is hello world 下一次起始搜索位置:optind = 3 -----------------------------------------------------------
可以看到optind 和 opterr的初始值都为1 ,opterr非零表示如果发生错误,会将错误输出到stderr上。
int main(int argc, char* argv[]); argc表示参数的个数,argv[]表示每个参数字符串。 对于./test -b "hello world" 命令,argc就为3,argv[]分别表示./test -b "hello world" , 实际上真正的参数从 -b 开始,也就是argv[1] ,所以optind的初始值就是1。
当执行getopt()函数时,会依次扫描每一个命令行参数(下标1开始),第一个-b是一个选项,而且这个选项在选项字符串optstring中有,b后面有冒号表示b后面必须带有参数, “hello world”就是它的参数。所以这个命令行是符合要求的。至于执行后optind为什么是3,这是因为optind是下一次getopt()函数要从argv[3]开始搜索。当然,这个例子argv[3]已经没有了,此时getopt()函数会返回-1,结束while循环。
再次输入一行命令: ./test -b "hello world" -c1234
输出结果为:
optind:1, opterr:1 ----------------------------------------------------------- b the argument of -b is hello world 下一次起始搜索位置:optind = 3 ----------------------------------------------------------- c the argument of -c is 1234 下一次起始搜索位置:optind = 4 -----------------------------------------------------------
对于这个过程,最开始optind=1 ,找到选项-b 和他的参数“hello world” ,之后搜索起始位置跳至argv[3] 找到 -c和他的参数1234(选项和参数是连在一起的),由于-c1234是写在一起的,所以他俩一起占用argv[3] ,之后搜索起始位置跳至 argv[4] ,而argv[4]为空,这样getopt()函数就会返回-1,循环结束。
再次输入命令: ./test -z 123
输出结果为:
optind:1, opterr:1 ----------------------------------------------------------- ./test: invalid option -- 'z' unknown option: z 下一次起始搜索位置:optind = 2 -----------------------------------------------------------
其中./test: invalid option -- 'z' 就是输出到stderr的错误输出 ,如果把opterr设置为0那么就不会有这条输出。
再次输入命令: ./test -zheng
输出结果为:
optind:1, opterr:1 ----------------------------------------------------------- ./test: invalid option -- 'z' unknown option: z 下一次起始搜索位置:optind = 1 ----------------------------------------------------------- ./test: invalid option -- 'h' unknown option: h 下一次起始搜索位置:optind = 1 ----------------------------------------------------------- e the argument of -e is ng 下一次起始搜索位置:optind = 2 -----------------------------------------------------------
由于不带参数的选项可以写在一起,所以当getopt()函数找到-z的时候,发现在optstring中没有,这时候他就认为h也是一个选项,也就是-h 和 -z写在一起了,依次类推,直到找到-e,发现optstring中有。
函数二: getopt_long_only(int argc, char* argv[], const struct char* options, int* index)
先看个例子:
/* ============================================================================ Name : test.c Author : lgh ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include <getopt.h> int main(int argc, char* argv[]) { const char* optstring="n:v"; int c, deb, index; struct option options[]= { {"username", required_argument, NULL, 'n'}, {"version" , no_argument, NULL, 'v'}, {0 , 0 , NULL, 0 }, }; while((c=getopt_long_only(argc,argv,optstring, options, &index))!=-1) { switch(c) { case 'n': printf("username is %s\n", optarg); break; case 'v': printf("version is 0.0.1\n"); break; case '?': printf("?\n"); break; default: printf("c is %d\n",c); break; } } return 0; }
输入指令:
./test -n "hello world"
输出结果:
username is hello world
输入命令:
./test -v
输出结果:
version is 0.0.1
struct option options[]为结构体数组, “n:v”为选项字符,他们对应的长字符分别为前面的 username 、version ;
required_argument 表示输入指令时 选项字符后面需要带参数,no_argument则表示不用带参数。