linux/Unix系统调用之getopt()

本文详细介绍了Linux/Unix系统调用getopt(),用于解析命令行参数。getopt()函数根据optstring参数处理命令行选项,区分不带值、必须带值和可选值的参数。当遇到未定义的选项或缺少参数时,会返回错误。全局变量optind表示参数的索引,opterr控制错误消息显示。getopt()会重新排列argv,使非选项参数移至末尾。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

getopt()解析命令行参数 

使用前提:

#include<unistd.h>
extern char *optarg;
extern int optind,opterr,optopt;
//函数的定义
int getopt(int argc,char*const argv[],const char *optstring);

 

函数说明:

       getopt()解析给定在参数argc和argv中的命令行参数集合。这两个参数通常是从main()函数的参数列表中获取。(当然也可以自行定义)参数optstring指定了函数应处理的命令行选项集合。此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母。如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,全域变量optarg 即会指向此额外参数。如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符,如果不希望getopt()印出错信息,可将全域变量opterr设为0或在optstring的选项字符集之前加上 ‘ : ’ 即可。

短参数定义:

       getopt()使用optstring所指的字串作为短参数列表,像"1ac:d::"就是一个短参数列表。短参数的定义是一个'-'后面跟一个字母或数字,象-a, -b就是一个短参数。每个数字或字母定义一个参数。 

  其中短参数在getopt定义里分为三种:

  1. 不带值的参数,它的定义即是参数本身。

  2. 必须带值的参数,它的定义是在参数本身后面再加一个冒号。

  3. 可选值的参数,它的定义是在参数本身后面加两个冒号 。

  在这里拿上面的"1ac:d::"作为样例进行说明,其中的1,a就是不带值的参数,c是必须带值的参数,d是可选值的参数。

  在实际调用中,'-1 -a -c cvalue -d', '-1 -a -c cvalue -ddvalue', '-1a -ddvalue -c cvalue'都是合法的。这里需要注意三点:

  1. 不带值的参数可以连写,象1和a是不带值的参数,它们可以-1 -a分开写,也可以-1a或-a1连写。

  2. 参数不分先后顺序,'-1a -c cvalue -ddvalue'和'-d -c cvalue -a1'的解析结果是一样的。

  3. 要注意可选值的参数的值与参数之间不能有空格,必须写成-ddvalue这样的格式,如果写成-d dvalue这样的格式就会解析错误。

 

返回值:

   getopt()每次调用会逐次返回命令行传入的参数。

   当没有参数的最后的一次调用时,getopt()将返回-1。

   当解析到一个不在optstring里面的参数,或者一个必选值参数不带值时,返回'?'。

   当optstring是以':'开头时,缺值参数的情况下会返回':',而不是'?' ,并且此时不会打印错误信息。

-----------------------------------------------------------------------------------------------------------------------------------------------------

以上内容来自51cto博客http://blog.51cto.com/vopit/440453

-----------------------------------------------------------------------------------------------------------------------------------------------------

补充内容:

一、执行程序时,如果参数中有 ‘--’作为单独参数,那么getopt()函数会将其之后的所有参数当做非选项参数。

例如:

$ grep -- -k filename

并不会将‘-k’当做grep的选项,而是作为PATTERN,来匹配filename所代表文件中的内容

二、getopt的错误处理:

     getopt()在处理选项列表时,可能出现两种错误:

1.当遇到某个在optstring中没有指定的选项时;

2.当某一个选项需要一个参数,但是却没有提供参数时;

     处理方式:

1.默认情况下,getopt()在标准错误输出打印一条错误消息,并将字符‘?’作为返回值返回。这种情况下,全局变量optopt会返回出现错误的选项字符(即未能识别出来的或者缺少参数的那个选项)。

2.全局变量opterr可用来禁止显示有getopt()打印出来的错误消息。默认情况下,opterr值为1。如果我们将它设为0,那么getopt()将不会打印错误消息。这时程序可以通过检查函数是否为‘?’,并配合全局变量optopt打印用户自定义的错误信息。此外还有一种方法可以用来禁止显示错误信息:在optstring中将第一个字符设为 ‘:’ 。此时错误上报同将opterr设为0时一样,只是这时因缺失参数而导致的错误,会使函数返回‘:’,而不再是‘?’。如下表:

 

三、全局变量optind表示访问参数的索引.   如果getopt()返回了-1,则表示此时没有更多的选项可以解析了。但如果此时optind比argc小,说明仍有非选项的参数需要处理。此时optind的值就是第一个非选项参数的索引。

注:在getopt()的man page中有这样一句话:"By  default, getopt() permutes the contents of argv as it scans, so that eventually all the nonoptions are at the end."。即在默认情况下,函数会重新排列argv这个数组的内容,最终那些非选项参数将会被放到最后。即如果有如下命令:(假设abc均为cmd的合法选项)

$ cmd file1 file2 -a -b -c 

也就是argv数组的内容为:

{"file1","file2","-a","-b","-c"}

在循环调用getopt()之后,会将argv的各元素重新排序为

{"-a","-b","-c","file1","file2"}

这样一来,当getopt返回-1,则表示"-a","-b","-c"均已被解析出来,现在剩下"file1","file2"还没有处理,此时,optind会被设置为"file1"在argv中的当前的索引值,即optind==4。此后保证optind<argc的前提下,即可通过改变optind的值来读取argv中非选项参数进行处理。

 

测试代码:

#include<unistd.h>
#include<stdio.h>
int main(int argc,char *argv[])
{
	int choice,i;
	extern char*optarg;
	extern int optind;
	printf("argv is {");
	for (i = 1; i < argc; i++)
		printf("\"%s\",",argv[i]);
	puts("\b }");
	while ((choice = getopt(argc, argv, "a::b:1c")) > 0)
	{
		switch (choice)
		{
		case 'a':
			printf("%c with argument:%s\n", choice, optarg);	//a是可选参数选项,所以如果没有参数时,optarg会被置为NULL
			break;
		case 'b':
			printf("%c with argument:%s\n", choice,optarg);		//b必须加参数选项,所以如果没有参数时,程序会报错,此时getopt()会返回‘?’,不会执行这个语句
			break;
		case 'c':
			printf("%c with no argument\n", choice);
			break;
		case '1':
			printf("%c with no argument\n", choice);		//SUSv3标准允许使用字母数字作为选项,所以这个也是可以的
			break;
		case '?':												//发生错误时,发生这种情况
			printf("!!! ? \n");
			break;
		case ':':
			printf("!!! : \n");					//只有在optstring[0]==':'时,才会出现这种情况
			break;
		}
	}
	printf("argv is {");
	for (i = 1; i < argc; i++)
		printf("\"%s\",", argv[i]);
	puts("\b }");							//[\b ]只是用来清楚多余的‘,’

	printf("the nonoptions is {");
	for (; optind < argc; optind++)			//使用optind就可以获得剩余的非选项参数了
		printf("\"%s\",", argv[optind]);
	puts("\b }");
	return 0;
}

 

运行:

$ ./tmp.out  hello world -aarga -b argvb -c1 -- -d -a


 

$ ./tmp.out  hello world -aarga -b 

 

好了,完了。有问题,你讲。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值