getopt

编译测试程序通常需要解析命令行参数,linux提供了比较方便的api来解析这些命令行参数。

  • 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);

这里有3个api函数,先从第一个开始看

  • getopt
/**
 * @ argc: 传递的参数个数
 * @ argv: 传递的参数字符串指针
 * @ optstring: 选项字符串,用来告诉函数可以处理那些选项,以及需要的参数
 * @ return: 
 */
int getopt(int argc, char * const argv[], const char *optstring);

编写测试代码

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

int my_getopt(int argc, char *argv[])
{
	int opt;
	char optString[] = "a:b::cd";

	while((opt = getopt(argc, argv, optString)) != -1) {
		printf("opt = %c		", opt);
		printf("optarg = %s		", optarg);
		printf("optind = %d		", optind);
		printf("argv[%d] = %s
", optind, argv[optind]);
	}

	return 0;
}

int main(int argc, char *argv[])
{
	my_getopt(argc, argv);
	return 0;
}

编译并执行,查看下面执行的情况,其中a参数可选,b参数固定,c和d没有参数。

# ./getopt -a123 -b200 -c -d 
opt = a		optarg = 123		optind = 2		argv[2] = -b200
opt = b		optarg = 200		optind = 3		argv[3] = -c
opt = c		optarg = (null)		optind = 4		argv[4] = -d
opt = d		optarg = (null)		optind = 5		argv[5] = (null)

#./getopt -a -b200 -c -d 
opt = a		optarg = (null)		optind = 2		argv[2] = -b200
opt = b		optarg = 200		optind = 3		argv[3] = -c
opt = c		optarg = (null)		optind = 4		argv[4] = -d
opt = d		optarg = (null)		optind = 5		argv[5] = (null)
  • getopt_long
/**
 * @ argc: 传递的参数个数
 * @ argv: 传递的参数字符串指针
 * @ optstring: 选项字符串,用来告诉函数可以处理那些选项,以及需要的参数
 * @ longopts: 指明了长函数的名称和属性
 * @ longindex: 如果longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值
 * @ return: 
 */
int getopt_long(int argc, char * const argv[],
          const char *optstring,
          const struct option *longopts, int *longindex);
struct option {
       char *name;
       int has_arg;
       int *flag;
       int val;
};

The name field should contain the option name without the leading double dash.

The has_arg field should be one of:
	
	   no_argument        no argument to the option is expected
	   required_argument  an argument to the option is required
	   optional_argument  an argument to the option may be presented
	   
If flag is not NULL, then the integer pointed to by it will be set to the value in the val field.
If the flag field is NULL, then the val field will be returned.
	   

测试代码

int my_getopt_long(int argc, char *argv[])
{
	int opt;
	int optidx = 0;

	char *string = "a::b:cd";
	static struct option longopts[] = {
		{ "optarg",		optional_argument,      NULL,		'a' },
		{ "reqarg",		required_argument,      NULL,       'b' },
		{ "noarg",		no_argument,            NULL,		'c' },
		{ "noarg",       no_argument,			NULL,		'd' }
	};

	while ((opt = getopt_long(argc, argv, string, longopts, &optidx)) != -1) {
		printf("opt = %c		", opt);
		printf("optarg = %s		", optarg);
		printf("optind = %d		", optind);
		printf("argv[%d] = %s		", optind, argv[optind]);
		printf("openindex = %d
", optidx);
	}

	return 0;
}

int main(int argc, char *argv[])
{
	my_getopt_long(argc, argv);
	return 0;
}

测试结果,使用长选项指定参数

➜  getopt ./getopt --reqarg 100 --optarg=200 --noarg
opt = b		optarg = 100		optind = 3		argv[3] = --optarg=200		openindex = 1
opt = a		optarg = 200		optind = 4		argv[4] = --noarg		openindex = 0
opt = c		optarg = (null)		optind = 5		argv[5] = (null)		openindex = 2
  • getopt_long_only

getopt_long_only 函数与 getopt_long 函数使用相同的参数表,在功能上基本一致。