头文件getopt.h可参考这里点击打开
getopt是一个专门设计来减轻命令行处理负担的库函数,它可以在全局结构中记录命令参数,以便随后随时在整个程序中使用,即getopt被用来解析命令行选项参数,就不用自己写代码处理argv了。其中比较重要的函数是getopt()和getopt_long()。
1.C语言是如何传递参数的?
main()中的两个参数。声明main()函数有两种形式:int main( int argc, char *argv[] ); 和int main( int argc, char **argv );现在前者用的较多。当 C 运行时库的程序启动代码调用 main() 时,已经对命令行进行了处理。argc 参数包含参数的计数值,而 argv 包含指向这些参数的指针数组。对于 C 运行时库,arguments 是程序的名称,程序名后的任何内容都应该使用空格加以分隔。
例如,如果运行一个名为 test 程序:./test -v abc d。那么argc 值为 4,argv 的设置情况则是:
argv[0] = foo
argv[1] = -v
argv[2] = bar
argv[3] = www.ibm.com
2.getopt()
函数原型:
给定了命令参数的数量 (int getopt( int argc, char *const argv[], const char *optstring );
argc
)、指向这些参数的数组 (argv
) 和选项字符串 (optstring
) 后,getopt()
将返回第一个选项,并设置一些全局变量。使用相同的参数再次调用该函数时,它将返回下一个选项,并设置相应的全局变量。如果不再有识别到的选项,将返回-1
,此任务就完成了。
getopt()
所设置的全局变量包括:
optarg
——指向当前选项参数(如果有)的指针。optind
——再次调用getopt()
时的下一个 argv 指针的索引。optopt
——最后一个已知选项。
再说一下什么是选项,什么是参数。
字符串optstring可以下列元素,
1.单个字符,表示选项,
2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg。
3 单个字符后跟两个冒号,表示该选项后必须跟一个参数。参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(这个特性是GNU的扩张)。
getopt处理以'-’开头的命令行参数,如optstring="ab:c::d::",命令行为getopt.exe -a -b host -ckeke -d haha
在这个命令行参数中,-a和-h就是选项元素,去掉'-',a,b,c就是选项。host是b的参数,keke是c的参数。但haha并不是d的参数,因为它们中间有空格隔开。
还要注意的是默认情况下getopt会重新排列命令行参数的顺序,所以到最后所有不包含选项的命令行参数都排到最后。
如getopt.exe -a ima -b host -ckeke -d haha, 都最后命令行参数的顺序是: -a -b host -ckeke -d ima haha
如果optstring中的字符串以'+'加号开头或者环境变量POSIXLY_CORRE被设置。那么一遇到不包含选项的命令行参数,getopt就会停止,返回-1。
3.getopt_long()
函数原型是
int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
这里参数longopts,其实是一个结构的实例:
struct option {
const char *name; //name表示的是长参数名
int has_arg; //has_arg有3个值,no_argument(或者是0),表示该参数后面不跟参数值
//required_argument(或者是1),表示该参数后面一定要跟个参数值
//optional_argument(或者是2),表示该参数后面可以跟,也可以不跟参数值
int *flag; //用来决定,getopt_long()的返回值到底是什么。如果 flag 成员未设置为 NULL,在处理期间遇到此选项时,
//会使用 val 成员的值填充它所指向的 int 值。如果 flag 成员为 NULL,在 getopt_long() 遇到此选项时,将返回 val 中的值;
int val; //和flag联合决定返回值
}
将 getop() 调用更改为了 getopt_long(),除了 getopt() 的参数外,它还接受 longOpts 数组和 int 指针 (longIndex)。当getopt_long() 返回 0 时,longIndex 所指向的整数将设置为当前找到的长选项的索引。
实例代码如下
#include <stdio.h>
#include <getopt.h>
char *val;
const char *optString = "vh:";
static const struct option long_options[] =
{
{"version", 0, NULL, 'v'},
{"hello", 1, NULL, 'h'},
{NULL, 0, NULL, 0}
};
int main(int argc, char *argv[])
{
int opt = 0;
while((opt = getopt_long(argc, argv, optString,long_options, NULL)) != -1)
{
switch(opt)
{
case 'v':
printf("It's the getopt_long_test V1.0\n");
break;
case 'h':
val = optarg;
printf("Hello, %s~\n", val);
break;
}
}
return 0;
}
4.参数传递标准
如今的选项有两种模式,短选项和长选项,选项又分为带参数和不带参数。
比如:
gcc -V 是短选项,且不带参数
gcc –version 是长选项,不带参数。与gcc -V相同
gcc -o exc 是短选项 带参数,与gcc –output exc相同
而多个短选项可直接连接,例如gcc -so FILE 与 gcc -s -o FILE相同
短选项的参数可直接紧接在其后,例如gcc -oFILE = gcc -oFILE
长选项的参数可以以空格分隔或者=分隔,例如 gcc –output FILE = gcc –output=FILE
5.总结
UNIX 用户始终依赖于命令行参数来修改程序的行为,特别是那些设计作为小工具集合 (UNIX 外壳环境)的一部分使用的实用工具更是如此。程序需要能够快速处理各个选项和参数,且要求不会浪费开发人员的太多时间。毕竟,几乎没有程序设计为仅处理命令行参数,开发人员更应该将精力放在程序所实际进行的工作上。
getopt()
函数是一个标准库调用,可允许您使用直接的 while/switch 语句方便地逐个处理命令行参数和检测选项(带或不带附加的参数)。与其类似的getopt_long()
允许在几乎不进行额外工作的情况下处理更具描述性的长选项,这非常受开发人员的欢迎。
既然已经知道了如何方便地处理命令行选项,现在就可以集中精力改进您的程序的命令行,可以添加长选项支持,或添加之前由于不想向程序添加额外的命令行选项处理而搁置的任何其他选项。
不要忘记在某处记录您所有的选项和参数,并提供某种类型的内置帮助函数来为健忘的用户提供帮助。