程序参数简述
当一个用C语言编写的Linux或UNIX程序运行时,它是从main函数开始的。对这些程序而言,main函数的声明如下所示:
int main(int argc, char *argv[])
其中argc是程序参数的个数,argv是一个代表参数自身的字符串数组
也可以如下声明
main()
这样也行,因为默认的返回值类型是int,而且函数中不用的形式参数不需要声明。argc和argv仍在,但如果不声明它们,你就不能使用它们
无论操作系统何时启动一个新程序,参数argc和argv都被设置并传递给main。这些参数通常由另一个程序提供,这个程序一般是shell,它要求操作系统启动该新程序。shell接受用户输入的命令行,将命令行分解成单词,然后把这些单词放入argv数组。请记住:Linux的shell一般会在设置argc和argv之前对文件名参数进行通配符扩展,而MS-DOS的shell则期望程序接受带通配符的参数,并执行它们自己的通配符扩展。
通常,你可以使用一个以短横线(-)开头的命令行参数来设置这些所谓的标志(flag)或开关(switch)。
sort -r /etc/hosts
程序参数示例
下面这个程序args.c对其参数进行检查:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
int arg; //定义数组游标,用于遍历数组
for(arg=0;arg<argc;arg++)
{
if(argv[arg][0] == '-') // 判断参数的第一个字符是否为'-'
{
printf("option:%s\n",argv[arg]+1); // 输出选项指令
}else
{
printf("argument %d:%s\n",arg,argv[arg]); // 输出参数
}
}
exit(0);
}
结果如下:

