[置顶] getopt、getopt_long、getopt_long_only详解

平时写程序时,有时需要对命令行参数进行处理。在接触本文所涉及的内容前,我们可能想到的方法是顺序提取命令行参数,进行顺序判断处理;然而,这种方法相当不灵活,尤其是在遇到带有可选参数的情况时,很难处理。为此,Linux提供了如下接口进行命令行参数的处理:

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

       #include <getopt.h>
       int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
       int getopt_long_only(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);

我们首先介绍几个全局变量

       optarg;	//指向当前选项参数(如果有)的指针
       optind,  //再次调用 getopt() 时的下一个 argv 指针的索引
       opterr,  //指定getopt、getopt_long、getopt_long_only是否在遇到错误时将错误输出到标准输出流
       optopt;  //最后一个未知选项

getopt

int getopt(int argc, char * const argv[],const char *optstring);
argc和argv与main函数的两个参数相匹配的
optstring是一个字符串,形式如“a:b::cd:”,分别表示选项 程序支持的命令行选项有-a、-b、-c、-d,冒号含义如下:
  • 只有一个字符,不带冒号——只表示选项, 如-c
  • 一个字符,后接一个冒号——表示选项后面带一个参数,如-a 100
  • 一个字符,后接两个冒号——表示选项后面带一个可选参数,即参数可有可无,如果带参数,则选项与参数直接不能有空格,形式应该如-b200
下面看一个例子:
#include <stdio.h>                                                              
#include <unistd.h>

int main(int argc, char* argv[])
{
    int opt;
    char *optstring = "a:b::cd:";
        
    while ((opt = getopt(argc, argv, optstring)) != -1) 
    {   
        printf("opt = %c\n", opt);<span style="white-space:pre">	</span> //输出选项名称
        printf("optarg = %s\n", optarg); //输出选项后接的参数
        printf("optind = %d\n", optind); //输出当前命令行参数下一个参数的下标
        printf("argv[optind-1] = %s\n\n", argv[optind-1]); //
    }   

    return 0;
}
测试
windeal@ubuntu:Test$ ./a.out -a 100 -b200 -b -c -d 300
opt = a
optarg = 100
optind = 3
argv[optind-1] = 100

opt = b
optarg = 200
optind = 4
argv[optind-1] = -b200

opt = b
optarg = (null)
optind = 5
argv[optind-1] = -b

opt = c
optarg = (null)
optind = 6
argv[optind-1] = -c

opt = d
optarg = 300
optind = 8
argv[optind-1] = 300

windeal@ubuntu:Test$ 

getopt_long

getopt_long相当于getopt的拓展,getopt_long支持长选项参数(即选项不是单个字符)。

getopt_long其原型如下:

       int getopt_long(int argc, char * const argv[],
                  const char *optstring,
                  const struct option *longopts, int *longindex);
除了与getopt相同的三个参数外,getopt_long还带有参数longopts,和longindex。

longindex表示当前长参数在longopts中的索引值

longopts类型定义如下

           struct option {
               const char *name;
               int         has_arg;
               int        *flag;
               int         val;
           };


no_argument(或者是0)时  ——参数后面不跟参数值

required_argument(或者是1)时 ——参数输入格式为:--参数 值 或者 --参数=值。

optional_argument(或者是2)时  ——参数输入格式只能为:--参数=值。

#include <stdio.h>
#include <unistd.h>
#include <getopt.h>

#define VAL1	0
#define VAL2	1
#define VAL3	2

int main(int argc, char* argv[])
{
	int opt;
	int this_option_optind = optind ? optind : 1;
	char *optstring = "a:b::cd:";
	struct option long_options[] = {
		{"lopt1", no_argument, 			0, VAL1},
		{"lopt2", required_argument,	0, VAL2},
		{"lopt3", optional_argument,	0, VAL3},
		{"lopt4", no_argument,			0, VAL1},
		{0,0,0,0}
	};
	int option_index = 0;


	while ((opt = getopt_long(argc, argv, optstring, long_options, &option_index)) != -1)
	{
		
		switch(opt)
		{
			case VAL1:
			case VAL2:
			case VAL3:
				printf("option %s", long_options[option_index].name);
				if (optarg)
					printf(" with arg %s", optarg);
            		printf("\n");
				break;
			case 'a':
			case 'b':
			case 'c':
			case 'd':
				printf("opt = %c\n", opt);	 //输出选项名称
				printf("optarg = %s\n", optarg); //输出选项后接的参数
				printf("optind = %d\n", optind); //输出当前命令行参数下一个参数的下标
				printf("argv[optind-1] = %s\n\n", argv[optind-1]); //
			default:
				exit(-1);
				break;
				
		}
	}


	return 0;
}


测试结果:

windeal@ubuntu:Test$ ./a.out --lopt1 --lopt2 23 --lopt3=33 --lopt4 -a 100
option lopt1
option lopt2 with arg 23
option lopt3 with arg 33
option lopt4
opt = a
optarg = 100
optind = 8
argv[optind-1] = 100

windeal@ubuntu:Test$ vim test.c 


getopt_long_only

getopt_long_only与getopt_long参数表和功能基本相同,主要差别的地方在于长选项参数的解析。

在getopt_long中,长选项参数需要由双横杠开始,即--name, 而-name会被解析成-n,-a,-m和-e在optstring中匹配

在getopt_long_only中,--name和-name都被解析成长选项参数。



















你可能感兴趣的:(c,参数解析)