I'd like to pass parameters to my C++ program in the following manner:
./myprog --setting=value
Are there any libraries which will help me to do this easily?
GNU GetOpt.
A simple example using GetOpt:
// C/C++ Libraries:
#include <string>
#include <iostream>
#include <unistd.h>
// Namespaces:
using namespace std;
int main(int argc, char** argv) {
int opt;
bool flagA = false;
bool flagB = false;
// Shut GetOpt error messages down (return '?'):
opterr = 0;
// Retrieve the options:
while ( (opt = getopt(argc, argv, "ab")) != -1 ) { // for each option...
switch ( opt ) {
case 'a':
flagA = true;
break;
case 'b':
flagB = true;
break;
case '?': // unknown option...
cerr << "Unknown option: '" << char(optopt) << "'!" << endl;
break;
}
}
// Debug:
cout << "flagA = " << flagA << endl;
cout << "flagB = " << flagB << endl;
return 0;
}
You can also use optarg if you have options that accept arguments.
TCLAP is a really nice lightweight design and easy to use:
http://tclap.sourceforge.net/
I find it easier to use ezOptionParser. It's also a single header file, does not depend on anything but STL, works for Windows and Linux (very likely other platforms too), has no learning curve thanks to the examples, has features other libraries don't (like file import/export with comments, arbitrary option names with delimiters, auto usage formatting, etc), and is LGPL licensed.
And there's a Google library available.
Really, command-line parsing is "solved." Just pick one.
I think that GNU GetOpt is not too immediate to use.
Qt and Boost could be a solution, but you need to download and compile a lot of code.
So I implemented a parser by myself that produces a std::map<std::string, std::string> of parameters.
For example, calling:
./myProgram -v -p 1234
map will be:
["-v"][""]
["-p"]["1234"]
Usage is:
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;
}
Tooting my own horn if I may, I'd also like to suggest taking a look at an option parsing library that I've written: dropt.
- It's a C library (with a C++ wrapper if desired).
- It's lightweight.
- It's extensible (custom argument types can be easily added and have equal footing with built-in argument types).
- It should be very portable (it's written in standard C) with no dependencies (other than the C standard library).
- It has a very unrestrictive license (zlib/libpng).
One feature that it offers that many others don't is the ability to override earlier options. For example, if you have a shell alias:
alias bar="foo --flag1 --flag2 --flag3"
and you want to use bar but with--flag1 disabled, it allows you to do:
bar --flag1=0
argstream is quite similar to boost.program_option: it permits to bind variables to options, etc. However it does not handle options stored in a configuration file.
Try CLPP library. It's simple and flexible library for command line parameters parsing. Header-only and cross-platform. Uses ISO C++ and Boost C++ libraries only. IMHO it is easier than Boost.Program_options.
Library: http://sourceforge.net/projects/clp-parser/
26 October 2010 - new release 2.0rc. Many bugs fixed, full refactoring of the source code, documentation, examples and comments have been corrected.
Qt 5.2 comes with a command line parser API.
Small example:
#include <QCoreApplication>
#include <QCommandLineParser>
#include <QDebug>
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
app.setApplicationName("ToolX");
app.setApplicationVersion("1.2");
QCommandLineParser parser;
parser.setApplicationDescription("Tool for doing X.");
parser.addHelpOption();
parser.addVersionOption();
parser.addPositionalArgument("infile",
QCoreApplication::translate("main", "Input file."));
QCommandLineOption verbose_opt("+",
QCoreApplication::translate("main", "be verbose"));
parser.addOption(verbose_opt);
QCommandLineOption out_opt(QStringList() << "o" << "output",
QCoreApplication::translate("main", "Output file."),
QCoreApplication::translate("main", "filename"), // value name
QCoreApplication::translate("main", "out") // default value
);
parser.addOption(out_opt);
// exits on error
parser.process(app);
const QStringList args = parser.positionalArguments();
qDebug() << "Input files: " << args
<< ", verbose: " << parser.isSet(verbose_opt)
<< ", output: " << parser.value(out_opt)
<< '\n';
return 0;
}
Example output
The automatically generated help screen:
$ ./qtopt -h Usage: ./qtopt [options] infile Tool for doing X. Options: -h, --help Displays this help. -v, --version Displays version information. -+ be verbose -o, --output Output file. Arguments: infile Input file.
Automatically generated version output:
$ ./qtopt -v ToolX 1.2
Some real calls:
$ ./qtopt b1 -+ -o tmp blah.foo
Input files: ("b1", "blah.foo") , verbose: true , output: "tmp"
$ ./qtopt
Input files: () , verbose: false , output: "out"
A parse error:
$ ./qtopt --hlp Unknown option 'hlp'. $ echo $? 1
Conclusion
If your program already use the Qt (>= 5.2) libraries, its command line parsing API is convenient enough to get the job done.
Be aware that builtin Qt options are consumed by QApplication before the option parser runs.
You could try my little options header (166 loc so easily hackable) options.hpp. It is a single header implementation and should do what you ask. It also prints you the help page automatically.
There are a couples of C++ argument parsers out there, you may want to try this one from http://clp.sourceforge.net/, very simple and convenient.
来源:https://stackoverflow.com/questions/253556/what-parameter-parser-libraries-are-there-for-c