实验解析:
这个程序利用计数参数argc建立一个循环来检查所有的程序参数。它通过检查首字母是否是短横线来发现选项。
在本例中,如果打算支持-l选项和-r选项,那么我们就忽略了一个事实:-lr选项应该和-l –r一样处理。
X/Open规范(可以在http://opengroup.org/上找到)定义了命令行选项的标准用法(工具语法指南),同时定义了在C语言程序中提供命令行开关的标准编程接口:getopt函数。
getopt
为了帮助我们遵循这些准则,Linux提供了getopt函数,它支持需要关联值和不需要关联值的选项,而且简单易用。
#include <unistd.h>
int getopt(int argc, char *const argv[],const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
getopt函数将传递给程序的main函数的argc和argv作为参数,同时接受一个选项指定字符串optstring,该字符串告诉getopt哪些选项可用,以及它们是否有关联值。optstring只是一个字符列表,每个字符代表一个单字符选项。如果一个字符后面紧跟一个冒号(😃,则表明该选项有一个关联值作为下一个参数。bash中的getopts命令执行类似的功能
调用方式
getops(argc,argv,'if:lr');
它允许几个简单的选项:-i、-l、-r和-f,其中-f后面紧跟一个文件名参数。使用相同的参数,但以不同的顺序来调用命令将改变程序的行为。
getopt的返回值是argv数组中的下一个选项符。循环调用getopt就可以依次得到每个选项。
getopt有如下行为
1.如果选项有一个关联值,则外部变量optarg指向这个值
2.如果选项处理完毕,getopt返回-1,特殊参数--将使getopt停止扫描选项
3.如果遇到一个无法识别的选项,getopt返回一个问号(?),并把它保存到外部变量optopt中
4.如果一个选项要求有一个关联值(例如例子中的-f),但用户并未提供这个值,getopt通常将返回一个问题(?)。如果我们将选项字符串的第一个字符设置为冒号(😃,那么getopt将在用户未提供值的情况下返回冒号(:)而不是问题(?)
外部变量optind被设置为下一个待处理参数的索引,getopt利用它来记录自己的进度。程序很少需要对这个变量进行设置,当所有选项参数都处理完毕后,optind将指向argv数组尾部可以找到其余参数的设置
有些版本的getopt会在第一个非选项参数处停下来,返回-1并设置optind的值。而其他一些版本,如果Linux提供的版本,能够处理出现在程序参数中任意位置的选项。
注意,在这种情况下,getopt实际上重写了argv数组,把所有非选项参数都集中在一起,从argv[optind]位置开始。对GNU版本的getopt而言,这一行为是由环境变量POSIXLY_CORRECT控制的,如果它被设置,getopt就会在第一个非选项参数处停下来。此外,还有些getopt版本会在遇到未知选项时打印出错误信息。注意,根据POSIX规范,如果opterr变量是非零值,getopt就会向stderr打印一条出错误信息
实验 getopt函数
在这个实验中,你将在程序中使用getopt函数,并将新程序命名为argopt.c:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
int opt;
while((opt = getopt(argc,argv,":if:lr")) != -1){
switch(opt){
case 'i':
case 'l':
case 'r':
printf("option: %c\n",opt);
break;
case 'f':
printf("filename: %s\n",optarg);
break;
case ':':
printf("option needs a value\n");
break;
case '?':
printf("unknown option: %c\n",optopt);
break;
}
}
for(;optind < argc ; optind++)
printf("argument: %s\n",argv[optind]);
exit(0);
}

实验解析
这个程序循环调用getopt对选项参数进行处理,直到处理完毕,此时getopt返回-1.每个选项(包括未知选项和缺少关联值的选项)都有相应的处理动作。根据使用的getopt版本,你看到的输出可能和上面略有不同,尤其是出错信息部分,但含义都是明确的
当所有选项都处理完毕后,程序像以前一样把其余参数都打印出来,但这次是从optind位置开始
getopt_long
GNU C函数库包含getopt的另一个版本,称作getopt_long,它接受以双划线(--)开始的长参数
实验getopt_long
你可以使用getopt_long创建一个新版本的示例程序,它可以使用与前面选项等效的长参数选项:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define _GNU_SOURCE
#include <getopt.h>
int main(int argc, char *argv[])
{
int opt;
struct option longopts[] = {
{"initialize",0,NULL,'i'},
{"file",1,NULL,'f'},
{"list",0,NULL,'l'},
{"restart",0,NULL,'r'},
{0,0,0,0}};
while((opt = getopt_long(argc,argv,":if:lr",longopts,NULL)) != -1){
switch(opt){
case 'i':
case 'l':
case 'r':
printf("option: %c\n",opt);
break;
case 'f':
printf("filename: %s\n",optarg);
break;
case ':':
printf("option needs a value\n");
break;
case '?':
printf("unknown option:%c\n",optopt);
break;
}
}
for(;optind < argc; optind++)
printf("argument:%s\n",argv[optind]);
exit(0);
}

事实上,新的长选项和原来的单字符选项可以混合使用。只要它们能够被区分开,长选项也可以缩写。有关联值的长选项可以按照格式--option=value作为单个参数给出,如下所示

实验解析
getopt_long函数比getopt多两个参数。第一个附加参数是一个结构数组,它描述了每个长选项并告诉getopt_long如何处理它们。第二个附加参数是一个变量指针,它可以作为optind的长选项版本使用。对于每个识别的长选项它在长选项数组中的索引就写入该变量。在本例中,你不需要这一信息,因此第二个附加参数是NULL
长选项数组由一些类型为struct option的结构组成,每个结构描述了一长选项的行为。该数组必须以一个包含全0的结构结尾。
长选项结构在头文件getopt.h中定义,并且该关文件必须与常量_GNU_SOURCE一同包含进来,该常量启用getopt_long功能
struct option{
const char *name;
int has_arg;
int *flag;
int val;
}
| 选项成员 | 说明 |
|---|---|
| name | 长选项的名字。缩写也可以接受,只要不与其他选项混淆 |
| has_arg | 该选项是否带参数。0表示不带,1表示必须带一个参数,2表示有一个可选参数 |
| flag | 设置为NULL表示当找到该选项时,getopt_long返回在成员val里给出的值。否则,getopt_long返回0,并将val的值写入flag指向的变量 |
| val | getopt_long为该选项返回的值 |
要了解GNU对getopt扩展的其他选项及相关函数,主参考getopt的手册页
浙公网安备 33010602011771号