Linux下getopt_long函数的使用

getopt_long为解析命令行参数函数,它是Linux C库函数。使用此函数需要包含系统头文件getopt.h。

getopt_long函数声明如下:

int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);

getopt_long的工作方式与getopt类似,关于getopt的介绍可以参考: https://blog.csdn.net/fengbingchun/article/details/81122843   。但是getopt_long除了接受短选项外还接受长选项,长选项以"--"开头。如果程序只接受长选项,那么optstring应指定为空字符串。如果缩写是唯一的,那么长选项名称可以缩写。长选项可以采用两种形式:--arg=param或--arg param. longopts是一个指针指向结构体option数组。

结构体option声明如下:

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

name:长选项的名字

has_arg:0,不需要参数;1,需要参数;2,参数是可选的

flag:指定如何为长选项返回结果。如果flag是null,那么getopt_long返回val(可以将val设置为等效的短选项字符),否则getopt_long返回0.

val:要返回的值。

结构体option数组的最后一个元素必须用零填充

当一个短选项字符被识别时,getopt_long也返回选项字符。对于长选项,如果flag是NULL,则返回val,否则返回0。返回-1和错误处理方式与getopt相同。

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

CMakeLists.txt文件内容如下:

PROJECT(samples_cplusplus)
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)

# 支持C++11
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -O2 -std=c11")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -g -Wall -O2 -std=c++11")

INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})

FILE(GLOB samples ${PROJECT_SOURCE_DIR}/*.cpp)

FOREACH (sample ${samples})
	STRING(REGEX MATCH "[^/]+$" sample_file ${sample})
	STRING(REPLACE ".cpp" "" sample_basename ${sample_file})
	ADD_EXECUTABLE(test_${sample_basename} ${sample})
	TARGET_LINK_LIBRARIES(test_${sample_basename} pthread)
ENDFOREACH()

sample_getopt_long.cpp内容如下:

#include 
#include 
#include 

int main(int argc, char* argv[])
{
	// reference: http://man7.org/linux/man-pages/man3/getopt.3.html
	int c;
	int digit_optind = 0;

	while (1) {
		int this_option_optind = optind ? optind : 1;
		int option_index = 0;
		static struct option long_options[] = {
			{"add",		required_argument,	0,	0},
			{"append",	no_argument,		0,	0},
			{"delete",	required_argument, 	0,	0},
			{"verbose",	no_argument,		0,	0},
			{"create",	required_argument,	0,	'c'},
			{"file",	required_argument,	0,	0},
			{0,		0,			0,	0}
		};

		c = getopt_long(argc, argv, "abc:d:012", long_options, &option_index);
		if (c == -1) break;

		switch (c) {
		case 0:
			//fprintf(stdout, "option %s ", long_options[option_index].name);
			//if (optarg) fprintf(stdout, "with arg %s", optarg);
			//fprintf(stdout, "\n");

			if (strcmp(long_options[option_index].name, "add") == 0)
				fprintf(stdout, "long option \"add\" value: %s\n", optarg);
			else if (strcmp(long_options[option_index].name, "append") == 0)
				fprintf(stdout, "long option \"append\"\n");
			else if (strcmp(long_options[option_index].name, "delete") == 0)
				fprintf(stdout, "long option \"delete\" value: %s\n", optarg);
			else if (strcmp(long_options[option_index].name, "create") == 0)
				fprintf(stdout, "long option \"create\" value: %s\n", optarg);
			else if (strcmp(long_options[option_index].name, "verbose") == 0)
				fprintf(stdout, "long option \"verbose\"\n");
			else if (strcmp(long_options[option_index].name, "file") == 0)
				fprintf(stdout, "long option \"file\" value: %s\n", optarg);
			break;
		case '0':
		case '1':
		case '2':
			if (digit_optind != 0 && digit_optind != this_option_optind)
				fprintf(stdout, "digits occur in two different argv elements.\n");
			digit_optind = this_option_optind;
			fprintf(stdout, "option %c\n", c);
			break;
		case 'a':
			fprintf(stdout, "option a\n");
			break;
		case 'b':
			fprintf(stdout, "option b\n");
			break;
		case 'c':
			fprintf(stdout, "option c with value '%s'\n", optarg);
			break;
		case 'd':
			fprintf(stdout, "option d with value '%s'\n", optarg);
			break;
		case '?':
			break;
		default:
			fprintf(stdout, "?? getopt returned character code 0%o ??\n", c);
		}	
	}

	if (optind < argc) {
		fprintf(stdout, "non-option argv elements: ");
		while (optind < argc)
			fprintf(stdout, "%s ", argv[optind++]);
		fprintf(stdout, "\n");
	}


	exit(EXIT_SUCCESS);
}

bash.sh内容如下:

#! /bin/bash

real_path=$(realpath $0)
dir_name=`dirname "${real_path}"`
echo "real_path: ${real_path}, dir_name: ${dir_name}"

new_dir_name=${dir_name}/build
mkdir -p ${new_dir_name}
cd ${new_dir_name}
cmake ..
make

cd -

run_getopt_long.sh内容如下:

#! /bin/bash

real_path=$(realpath $0)
dir_name=`dirname "${real_path}"`
echo "real_path: ${real_path}, dir_name: ${dir_name}"

echo -e "\n\ntest argv1:"; ${dir_name}/build/test_sample_getopt_long
echo -e "\n\ntest argv2:"; ${dir_name}/build/test_sample_getopt_long -?
echo -e "\n\ntest argv3:"; ${dir_name}/build/test_sample_getopt_long --add xxx
echo -e "\n\ntest argv4:"; ${dir_name}/build/test_sample_getopt_long -a xx -b yy -c zz -d rr -0 ss -1 tt -2 qq
echo -e "\n\ntest argv5:"; ${dir_name}/build/test_sample_getopt_long --add Tom --append Jim --delete Rucy --verbose XXX --create new_data --file a.txt -ab -c 111 -d 222
echo -e "\n\ntest argv6:"; ${dir_name}/build/test_sample_getopt_long -xxx yyy
echo -e "\n\ntest argv7:"; ${dir_name}/build/test_sample_getopt_long -a

执行过程:首先执行build.sh,然后再执行run_getopt_long.sh即可。

GitHub: https://github.com/fengbingchun/Linux_Code_Test 

你可能感兴趣的:(C/C++/C++11,Linux)