C++ 命令列引數解析
文章目錄
說明
主要參考以下部落格:
部落格一:getopt和getopt_long函式
部落格三:使用 Qt 解析命令列引數
短引數之 getopt()
標頭檔案:#include <unistd.h>
函式原型:int getopt(int argc, char * const argv[], const char *optstring);
引數解釋:
[param1] argc: main 函式的 argc
[param2] argv: main 函式的 argv
[param3] optstring: 格式控制符。"ab:c:d"代表 -b 和 -b 後面必須跟一個引數,而 -a 和 -d 不需要引數
相關變數:
extern char *optarg; 表示引數的具體內容
extern int optind; 表下一個將被處理到的引數在 argv 中的下標值
extern int opterr;
extern int optopt;
測試案例:
// Opt.cpp
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
// 短引數測試案例
void testGetOpt(int argc, char *argv[]) {
int opt; // getopt() 的返回值
const char *optstring = "a:b:c:d"; // 設定短引數型別及是否需要引數
while ((opt = getopt(argc, argv, optstring) ) != -1) {
printf("opt = %c\n", opt); // 命令引數,亦即 -a -b -c -d
printf("optarg = %s\n", optarg); // 引數內容
printf("optind = %d\n", optind); // 下一個被處理的下標值
printf("argv[optind - 1] = %s\n\n", argv[optind - 1]); // 引數內容
}
}
int main(int argc, char *argv[]) {
testGetOpt(argc, argv);
return 0;
}
正確的使用方法(√):
[[email protected]:~/Desktop]$ opt.exe -a a_para -b b_para -c c_para -d # 引數全用
[[email protected]:~/Desktop]$ opt.exe -a a_para -b b_para -d # 部分引數
[[email protected]:~/Desktop]$ opt.exe -b b_para -a a_para # 可以倒序
[[email protected]:~/Desktop]$ opt.exe # 可以無參
錯誤的使用方法(×):
[[email protected]:~/Desktop]$ opt.exe -a # -a 後面沒有跟引數
[[email protected]:~/Desktop]$ opt.exe -a a_para -d d_para # -d 後面跟了引數
長引數之 getopt_long()
標頭檔案:#include <getopt.h>
函式原型:int getopt(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
引數解釋:
[param1] argc: main 函式的 argc
[param2] argv: main 函式的 argv
[param3] optstring: 格式控制符
[param4] longopts: 一個由option結構體組成的陣列,陣列的每個元素,指明瞭一個“長引數”(即形如–name的引數)名稱和性質
[param5] longindex: 如果longindex非空,它指向的變數將記錄當前找到引數符合longopts裡的第幾個元素的描述,即是longopts的下標值
相關變數:
同上
測試案例:
// Opt.cpp
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
// 長引數測試案例
void testGetOptLong(int argc, char *argv[]) {
int opt; // getopt_long() 的返回值
int digit_optind = 0; // 設定短引數型別及是否需要引數
// 如果option_index非空,它指向的變數將記錄當前找到引數符合long_opts裡的
// 第幾個元素的描述,即是long_opts的下標值
int option_index = 0;
// 設定短引數型別及是否需要引數
const char *optstring = "ab:nr:";
// 設定長引數型別及其簡寫,比如 --reqarg <==>-r
/*
struct option {
const char * name; // 引數的名稱
int has_arg; // 是否帶引數值,有三種:no_argument, required_argument,optional_argument
int * flag; // 為空時,函式直接將 val 的數值從getopt_long的返回值返回出去,
// 當非空時,val的值會被賦到 flag 指向的整型數中,而函式返回值為0
int val; // 用於指定函式找到該選項時的返回值,或者當flag非空時指定flag指向的資料的值
};
其中:
no_argument(即0),表明這個長引數不帶引數(即不帶數值,如:--name)
required_argument(即1),表明這個長引數必須帶引數(即必須帶數值,如:--name Bob)
optional_argument(即2),表明這個長引數後面帶的引數是可選的,(即--name和--name Bob均可)
*/
static struct option long_options[] = {
{"reqarg", required_argument, NULL, 'r'},
{"noarg", no_argument, NULL, 'n'},
{"optarg", optional_argument, NULL, 'o'},
{0, 0, 0, 0} // 新增 {0, 0, 0, 0} 是為了防止輸入空值
};
while ( (opt = getopt_long(argc,
argv,
optstring,
long_options,
&option_index)) != -1) {
printf("opt = %c\n", opt); // 命令引數,亦即 -a -b -n -r
printf("optarg = %s\n", optarg); // 引數內容
printf("optind = %d\n", optind); // 下一個被處理的下標值
printf("argv[optind - 1] = %s\n", argv[optind - 1]); // 引數內容
printf("option_index = %d\n", option_index); // 當前列印引數的下標值
printf("\n");
}
}
int main(int argc, char *argv[]) {
testGetOptLong(argc, argv);
return 0;
}
正確的使用方法(√):
[[email protected]:~/Desktop]$ opt.exe -a -b b_para -n -r r_para # 全部使用
[[email protected]:~/Desktop]$ opt.exe -a # 部分引數
[[email protected]:~/Desktop]$ opt.exe -a -b b_para # 部分引數
[[email protected]:~/Desktop]$ opt.exe -a -b b_para -n # 部分引數
[[email protected]:~/Desktop]$ opt.exe -n -r r_para # 部分引數
[[email protected]:~/Desktop]$ opt.exe -a --noarg --reqarg required_para # 長引數
錯誤的使用方法(×):
[[email protected]:~/Desktop]$ opt.exe -a -b -n -r required_para # -b 沒有跟引數
注意事項:一般地,不要將短引數的 optstring 和長引數的 struct option 的 val 設定為一樣的字母,這樣易於區分!!!
長引數之 getopt_long_only()
標頭檔案:#include <unistd.h>
函式原型:int getopt(int argc, char * const argv[], const char *optstring, const struct option *long_opts, int *longindex);
與 getopt_long() 的區別:
- 該函式與 getopt_long() 函式使用相同的引數表,在功能上基本一致
- 只是 getopt_long() 只將 --name 當作長引數,但 getopt_long_only() 會將 --name 和 -name 兩種選項都當作長引數來匹配
- getopt_long() 在遇到 -name 時,會拆解成 -n -a -m -e 到 optstring 中進行匹配,而 getopt_long_only() 只在 -name 不能在longopts() 中匹配時才將其拆解成 -n -a -m -e 這樣的引數到 optstring 中進行匹配