Linux下getopt函式的使用
getopt為解析命令列引數函式,它是Linux C庫函式。使用此函式需要包含系統標頭檔案unistd.h。
getopt函式宣告如下:
int getopt(int argc, char * const argv[], const char * optstring);
其中函式的argc和argv引數通常直接從main的引數直接傳遞而來。optstring是一個包含合法選項字元的字串。如果字元後跟一個冒號”:”,則該選項要求有引數。在argv中以“-“開頭的都視作選項,“-“後的字元是選項字元。getopt會返回在argv中的選項字元,此字元會對應optstring中的字元。如果getopt被重複呼叫,它返回下一個選項字元。如果不再有可識別的選項字元,將返回-1。
如果getopt找到另一個選項字元,則返回該字元,更新外部變數optind和靜態變數nextchar,以便下次呼叫getopt可以重複使用接下來的選項字元。如果成功找到選項,getopt返回該選項字元。如果所有命令列選項已被解析,getopt返回-1.如果getopt遇到一個選項字元不在optstring中,那麼將返回"?".
如果getopt遇到一個缺少引數的選項,則返回值取決於optstring中的第一個字元,如果是":",則返回":",否則返回"?".
預設情況下,getopt會調換argv中的內容,將非選項放在最後。這樣當getopts讀取完所有的選項以後,optind會指向非選項的引數。
在處理選項列表時,getopt可以檢測兩種錯誤:(1).一個選項字元在optstring中並沒有指定;(2).缺少選項引數。預設情況下,getopt在標準錯誤上輸出錯誤資訊,將錯誤的選項字元放在optopt中,並返回"?"作為函式結果。如果呼叫者將全域性變數opterr設定為0,那麼getopt不會輸出錯誤資訊(預設情況下,opterr是一個非零值)。如果optstring中的第一個字元是冒號":",那時getopt同樣不會列印錯誤資訊。另外,getopt將返回":"代替返回"?"以表示缺少選項引數。
getopt()所設定的全域性變數包括:
(1). char *optarg:當前選項的引數。
(2). int optind: 是在argv中要處理的下一個元素的索引。系統初始化此值為1.呼叫者可以將其重置為1以重新開始掃描相同的argv,或掃描一個新的引數向量。每次呼叫getopt時,optind儲存下個引數在argv中的索引(index)。如果找到一個選項,getopt會返回找到的選項字元,更新optind。如果選項有引數,將引數存到optarg,否則optarg為0。
(3). int opterr: 這個變數為非零時,getopt為”無效選項”或”缺少引數選項”輸出錯誤資訊。
(4). int optopt: 當發現無效選項字元時,getopt或返回'?'字元,或返回':'字元,並且optopt包含了所發現的無效選項字元。
getopt定義分為三種:
(1). 不帶引數的選項。
(2). 必須帶引數的選項:在選項後加一個冒號。
(3). 可選引數的選項:在選項後加兩個冒號。
注意事項:
(1). 不帶引數的選項可用連寫。
(2). 選項不分先後順序。
(3). 可選引數的選項與引數之間不能有空格。
下面是從其他文章中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.cpp內容如下:
#include <iostream>
#include <unistd.h>
namespace {
void test1(int argc, char* argv[])
{
// reference: http://man7.org/linux/man-pages/man3/getopt.3.html
int 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-function
const 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);
else
fprintf(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;
}
} // namespace
int 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內容如下:
#! /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.sh內容如下:
#! /bin/bash
real_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.jpg
echo -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: -
執行過程:首先執行build.sh,然後再執行run_getopt.sh即可。
相關文章
- Linux下getopt()函式的簡單使用Linux函式
- linux下getopt函式的用法Linux函式
- linux之getopt 函式(轉)Linux函式
- Linux選項解釋-getopt和getopt_long函式Linux函式
- getopt_long函式基本用法-linux函式Linux
- linux系統getopt函式詳解Linux函式
- Linux中getopt函式、optind等變數使用詳解Linux函式變數
- linux的命令列解析引數之getopt_long函式使用Linux命令列函式
- 命令列引數選項處理:getopt()及getopt_long()函式使用命令列函式
- 1.linux的命令列解析引數之getopt_long函式Linux命令列函式
- 命令列引數解析函式getopt_long() 使用詳解命令列函式
- C/C++—— 分析命令列引數的getopt()函式使用介紹C++命令列函式
- 一個使用getopt()函式獲取命令列引數的例子(轉)函式命令列
- linux下execl函式的使用和比較Linux函式
- linux下的c庫函式Linux函式
- Linux下的時間函式Linux函式
- 關閉 linux下的umask( )函式、setsid( )函式Linux函式
- Linux-getoptLinux
- linux getopt 命令Linux
- linux下C語言中的mkdir函式與rmdir函式LinuxC語言函式
- shell中getopt的使用
- linux 中getopt和getopt_long 用法解析Linux
- 【轉】linux下awk內建函式的使用(split/substr/length)Linux函式
- Linux access()函式 使用Linux函式
- c++中getopt和getopt_long的使用方法C++
- linux系統呼叫getoptLinux
- 關於linux下system()函式的總結Linux函式
- linux與windows下C++的sleep函式LinuxWindowsC++函式
- getopt在Python中的使用Python
- 對於linux下system()函式的深度理解(整理)Linux函式
- 函式下函式
- 函式: 函式是怎麼使用的?函式
- linux程式設計下signal()函式Linux程式設計函式
- getopt和getopt_long
- getopt與getopt_long
- Linux下使用Matlab符號函式出錯的解決辦法(轉)LinuxMatlab符號函式
- 使用 cURL 函式下載B站字幕函式
- 使用bind()函式的產生的函式用作建構函式this的指向函式