前提知识:main的argc和argv是什么
argc和argv是程序的入口函数main的参数,它们用于接收和解析命令行传递给程序的参数。
比如我们在命令行中运行一个程序时
./test -a value1 -b value2 a.cpp
对于上述这个命令行,操作系统会将命令行拆分为字符串数组,并对argc和argv进行设置,然后将argc和argv传递给可执行文件test的入口main函数。
agrc:参数总数,对于上面这个命令行会被拆分成6个部分,因此argc为6
argv:数组内容,argv[0]为”./test”、argv[1]为”-a”..........argv[5]为”a.cpp”
<getopt.h>中的常用函数
getopt
函数原型:
int getopt(int argc, char argv[], const char* optstring);
参数:
argc:命令行的参数量(一般由main提供,也可以自己传入)
argv:命令行的的参数数组(一般由main提供,也可以自己传入)
optstring:一个字符串,用于定义有效的选项及其参数需求
每个字符表示一个选项,例如a表示选项-a
如果一个选项需要参数,则在字符后添加:例如b:表示-b 需要参数
如果选项是可选的(仅GNU扩展支持),使用:: 例如c::
返回值:
成功解析则返回当前选项的字符,比如返回a表示-a
如果解析完毕返回-1
如果遇到无效的选项返回?,并设置全局变量optopt为无效选项的字符
示例:
getopt_long
解析命令行参数中的长选项,例如 - -option,并可结合短选项一起使用
函数原型:
int getopt_long(int argc, char* const argv[], const char* optstring
const struct option* longopts, int* longindex);
参数:
argc:命令行参数数量
argv:命令行参数数组
optstring:定义短选项及其参数需求(与getopt相同)
longopts:指向一个struct option数组,用于定义长选项的属性
longindex:指向一个整数,用于存储当前被解析的长选型在longopts数组中的索引
结构体:option
struct option {
const char* name; 长选型的名称(如”help”)
int has_arg; 参数类型:0表示无参数,1表示需要参数,2表示可选参数
int* flag; 如果非NULL,则返回0并设置*flag为val,否则返回val
int val; 长选项的返回值(如果flag为NULL)
}
注意:该struct option数组必须以一个空项的option结构体结束
static struct option long_options[] = {
{"help", no_argument, nullptr, 'h'},
{"output", required_argument, nullptr, 'o'},
{"version", no_argument, nullptr, 'v'},
{nullptr, 0, nullptr, 0 } //结束标志
};
返回值:
如果flag为NULL,返回val
如果flag非NULL,返回0,并将*flag设置为val
如果加载完毕返回-1
如果遇到无效选项,返回?
示例:
<getopt.h>中的全局变量
optind
int optind
通常初始化为1,指向argv[1](跳过程序名)
在调用getopt或getopt_long时,optind会自动递增,用于跟踪解析进度
当所有选项解析完成后,optind会指向第一个非选项参数(或超出argv范围)
示例:
首先getind会被初始化为1,在getopt时optind会随着解析到有效选项而自增,由于有两个有效项,因此会自增到3。
optopt
表示解析过程中遇到的未定义选项或选项缺少参数时的选项字符
int optopt
如果命令行的选项未在optstring中定义或者选项定义时指明了需要参数,但在命令行中没有为该选项指定参数,则getopt返回’?’,并将错误选项字段存储在optopt中
示例:
opterr
控制getopt是否自动打印错误信息
默认值为1,表示启用错误信息输出
如果opterr为非0值,当解析遇到错误时,getopt会打印标准错误信息
设置opterr = 0可以禁用此行为,让程序自行处理错误
optarg
存储当前选项的参数值(如果需要参数)
char* optarg
如果某选项需要参数(由optstring中的:指定),optarg会指向该参数值。
如果选项中没有参数或解析错误,则optarg为NULL
示例:
全局变量总结:
<getopt.h>使用示例
#include <iostream>
#include <getopt.h> // getopt_long
#include <string>
#include <vector>
int main(int argc, char* argv[]) {
std::string inputFile;
std::string outputFile;
std::string mode = "default";
bool verbose = false;
// 禁止 getopt 自动输出错误信息
opterr = 0;
// 定义长选项结构体
const struct option long_options[] = {
{"input", required_argument, nullptr, 'i'},
{"output", required_argument, nullptr, 'o'},
{"mode", required_argument, nullptr, 'm'},
{"verbose", no_argument, nullptr, 'v'},
{"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0}
};
int opt;
int long_index = 0;
// 开始解析参数
while ((opt = getopt_long(argc, argv, "i:o:m:vh", long_options, &long_index)) != -1) {
switch (opt) {
case 'i':
inputFile = optarg;
break;
case 'o':
outputFile = optarg;
break;
case 'm':
mode = optarg;
break;
case 'v':
verbose = true;
break;
case 'h':
std::cout << "Usage: " << argv[0] << " [OPTIONS] file1 file2 ...\n"
<< " -i, --input <file> Input file\n"
<< " -o, --output <file> Output file\n"
<< " -m, --mode <mode> Processing mode (default/custom)\n"
<< " -v, --verbose Enable verbose output\n"
<< " -h, --help Show this help message\n";
return 0;
case '?':
std::cerr << "Unknown option: " << static_cast<char>(optopt) << "\n";
return 1;
}
}
// 输出所有选项结果
std::cout << "Input File : " << inputFile << "\n"; // ← 输入文件
std::cout << "Output File: " << outputFile << "\n"; // ← 输出文件
std::cout << "Mode : " << mode << "\n"; // ← 模式
std::cout << "Verbose : " << (verbose ? "Yes" : "No") << "\n"; // ← 是否开启 verbose
// 输出剩余的非选项参数(比如要处理的多个文件)
std::vector<std::string> files;
for (int i = optind; i < argc; ++i) {
files.emplace_back(argv[i]);
}
std::cout << "Remaining files to process: \n";
for (const auto& file : files) {
std::cout << " " << file << "\n"; // ← 非选项参数(如 a.cpp b.cpp 等)
}
// 这里你可以根据 inputFile/outputFile/mode/files 做实际文件处理
// (此处略去实现逻辑)
return 0;
}
命令行执行:
./fileproc -i config.txt --output result.log -m fast --verbose main.cpp util.cpp
程序输出:
Input File : config.txt
Output File: result.log
Mode : fast
Verbose : Yes
Remaining files to process:
main.cpp
util.cpp