如果程序被指定像这样运行,那么在c++中解析命令行参数的最佳方式是什么:
prog [-abc] [input [output]]
是否有某种方法可以在标准库中实现这一点,或者我需要自己编写代码?
相关:
在unicode c++应用程序中解析命令行参数
如果程序被指定像这样运行,那么在c++中解析命令行参数的最佳方式是什么:
prog [-abc] [input [output]]
是否有某种方法可以在标准库中实现这一点,或者我需要自己编写代码?
相关:
在unicode c++应用程序中解析命令行参数
当前回答
boost::program_options和GNU getopt的建议是很好的。
然而,对于简单的命令行选项,我倾向于使用std::find
例如,在-f命令行参数后读取文件名。您还可以检测是否传入了一个单字选项,例如-h,以寻求帮助。
#include <algorithm>
char* getCmdOption(char ** begin, char ** end, const std::string & option)
{
char ** itr = std::find(begin, end, option);
if (itr != end && ++itr != end)
{
return *itr;
}
return 0;
}
bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
return std::find(begin, end, option) != end;
}
int main(int argc, char * argv[])
{
if(cmdOptionExists(argv, argv+argc, "-h"))
{
// Do stuff
}
char * filename = getCmdOption(argv, argv + argc, "-f");
if (filename)
{
// Do interesting things
// ...
}
return 0;
}
使用这种方法需要注意的一点是,必须使用std::strings作为std::find的值,否则将对指针值执行相等性检查。
我希望它是可以编辑这个回应,而不是添加一个新的,因为这是基于原始的答案。我稍微重写了函数,并将它们封装在一个类中,下面是代码。我认为这样使用也很实用:
class InputParser{
public:
InputParser (int &argc, char **argv){
for (int i=1; i < argc; ++i)
this->tokens.push_back(std::string(argv[i]));
}
/// @author iain
const std::string& getCmdOption(const std::string &option) const{
std::vector<std::string>::const_iterator itr;
itr = std::find(this->tokens.begin(), this->tokens.end(), option);
if (itr != this->tokens.end() && ++itr != this->tokens.end()){
return *itr;
}
static const std::string empty_string("");
return empty_string;
}
/// @author iain
bool cmdOptionExists(const std::string &option) const{
return std::find(this->tokens.begin(), this->tokens.end(), option)
!= this->tokens.end();
}
private:
std::vector <std::string> tokens;
};
int main(int argc, char **argv){
InputParser input(argc, argv);
if(input.cmdOptionExists("-h")){
// Do stuff
}
const std::string &filename = input.getCmdOption("-f");
if (!filename.empty()){
// Do interesting things ...
}
return 0;
}
其他回答
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i],"-i")==0) {
filename = argv[i+1];
printf("filename: %s",filename);
} else if (strcmp(argv[i],"-c")==0) {
convergence = atoi(argv[i + 1]);
printf("\nconvergence: %d",convergence);
} else if (strcmp(argv[i],"-a")==0) {
accuracy = atoi(argv[i + 1]);
printf("\naccuracy:%d",accuracy);
} else if (strcmp(argv[i],"-t")==0) {
targetBitRate = atof(argv[i + 1]);
printf("\ntargetBitRate:%f",targetBitRate);
} else if (strcmp(argv[i],"-f")==0) {
frameRate = atoi(argv[i + 1]);
printf("\nframeRate:%d",frameRate);
}
}
TCLAP是一个非常好的轻量级设计,易于使用: http://tclap.sourceforge.net/
我认为GNU GetOpt并不是马上就可以使用的。
Qt和Boost可能是一种解决方案,但您需要下载并编译大量代码。
所以我自己实现了一个解析器,它产生一个std::map<std::string, std::string>的参数。
例如,调用:
./myProgram -v -p 1234
地图将是:
["-v"][""]
["-p"]["1234"]
用法是:
int main(int argc, char *argv[]) {
MainOptions mo(argc, argv);
MainOptions::Option* opt = mo.getParamFromKey("-p");
const string type = opt ? (*opt).second : "";
cout << type << endl; /* Prints 1234 */
/* Your check code */
}
MainOptions.h
#ifndef MAINOPTIONS_H_
#define MAINOPTIONS_H_
#include <map>
#include <string>
class MainOptions {
public:
typedef std::pair<std::string, std::string> Option;
MainOptions(int argc, char *argv[]);
virtual ~MainOptions();
std::string getAppName() const;
bool hasKey(const std::string&) const;
Option* getParamFromKey(const std::string&) const;
void printOptions() const;
private:
typedef std::map<std::string, std::string> Options;
void parse();
const char* const *begin() const;
const char* const *end() const;
const char* const *last() const;
Options options_;
int argc_;
char** argv_;
std::string appName_;
};
MainOptions.cpp
#include "MainOptions.h"
#include <iostream>
using namespace std;
MainOptions::MainOptions(int argc, char* argv[]) :
argc_(argc),
argv_(argv) {
appName_ = argv_[0];
this->parse();
}
MainOptions::~MainOptions() {
}
std::string MainOptions::getAppName() const {
return appName_;
}
void MainOptions::parse() {
typedef pair<string, string> Option;
Option* option = new pair<string, string>();
for (const char* const * i = this->begin() + 1; i != this->end(); i++) {
const string p = *i;
if (option->first == "" && p[0] == '-') {
option->first = p;
if (i == this->last()) {
options_.insert(Option(option->first, option->second));
}
continue;
} else if (option->first != "" && p[0] == '-') {
option->second = "null"; /* or leave empty? */
options_.insert(Option(option->first, option->second));
option->first = p;
option->second = "";
if (i == this->last()) {
options_.insert(Option(option->first, option->second));
}
continue;
} else if (option->first != "") {
option->second = p;
options_.insert(Option(option->first, option->second));
option->first = "";
option->second = "";
continue;
}
}
}
void MainOptions::printOptions() const {
std::map<std::string, std::string>::const_iterator m = options_.begin();
int i = 0;
if (options_.empty()) {
cout << "No parameters\n";
}
for (; m != options_.end(); m++, ++i) {
cout << "Parameter [" << i << "] [" << (*m).first << " " << (*m).second
<< "]\n";
}
}
const char* const *MainOptions::begin() const {
return argv_;
}
const char* const *MainOptions::end() const {
return argv_ + argc_;
}
const char* const *MainOptions::last() const {
return argv_ + argc_ - 1;
}
bool MainOptions::hasKey(const std::string& key) const {
return options_.find(key) != options_.end();
}
MainOptions::Option* MainOptions::getParamFromKey(
const std::string& key) const {
const Options::const_iterator i = options_.find(key);
MainOptions::Option* o = 0;
if (i != options_.end()) {
o = new MainOptions::Option((*i).first, (*i).second);
}
return o;
}
提高program_options。
如果你只想自己处理命令行选项,最简单的方法是:
vector<string> args(argv + 1, argv + argc);
在main()的顶部。这将把所有命令行参数复制到std::strings的向量中。然后,您可以使用==轻松地比较字符串,而不是无休止的strcmp()调用。例如:
int main(int argc, char **argv) {
vector<string> args(argv + 1, argv + argc);
string infname, outfname;
// Loop over command-line args
// (Actually I usually use an ordinary integer loop variable and compare
// args[i] instead of *i -- don't tell anyone! ;)
for (auto i = args.begin(); i != args.end(); ++i) {
if (*i == "-h" || *i == "--help") {
cout << "Syntax: foomatic -i <infile> -o <outfile>" << endl;
return 0;
} else if (*i == "-i") {
infname = *++i;
} else if (*i == "-o") {
outfname = *++i;
}
}
}
[编辑:我意识到我正在复制argv[0],程序的名称,到args -已修复。]