1、Linux传入参数处理
在介绍使用getopt函数处理应用程序传入参数前,先来看一下Linux环境下编写的应用程序是如何处理传入的参数的
Linux环境编写应用程序时,main函数一般会有两个参数,用于描述执行应用程序时传入的参数,书写形式如下:
int main(int argc, char *argv[])
- argc:表示传入参数的个数
- argv:指针数组,每一项存放一个传入参数字符串的地址
在shell中启动这个应用程序,shell接受用户输入命令行,将命令行分解成单词,然后把这些单词放入到一个数组,操作系统将这个存放单词数组的长度和数组作为参数传递给了main函数。因此,实际情况下,argv[0]指向的一定是运行当前应用程序的全路径名称,argv[1]~argv[argc-1]指向的才是传入参数,实际传入参数的个数为argc-1
例如有一个名为hello_world应用程序,在shell中按照 "./hello_world 3" 执行该程序,此时,argc = 2,argv[0]指向的是 "./hello_world" 字符串存放地址,argv[1]指向的才是传入参数 "3" 字符串存放地址
显然,我们可以在main函数内自己编写程序,通过解析argc,argv参数来获取执行应用程序所传入的参数。但对于Linux这种广泛使用的操作系统,它已经在库函数中为用户提供了用于命令行参数解析的函数,我们直接调用这些函数,便可轻松的解析各种命令行参数模式
这里所讲的getopt函数,就是标准库中实现的一个用于解析命令行参数的函数,它支持需要关联值和不需要关联值的选项,而且简单易用。
(所谓的需要关联值的选项,以gcc编译器为例子,gcc的-o选项表示输出可执行程序名称,这个后面就需要跟一个名称才能正常使用,后面一个参数就是-o命令的关联值;所谓的不需要关联值,以ls命令为例子, ls的-l命令表示列出当前目录所有文件,这个后面不需要跟一些其他信息,这种被称作不需要关联值的选项)
2、getopt函数的原型
getopt函数有三个参数,函数的原型如下:
int getopt(int argc, char * const argv[], const char *optstring); extern char *optarg; extern int optind, opterr, optopt;
getopt函数本质上其实就是对main函数传入的argc和argv参数进行处理,它将传递给程序的main函数的argc和argv作为参数,同时接受一个选项指定字符串optstring。optstring字符串告诉getopt哪些选项可用,以及它们是否有关联值。
optstring是一个字符串列表,每个字符代表一个单字符选项。如果一个字符后面紧跟一个冒号(:),则表示一个该选项有一个关联值作为下一个参数。
例如:getopt(argc, argv, "if:l")
它允许-i、-f、-l作为参数,其中-f选项后要紧跟一个参数,也就是它的关联值。这里参数的传递可以不按照optstring字符串列表写入的顺序来传
getopt的返回值是argv数组中的下一个选项字符,循环调用getopt可以依次得到argv中每一个选项。函数的处理行为如下:
- 如果选项处理完毕,返回值为-1,循环遇到-1,可以退出
- 如果选项有一个关联值,全局变量optarg指向这个值
- 如果遇到不在optstring中选项,getopt返回一个问号(?),并将无法识别选项存放到全局变量optopt,有些getopt版本会在遇到未知选项时打印错误信息
- 如果选项要求有关联值,但是用户没传入一个关联值,默认情况下getopt通常返回一个问号(?)。我们可以将选项字符串的第一个字符设置成冒号,这个没传入关联值时,返回的是冒号(:)而不是问号(?)
optind表示下一个待处理参数的索引,getopt利用它来记录自己的进度,一般情况下在程序中很少用到
3、函数的使用
编写一个简单的例子,来演示getopt函数使用
#include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { int res; while((res = getopt(argc, argv, ":io:l")) != -1) { switch(res) { case 'i': case 'l': printf("option: %c\n", res); break; case 'o': printf("option: %c %s\n", res, optarg); break; case ':': printf("option need a value\n"); break; case '?': printf("unknown option: %c\n", optopt); break; default: break; } } }
main函数内使用getopt函数对传入参数进行解析,支持参数有-i、-o、-l,其中-o参数后要有一个关联值。这里optstring参数的第一个字符设置成冒号,是用来分辨输入-o,但没传入关联值情况,这种情况(:)被返回
如果传入-i、-l参数,打印参数信息
如果传入-o参数,打印参数信息和关联值信息
如果传入-o参数,并没传入关联值,打印出提示信息
如果传入无效参数时,打印出不识别提示信息
4、小结
调用getopt函数可以方便的处理我们程序中传入的不同参数,它按照我们指定的方式来解析main函数中传入的argc和argv参数,并返回选项字符。支持的参数在getopt的optstring参数指定,通过参数后面冒号(:)的有无来表示该参数后面是否需要紧跟关联值信息。但getopt函数也有自己的局限性,它仅支持的是单字符参数,如果想接受比单字符选项含义更明确的参数时,就不适用了。不过,如果你有这种需求,可以去研究下C库中getopt函数的另一个增强版本——getopt_long,它接受以下划线(--)开始的长参数