如何将命令行参数与c++中的选项一起传递给函数
How shall command line arguments be passed to a function along with options in c++?
我必须通过使用命令行参数(argv,argc)在c++中的函数内部传递系统配置的详细信息。函数如下所示:
function(char * array[]){
windows_details = array[1];
graphic_card = array[2];
ram_detail = array[3];
procesor_detail = array[4];
}
int main(int argc, char *argv[]){
char *array[] = { argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]};
function(array);
}
因此,当我执行如下程序exe时,我得到了正确的输出:
sample.exe windows_32bit nividia 5Gb i7processor
但我担心的是,每次值都必须按照特定的顺序排列,即用户必须注意"windows_details"将是第一个命令行参数,然后是"graphic_card",就像ram_details和processor_details一样,所以这个解决方案是不可靠的,即如果值序列互换,结果将不正确。我希望解决方案与序列无关,无论是序列,在正确的位置替换的值,以及作为值传递给选项的命令行参数。例如:
sample.exe --configuration i7_processor 5GB windows_32bit nividia or
sample.exe --configuration 5GB i7_processor nividia windows_32bit or
sample.exe --configuration nividia windows_32bit 5GB i7_processor
.
.
所以,和上面一样,有一个选项"--configuration",然后是任何序列中的细节。我尝试添加选项部分如下,但不起作用:
int main(int argc, char *argv[]){
char *array[] = { argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]};
std::string arg = *(reinterpret_cast<std::string*>(&array));
if (arg == "--configuration"){
function(array);
}
else {
std::cout << "Usage " << argv[0] << "t--configtt Specify the configuration of target" << std::endl;
return 1;
}
return 0;
}
所以,请帮我解决我的问题。我该怎么做才能让它在增加选项的同时变得更健壮?
您应该使用getopt
或Boost.ProgramOptions
。*(reinterpret_cast<std::string*>(&array))
很傻,不会做你认为它会做的事。
关于如何使用两者,有很多教程。以下是getopt手册中的一个示例和Boost.ProgramOptions文档的链接
一个简单的BPO示例如下:
po::options_description desc("Allowed options");
desc.add_options()
("help", "produce help message")
("arch", po::value< string >(),
"Windows version")
("card", po::value< string >(),
"Graphics card")
("ram", po::value< string >(),
"Amount of RAM")
("cpu", po::value< string >(),
"Type of processor")
;
po::variables_map vm;
po::store(po::command_line_parser(ac, av).
options(desc).run(), vm);
po::notify(vm);
if (vm.count("help")) {
cout << "Usage: options_description [options]n";
cout << desc;
return 0;
}
如果你愿意,你可以包括对位置选项的支持,但我不完全清楚你打算如何在没有显式开关的情况下区分各种选项。
Boost.Program_options
应该是实现这一目标的最佳选择,但是,如果您不想要boost,并且可以更改函数调用以接受映射,则可以使用非常容易维护和可读的代码,如下所示:
void function( std::unordered_map<std::string, std::string>& arrayMap )
{
windows_details = arrayMap ["--configuration"];
graphic_card = arrayMap ["--graphic_card"];
ram_detail = arrayMap ["--ram_detail"];
procesor_detail = arrayMap ["--procesor_detail"];
}
使用std::find
提取参数的函数
char* extractOption(char** startItr, char** endItr,
const std::string& searchParam)
{
char ** itr = std::find(startItr, endItr, searchParam);
if (itr != endItr && ++itr != endItr)
{
return *itr;
}
return 0;
}
然后你可以使用提取函数来填充地图,如下所示,(仅限伪代码):
int main(int argc, char * argv[])
{
std::unordered_map<std::string, std::string> optionMap;
std::string options[] = { "--configuration",
"--processor_details" ,
"--graphic_card" };
for(const auto& opts: options)
{
char * value= extractOption(argv, argv + argc, opts );
if (value)
{
optionMap[opts] = value ;
}
else
{
std::cout << "Not found : " << opts << 'n';
}
}
function( optionMap ) ;
return 0;
}
See Here
另一种没有第三方库的简单方法是using specific flags
作为(-p,-s,-c…),与参数描述或角色相对应。
然后,在您的代码中,您将得到如下内容:
if (i + 1 != argc) // Check that we haven't finished parsing already
if (argv[i] == "-f") {
// We know the next argument *should* be the filename:
myFile = argv[i + 1];
} else if (argv[i] == "-p") {
myPath = argv[i + 1];
} else if (argv[i] == "-o") {
myOutPath = argv[i + 1];
} else {
std::cout << "Not enough or invalid arguments, please try again.n";
Sleep(2000);
/*
* Sleep for 2 seconds to allow user (if any) to read above statement.
* The issue with this is that if we're a backend program to a GUI as mentioned above;
* that program would also sleep for 2 seconds. Most programs don't
* have this - the console will keep the text there until it scrolls off the page or whatever, so you may aswell leave it out.
***/
exit(0);
}
regex。
这里有一个简单的开始,你可以根据自己的意愿添加更多选项和错误检查。
#include <iostream>
#include <regex>
#include <string>
#include <vector>
#include <algorithm>
#include <cstring>
/*
sample.exe --configuration i7_processor 5GB windows_32bit nividia
sample.exe --configuration 5GB i7_processor nividia windows_32bit
sample.exe --configuration nividia windows_32bit 5GB i7_processor
*/
template<class Iter>
std::pair<Iter, Iter> find_config(Iter first, Iter last)
{
auto begin = std::find(first, last, std::string("--configuration"));
if (begin == last)
{
return { last, last };
}
begin = std::next(begin);
auto end = std::find_if(begin, last, [](auto& opt) {
return opt.substr(0, 2) == "--";
});
return { begin, end };
}
struct configuration
{
std::string processor = "not set";
unsigned long long memory = 0;
std::string os = "not set";
std::string graphics = "not set";
};
std::ostream& operator<<(std::ostream& os, const configuration& conf)
{
os << "processor = " << conf.processor;
os << "nmemory = " << conf.memory;
os << "nos = " << conf.os;
os << "ngraphics = " << conf.graphics;
return os;
}
const std::regex re_processor("(.*)_processor", std::regex::icase);
const std::regex re_memory("(\d+)(mb|gb)", std::regex::icase);
template<class Iter>
auto parse_config(Iter first, Iter last) -> configuration
{
configuration result;
for ( ; first != last ; ++first)
{
auto& option = *first;
std::smatch match;
if (std::regex_match(option, match, re_processor))
{
result.processor = match[1].str();
continue;
}
if (std::regex_match(option, match, re_memory))
{
unsigned long long num = std::stoi(match[1].str());
auto mult = match[2].str();
std::transform(mult.begin(), mult.end(),
mult.begin(),
[](auto& c) { return std::toupper(c); });
if (mult == "GB") {
num *= 1024 * 1024 * 1024;
}
else {
num *= 1024 * 1024;
}
result.memory = num;
continue;
}
}
return result;
}
int main(int argc, const char* const * argv)
{
std::vector<std::string> args(argv, argv + argc);
const auto& progname = &args[0];
auto config_range = find_config(std::next(std::begin(args)), std::end(args));
auto configuration = parse_config(config_range.first, config_range.second);
std::cout << configuration << std::endl;
}
示例运行:
$ sample --configuration i7_processor 5GB windows_32bit nividia
processor = i7
memory = 5368709120
os = not set
graphics = not set
$
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- Win32编译器选项和内存分配
- 如何将enable-if与模板参数和参数包一起使用
- 如何将PERF_AMPLE_READ与mmap一起使用
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- C/C++预处理器是否可以检测一些编译器选项
- 如何将C++中的库和头与MinGW一起使用
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 将--whole archive链接器选项与CMake和具有其他库依赖项的库一起使用
- 为什么我不能将 rand() 与数组的大小一起使用?
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 将“getopt_long”与无法识别的长选项一起使用时出现分段错误
- 如何将cacert.pem与vs2015 curl项目一起包含,因此无需指定Cainfo curl选项
- 如何将命令行参数与c++中的选项一起传递给函数
- 将 -frepo 选项与 G++ 一起使用
- 提升program_options解析选项和参数一起
- 在C++中,如何仅将长选项与必需参数一起使用
- 我可以用Boost::program_options将可猜测和不可猜测的选项解析在一起吗
- 与向量一起使用的C++可为Null/可选项的整数
- OSX 10.8.5 上的 Android 构建错误:cp:-R 和 -r 选项不能一起指定