Linux下getopt函数的使用
getopt為解析命令行參數(shù)函數(shù),它是Linux C庫函數(shù)。使用此函數(shù)需要包含系統(tǒng)頭文件unistd.h。
getopt函數(shù)聲明如下:
int getopt(int argc, char * const argv[], const char * optstring);
其中函數(shù)的argc和argv參數(shù)通常直接從main的參數(shù)直接傳遞而來。optstring是一個(gè)包含合法選項(xiàng)字符的字符串。如果字符后跟一個(gè)冒號”:”,則該選項(xiàng)要求有參數(shù)。在argv中以“-“開頭的都視作選項(xiàng),“-“后的字符是選項(xiàng)字符。getopt會返回在argv中的選項(xiàng)字符,此字符會對應(yīng)optstring中的字符。如果getopt被重復(fù)調(diào)用,它返回下一個(gè)選項(xiàng)字符。如果不再有可識別的選項(xiàng)字符,將返回-1。
如果getopt找到另一個(gè)選項(xiàng)字符,則返回該字符,更新外部變量optind和靜態(tài)變量nextchar,以便下次調(diào)用getopt可以重復(fù)使用接下來的選項(xiàng)字符。如果成功找到選項(xiàng),getopt返回該選項(xiàng)字符。如果所有命令行選項(xiàng)已被解析,getopt返回-1.如果getopt遇到一個(gè)選項(xiàng)字符不在optstring中,那么將返回"?".
如果getopt遇到一個(gè)缺少參數(shù)的選項(xiàng),則返回值取決于optstring中的第一個(gè)字符,如果是":",則返回":",否則返回"?".
默認(rèn)情況下,getopt會調(diào)換argv中的內(nèi)容,將非選項(xiàng)放在最后。這樣當(dāng)getopts讀取完所有的選項(xiàng)以后,optind會指向非選項(xiàng)的參數(shù)。
在處理選項(xiàng)列表時(shí),getopt可以檢測兩種錯(cuò)誤:(1).一個(gè)選項(xiàng)字符在optstring中并沒有指定;(2).缺少選項(xiàng)參數(shù)。默認(rèn)情況下,getopt在標(biāo)準(zhǔn)錯(cuò)誤上輸出錯(cuò)誤信息,將錯(cuò)誤的選項(xiàng)字符放在optopt中,并返回"?"作為函數(shù)結(jié)果。如果調(diào)用者將全局變量opterr設(shè)置為0,那么getopt不會輸出錯(cuò)誤信息(默認(rèn)情況下,opterr是一個(gè)非零值)。如果optstring中的第一個(gè)字符是冒號":",那時(shí)getopt同樣不會打印錯(cuò)誤信息。另外,getopt將返回":"代替返回"?"以表示缺少選項(xiàng)參數(shù)。
getopt()所設(shè)置的全局變量包括:
(1). char *optarg:當(dāng)前選項(xiàng)的參數(shù)。
(2). int optind: 是在argv中要處理的下一個(gè)元素的索引。系統(tǒng)初始化此值為1.調(diào)用者可以將其重置為1以重新開始掃描相同的argv,或掃描一個(gè)新的參數(shù)向量。每次調(diào)用getopt時(shí),optind保存下個(gè)參數(shù)在argv中的索引(index)。如果找到一個(gè)選項(xiàng),getopt會返回找到的選項(xiàng)字符,更新optind。如果選項(xiàng)有參數(shù),將參數(shù)存到optarg,否則optarg為0。
(3). int opterr: 這個(gè)變量為非零時(shí),getopt為”無效選項(xiàng)”或”缺少參數(shù)選項(xiàng)”輸出錯(cuò)誤信息。
(4). int optopt: 當(dāng)發(fā)現(xiàn)無效選項(xiàng)字符時(shí),getopt或返回'?'字符,或返回':'字符,并且optopt包含了所發(fā)現(xiàn)的無效選項(xiàng)字符。
getopt定義分為三種:
(1). 不帶參數(shù)的選項(xiàng)。
(2). 必須帶參數(shù)的選項(xiàng):在選項(xiàng)后加一個(gè)冒號。
(3). 可選參數(shù)的選項(xiàng):在選項(xiàng)后加兩個(gè)冒號。
注意事項(xiàng):
(1). 不帶參數(shù)的選項(xiàng)可用連寫。
(2). 選項(xiàng)不分先后順序。
(3). 可選參數(shù)的選項(xiàng)與參數(shù)之間不能有空格。
下面是從其他文章中copy的測試代碼,詳細(xì)內(nèi)容介紹可以參考對應(yīng)的reference:
CMakeLists.txt文件內(nèi)容如下:
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.cpp內(nèi)容如下:
#include <iostream>
#include <unistd.h>namespace {void test1(int argc, char* argv[])
{// reference: http://man7.org/linux/man-pages/man3/getopt.3.htmlint flags = 0, opt = -1, nsecs = 0, tfnd = 0;while ((opt = getopt(argc, argv, "nt:")) != -1) {switch (opt) {case 'n':flags =1;break;case 't':nsecs = atoi(optarg);tfnd = 1;break;default:fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n", argv[0]);exit(EXIT_FAILURE);}}fprintf(stdout, "flags = %d; tfnd = %d; nsec = %d; optind = %d\n", flags, tfnd, nsecs, optind);if (optind >= argc) {fprintf(stderr, "Expected argument after options\n");exit(EXIT_FAILURE);}fprintf(stdout, "name argument = %s\n", argv[optind]);exit(EXIT_SUCCESS);
}int test2()
{// reference: https://stackoverflow.com/questions/10502516/how-to-call-correctly-getopt-functionconst char* argv[] = {"ProgramNameHere", "-f", "input.gmn", "-output.jpg"};int argc = sizeof(argv) / sizeof(argv[0]);std::cout<<"argc: "<<argc<<std::endl;for (int i = 0; i < argc; ++i) {//std::cout<<"argv: "<<argv[i]<<std::endl;}int c = -1;while ((c = getopt(argc, (char**)argv, "f:s:o:pw:h:z:t:d:a:b:?")) != -1) {std::cout<<"Option: "<<(char)c;if (optarg) {std::cout<<", argument: "<<optarg;}std::cout<<"\n";}return 0;
}int test3(int argc, char* argv[])
{// reference: https://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html// Normally, getopt is called in a loop. When getopt returns -1, indicating no more options are present, the loop terminates.// A switch statement is used to dispatch on the return value from getopt. In typical use, each case just sets a variable that is used later in the program.// A second loop is used to process the remaining non-option arguments.int aflag = 0, bflag = 0, index = -1, c = -1;char* cvalue = nullptr;opterr = 0;while ((c = getopt(argc, argv, "abc:")) != -1) {switch (c) {case 'a':aflag = 1;break;case 'b':bflag = 1;break;case 'c':cvalue = optarg;break;case '?':if (optopt == 'c')fprintf(stderr, "Option -%c requires an argument.\n", optopt);else if (isprint(optopt))fprintf(stderr, "Unknown option '-%c'.\n", optopt);elsefprintf(stderr, "Unknown option character '\\x%x'.\n", optopt);return 1;default:abort();}} fprintf(stdout, "aflag = %d, bflag = %d, cvalue = %s\n", aflag, bflag, cvalue);for (index = optind; index < argc; ++index) {fprintf(stdout, "index: %d, Non-option argument: %s\n", index, argv[index]);}return 0;
}} // namespaceint main(int argc, char* argv[])
{if (argc < 2) {fprintf(stderr, "the number of params must be greater than or equal to 2\n");return -1;}int flag = atoi(argv[1]);switch(flag) {case 1:fprintf(stdout, "start test 1:\n");test1(argc, argv);break;case 2:fprintf(stdout, "start test 2:\n");test2();break;case 3:fprintf(stdout, "start test 3:\n");test3(argc, argv);break;default:fprintf(stderr, "params error\n");break;}return 0;
}
build.sh內(nèi)容如下:
#! /bin/bashreal_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 ..
makecd -
run_getopt.sh內(nèi)容如下:
#! /bin/bashreal_path=$(realpath $0)
dir_name=`dirname "${real_path}"`
echo "real_path: ${real_path}, dir_name: ${dir_name}"echo "test1:"
${dir_name}/build/test_sample_getopt 9 # params error
${dir_name}/build/test_sample_getopt 1 # flags = 0; tfnd = 0; nsec = 0; optind = 1
${dir_name}/build/test_sample_getopt 1 -b # invalid option -- 'b'
${dir_name}/build/test_sample_getopt 1 -x YYY # invalid option -- 'x'
${dir_name}/build/test_sample_getopt 1 -vZZZ # invalid option -- 'v'
${dir_name}/build/test_sample_getopt 1 -t 999 -n Jim # flags = 1; tfnd = 1; nsec = 999; optind = 4
${dir_name}/build/test_sample_getopt 1 -t888 -nSom # invalid option -- 'S'
${dir_name}/build/test_sample_getopt 1 -t6666 # flags = 0; tfnd = 1; nsec = 6666; optind = 2
${dir_name}/build/test_sample_getopt 1 -nant -t555 # invalid option -- 'a'
${dir_name}/build/test_sample_getopt 1 -n222 -t111 # invalid option -- '2'echo -e "\n\ntest2:"
${dir_name}/build/test_sample_getopt 2
# argc: 4
# Option: f, argument: input.gmn
# Option: o, argument: utput.jpgecho -e "\n\ntest3:"
${dir_name}/build/test_sample_getopt 3
# aflag = 0, bflag = 0, cvalue = (null)
# index: 1, Non-option argument: 3
${dir_name}/build/test_sample_getopt 3 -a -b
# aflag = 1, bflag = 1, cvalue = (null)
# index: 3, Non-option argument: 3
${dir_name}/build/test_sample_getopt 3 -ab
# aflag = 1, bflag = 1, cvalue = (null)
# iindex: 2, Non-option argument: 3
${dir_name}/build/test_sample_getopt 3 -c foo
# aflag = 0, bflag = 0, cvalue = foo
# index: 3, Non-option argument: 3
${dir_name}/build/test_sample_getopt 3 -cfoo
# aflag = 0, bflag = 0, cvalue = foo
# index: 2, Non-option argument: 3
${dir_name}/build/test_sample_getopt 3 arg1
# aflag = 0, bflag = 0, cvalue = (null)
# index: 1, Non-option argument: 3
# index: 2, Non-option argumnet: arg1
${dir_name}/build/test_sample_getopt 3 -a arg1
# aflag = 1, bflag = 0, cvalue = (null)
# index: 2, Non-option argument: 3
# index: 3, Non-option argument: arg1
${dir_name}/build/test_sample_getopt 3 -c foo arg1
# aflag = 0, bflag = 0, cvalue = foo
# index: 3, Non-option argument: 3
# index: 4, Non-option argument: arg1
${dir_name}/build/test_sample_getopt 3 -a -- -b
# aflag = 1, bflag = 0, cvalue = (null)
# index: 3, Non-option argument: 3
# index: 4, Non-option argument: -b
${dir_name}/build/test_sample_getopt 3 -a -
# aflag = 1, bflag = 0, cvalue = (null)
# index: 2, Non-option argument: 3
# index: 3, Non-option argument: -
執(zhí)行過程:首先執(zhí)行build.sh,然后再執(zhí)行run_getopt.sh即可。
GitHub: https://github.com/fengbingchun/Linux_Code_Test??
總結(jié)
以上是生活随笔為你收集整理的Linux下getopt函数的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows与Linux之间互传文件的
- 下一篇: Linux下getopt_long函数的