getopt.h和对应的链接库不是每个编译器都有的,gcc编译器好像是有的,但是在vs2008是没有的,所以就要去网上下载跨平台的代码,不管怎么样,最终要把getopt.h和相应的lib文件和工程链接起来,这样才不会报错。这些都比较简单,现在重点介绍一下getopt.h里的函数的使用。
getopt是一个专门设计来减轻命令行处理负担的库函数,它可以在全局结构中记录命令参数,以便随后随时在整个程序中使用,即getopt被用来解析命令行选项参数,就不用自己写代码处理argv了。其中比较重要的函数是getopt()和getopt_long()。
(1) main()中的两个参数。声明main()函数有两种形式:int main( int argc, char *argv[] ); 和int main( int argc, char **argv );现在前者用的较多。当 C 运行时库的程序启动代码调用 main() 时,已经对命令行进行了处理。argc 参数包含参数的计数值,而 argv 包含指向这些参数的指针数组。对于 C 运行时库,arguments 是程序的名称,程序名后的任何内容都应该使用空格加以分隔。
例如,如果使用参数 -v bar www.ibm.com 运行一个名为 foo 程序,您的 argc 将设置为 4,argv 的设置情况则是:
argv[0] - foo
argv[1] - -v
argv[2] - bar
argv[3] - www.ibm.com
(2) getopt()。getopt()原型是int getopt( int argc, char *const argv[], const char *optstring ); 调用一次,返回一个选项。 在命令行选项参数再也检查不到optstring中包含的选项时,返回-1,同时optind储存第一个不包含选项的命令行参数。
首先说一下什么是选项,什么是参数和optstring。
字符串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。
getopt() 所设置的全局变量包括:
optarg——指向当前选项参数(如果有)的指针(optarg不需要定义,在getopt.h中已经有定义)。
optind——再次调用 getopt() 时的下一个 argv 指针的索引。
optopt——最后一个已知选项。可以重复调用 getopt(),直到其返回 -1 为止.
(3) getopt_long()的说明。getopt_long的原型是int getopt_long(int argc, char * const argv[],
const char *optstring,这里参数longopts,其实是一个结构的实例:
struct option {}
将 getop() 调用更改为了 getopt_long(),除了 getopt() 的参数外,它还接受 longOpts 数组和 int 指针 (longIndex)。当getopt_long() 返回 0 时,longIndex 所指向的整数将设置为当前找到的长选项的索引。
参考网址:
http://www.ibm.com/developerworks/cn/aix/library/au-unix-getopt.html
http://www.cnitblog.com/zouzheng/archive/2007/04/02/25034.aspx
如今的选项有两种模式,短选项和长选项,选项又分为带参数和不带参数。
比如:
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
getopt中的内容:
具体讲解在实例中。
/* 已定义的变量 */
int opterr
int optopt
int optind
char *optarg
/* 已定义的函数 */
/* */
int getopt (int argc, char **argv, const char *options)
int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *indexptr)
int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *indexptr)
/* 数据类型 */
struct option
实例1.实现短参数
#include
#include
#include
/* getopt时必须包含 unistd头文件 */
#include
int main (int argc, char **argv)
{
int index;
int c;
opterr = 0;
/* getopt 用来解析短选项,第一二个参数基本都是相同的 */
/* 第三个选项传入能接受的参数,':'代表需要值 '::'代表值为可选*/
/* 如果传入了值,其值保存在optarg当中,当其值为必须是,若没有传入值则会报错 缺少值 */
/* getopt返回匹配的选项 例如a/b/c */
/* 未匹配值时返回? 解析完时,会返回-1 跳出 */
while ((c = getopt (argc, argv, "abc:")) != -1)
switch (c)
{
case 'a':
printf("检测到-a选项\n");
break;
case 'b':
printf("检测到-b选项\n");
break;
case 'c':
printf("检测到-c选项,其参数为:%s\n", optarg);
break;
/* 用来检测其他意外的值 */
case '?':
/* optopt为在没有匹配任何选项时,保存的选项值 */
/* 例如-n,没有与上面匹配,则此时optopt=c */
if (optopt == 'c')
fprintf (stderr, "选项 -%c 需要一个参数.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "`-%c'未定义\n", optopt);
else
fprintf (stderr,
" `\\x%x' 未定义\n",
optopt);
break;
default:
abort ();//跳出while循环
}
/*
最后检测命令行给的选项是否已经解析完
optind是当前解析到选项的索引
判断依据是如果解析的个数小于argc,那么就是没有解析完
*/
for (index = optind; index < argc; index++)
printf ("未定义的参数: %s\n", argv[index]);
return 0;
}
实例2.实现长选项
#include
#include
/* 使用getopt_long时不需要unistd*/
#include
/* 用来作为一个标志的值. */
static int verbose_flag;
int
main (argc, argv)
int argc;
char **argv;
{
int c;
while (1)
{
/*
结构说明
struct option {
const char *name; //匹配的长选项名
int has_arg; //指定参数选项no_argument required_argument optional_argument
// 无值 值必须 值可选
int *flag; //标志位,数据类型为 int*
int val; //值,标志位不为0时,如果该选项指定,那么flag=val 此时val不可作为case值
//否则val可以作为短选项 也就相当于case
};
*/
static struct option long_options[] =
{
/* 如果指定了-verbose 那么verbose_flag = 1*/
{"verbose", no_argument, &verbose_flag, 1},
/* 如果指定了-brief 那么verbose_flag = 0*/
{"brief", no_argument, &verbose_flag, 0},
/* --add = -a 不带参数*/
{"add", no_argument, 0, 'a'},
{"append", no_argument, 0, 'b'},
/* --delete=XX = -dXX 带参数*/
{"delete", required_argument, 0, 'd'},
{"create", required_argument, 0, 'c'},
{"file", required_argument, 0, 'f'},
/* 很明显5438不可能用一个ANSCI表示出来,那么这个可以直接用case就可以*/
{"a_very_long_arg", no_argument, 0, 5438},
/* 最后为空值,来标识结束 */
{0, 0, 0, 0}
};
/* 因为没有了optind,那么就要用一个值来存储当前索引 */
int option_index = 0;
/* 前三个参数与getopt相同,第四个为option,第五个为存索引int的指针*/
c = getopt_long (argc, argv, "abc:d:f:",
long_options, &option_index);
/* 当解析完返回-1 跳出循环 */
if (c == -1)
break;
switch (c)
{
case 0:
/* 当 flag不为0时,遇到那些选项 getopt_long返回0*/
if (long_options[option_index].flag != 0)
break;
printf ("选项 %s", long_options[option_index].name);
if (optarg)
printf (" 值 %s", optarg);
printf ("\n");
break;
case 'a':
puts ("选项 -a\n");
break;
case 'b':
puts ("选项 -b\n");
break;
//长选项
case 5438:
puts ("选项 --a_very_long_arg\n");
break;
break;
case 'c':
printf ("选项 -c 值为 `%s'\n", optarg);
break;
case 'd':
printf ("选项 -d 值为 `%s'\n", optarg);
break;
case 'f':
printf ("选项 -f 值为 `%s'\n", optarg);
break;
case '?':
/* getopt_long 会自动输出错误,不像getopt需要自己检测 */
break;
default:
abort ();
}
}
/* 检测是否设置了标志位 */
if (verbose_flag)
puts ("verbose 标志已被设置");
/* 输入未解析完的选项. */
if (optind < argc)
{
printf ("无效选项: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
exit (0);
}
实例3.getopt_long_only
这个函数的参数和getopt_long相同,只是接受长参数时,可以只用一个’-'来替代’–’。当-xx没有检测到xx的长参数时会检测-x短参数。
同时’–’也能够使用,也就是说-xx=–xx
不得不说,getopt是一个很实用的工具,对于编程能提供很多的便利。gnu也有开源的实现在gnulib和libc中