系统执行一个C语言程序总是从main()函数开始。在标准的C程序中,main()函数有两个参数,它们代表程序的命令行参数,原型如下:
int main(int argc, char *argv[]);
argc是命令行参数的个数,argv是C字符串的数组,它的元素是单个的命令行参数字符串。执行程序名是第一个字符串,而所有参数之后总是一个NULL指针:argv[argc]总是NULL。
比如,命令“cat abc def”中,argc等于3,argv的有效元素有3个,分别是cat、abc、def。
POSIX建议程序的选项(options)按照下面的规则定义:
- 选项用连字符“-”开始,并且只含有字符和数字。
- 多选项可以合并写出:-abc等于-a –b –c。
- 某些选项可以带一个参数(argument)。如:-o file。 带参数选项一般位于其它无参数选项前面。
- 两个连字符“–”之后所有的选项都视为普通命令行参数。
长选项用“–”开始,且不带参数。由于长选项没有参数,可以用“–name=value”的形式给出参数。
如果你的程序参数少,可以直接从argv数组中获取。如果选项较多而复杂,分析起来很麻烦,这时可以使用getopt()和getopt_long()函数分析典型的命令行参数。使用这两个函数,必须包含unistd.h文件。
getopt
getopt函数的原型如下:
int getopt(int argc, char **argv, const char *options);
该函数的作用是分析参数argc和argv提供的选项。
几个外部变量
- extern char *optarg; extern int optind, opterr, optopt;
- optarg:若短选项后有参数,则optarg指向该参数
- optind:扫描选项时,标识下一个选项的索引;扫描结束后,标识第一个非选项参数索引
- opterr:出现不可识别的选项时,getopt将打印错误信息。将opterr设为0,可不打印错误信息。
- optopt:存放不可识别的选项至optopt
这里的argc和argv往往直接来源于main函数的参数。options给出需要分析的有效选项的列表,是以字符串的形式给出。
其中需要有参数的选项后跟一个“:”,如果参数是可选的,则后面有两个冒号“::”。
getopt函数返回命令行中的一个选项字符,如果有参数,其参数存储在预定义变量char* optarg指定的内存中。
如果参数列表argv中包含普通的不是选项的参数,或者包含不在options中指定的选项,则getopt函数返回“?”字符,并且把相应的字符存储到变量optopt中。如果这时外部变量opterr不等于0,则getopt函数会打印错误信息。
当所有选项都给出后,函数返回-1,表示没有选项了。
通常getopt函数应该在一个循环中调用,每次给出一个选项,直到返回-1。循环中分析得到的选项,往往用switch语句。循环结束后,往往还需要一个循环分析不是选项的命令行参数,首个不是选项的命令行参数的位置存储在变量optind中。下面举例如下:
#include <unistd.h>
#include <stdio.h>
int
main(int argc,char *argv[])
{
int aflag = 0;
int bflag = 0;
char *cvalue = NULL;
int index;
int c;
opterr = 0;
while((c=getopt(argc,argv,"abc:"))!=-1)
{
switch(c)
{
case 'a':
aflag=1;
break;
case 'b':
bflag=1;
break;
case 'c':
cvalue=optarg;
break;
case '?':
if(isprint(optopt))
fprintf(stderr,"Unknown option '-%c'.\n",optopt);
else
fprintf(stderr,
"Unknown option charactor '\\x%x'.\n",
optopt);
return 1;
default:
abort();
}
}
printf("aflag = %d, bflag = %d,
cvalue = %s\n",aflag,bflag,cvalue);
for(index=optind;index<argc;index++)
printf("Non-option argument %s\n",argv[index]);
return 0;
}
getopt_long
getopt_long
函数getopt_long除了能够处理普通选项,还能处理长选项。它的原型如下:
int getopt_long(int argc, char **argv, const char *shortopts,
struct option *longopts, int *indexptr);
它从argv中解析出选项。参数shortopts描述了需要解析的短选项,它的表示方法同getopt函数一样,参数longopts描述了接受的长选项。当getopts_long函数遇到一个短选项,它的行为和getopts函数一样:返回选项字符,把参数存储到optarg中。
结构option是预先定义的结构,用来表明函数getopts_long能够接受的长选项和对该长选项的处理方法。它包含如下4个成员:
const char *name:字符串,选项的名称。
int has_arg:表示该长选项是否包含参数。它可取值no_argument、required_argument、optional_argument,分别表示无参数、有参数、可选参数。
int *flag
int val : 这两个参数合起来表示处理该选项的方法。如果指针flag为NULL,val就表示一个代表该选项的唯一整数。如果函数getopts_long的返回值是该整数,表明找到了该选项。如果希望某个长选项和另外一个短选项具有相同的意义,可以定义该长选项的val值和短选项字符相同。如果指针指向一个分配好的整数,那么当找到该选项时,这个整数就用来存储val给出的值,用来表明找到了该选项。这种情况下,函数getopts_long返回0。
函数getopts_long的参数longopts是一个指向结构option的指针,给出一组option类型的长选项,用{0,0,0,0}表示参数结束。
函数getopts_long的最后一个参数indexptr是一个整数指针,它在函数getopts_long正确调用后被设置成当前参数在longopts中的位置。比如,你可以用longopts[*indexptr].name引用找到参数的名称。
如果长选项有参数,它将被存储到optarg变量中。如果没有参数,变量optarg等于NULL。
当函数getopts_long不再能找出选项时,它返回-1。它仍然用optind表明剩下的参数在argv中的位置。
下面举例说明。
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
/* Flag set by '--verbose'. */
static int verbose_flag;
int
main(int argc,char **argv)
{
int c;
while(1)
{
static struct option long_options[]=
{
{"verbose",no_argument,&verbose_flag,1},
{"brief",no_argument,&verbose_flag,0},
{"add",required_argument,0,0},
{"append",no_argument,0,0},
{"delete",no_argument,0,0},
{"create",no_argument,0,0},
{"file",no_argument,0,0},
{0,0,0,0}
};
int option_index = 0;
c = getopt_long(argc,argv,"abc:d:",
long_options,&option_index);
if(c==-1)
break;
switch(c)
{
case 0:
if(long_options[option_index].flag!=NULL)
break;
printf("option %s",long_options[option_index].name);
if(optarg)
printf(" with arg %s",optarg);
printf("\n");
break;
case 'a':
puts("option -a\n");
break;
case 'b':
puts("option -b\n");
break;
case 'c':
printf("option -c with value '%s'\n",optarg);
break;
case 'd':
printf("option -d with value '%s'\n",optarg);
break;
case '?':
break;
default:
abort();
}
}
if(verbose_flag)
puts("verbose flag is set");
if(optind<argc)
{
printf("non-option argv elements: ");
while(optind<argc)
printf("%s ",argv[optind++]);
putchar('\n');
}
exit(0);
}