Ich möchte Parameter auf folgende Weise an mein C ++ - Programm übergeben:
./myprog --setting=value
Gibt es Bibliotheken, die mir dabei helfen?
Ich möchte Parameter auf folgende Weise an mein C ++ - Programm übergeben:
./myprog --setting=value
Gibt es Bibliotheken, die mir dabei helfen?
Antworten:
options.add_options()(option1)(option2)...
den ich als Missbrauch der C ++ - Grammatik betrachte.
--long-option
, ist es ziemlich einfach, sich selbst zu tun.
boost::program_options
ist hoffnungslos überarbeitet, schwer zu bedienen und unterdokumentiert. Eine der wenigen Boost-Bibliotheken, die von einer vollständigen Neugestaltung und Neufassung stark profitieren würden. Verwenden Sie es nicht, wenn Sie es vermeiden können.
GNU GetOpt .
Ein einfaches Beispiel mit 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;
}
Sie können optarg auch verwenden, wenn Sie Optionen haben, die Argumente akzeptieren.
Ich finde es einfacher, ezOptionParser zu verwenden . Es ist auch eine einzelne Header-Datei, hängt von nichts anderem als STL ab, funktioniert für Windows und Linux (sehr wahrscheinlich auch für andere Plattformen), hat dank der Beispiele keine Lernkurve und verfügt über Funktionen, die andere Bibliotheken nicht haben (wie den Import / Export von Dateien) mit Kommentaren, beliebigen Optionsnamen mit Trennzeichen, Formatierung der automatischen Verwendung usw.) und ist LGPL-lizenziert.
TCLAP
ist ein wirklich schönes, leichtes Design und einfach zu bedienen:
http://tclap.sourceforge.net/
Und es gibt eine Google-Bibliothek .
Die Befehlszeilenanalyse ist wirklich "gelöst". Wähle einfach einen aus.
Ich denke, dass GNU GetOpt nicht zu unmittelbar zu verwenden ist.
Qt und Boost könnten eine Lösung sein, aber Sie müssen viel Code herunterladen und kompilieren.
Also habe ich selbst einen Parser implementiert, der eine std :: map <std :: string, std :: string> von Parametern erzeugt.
Zum Beispiel:
./myProgram -v -p 1234
Karte wird sein:
["-v"][""]
["-p"]["1234"]
Verwendung ist:
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;
}
Es gibt diese Tools in der GNU C-Bibliothek, die GetOpt enthält .
Wenn Sie Qt und wie die getopt Schnittstelle verwenden, froglogic hat eine schöne Oberfläche veröffentlicht hier .
Wenn ich mein eigenes Horn betätigen darf, möchte ich auch vorschlagen, einen Blick auf eine von mir geschriebene Option zum Parsen von Bibliotheken zu werfen: dropt .
Eine Funktion, die viele andere nicht bieten, ist die Möglichkeit, frühere Optionen zu überschreiben. Wenn Sie beispielsweise einen Shell-Alias haben:
alias bar="foo --flag1 --flag2 --flag3"
und Sie möchten verwenden, bar
aber mit --flag1
deaktiviert, ermöglicht es Ihnen, Folgendes zu tun:
bar --flag1=0
Qt 5.2 wird mit einer Befehlszeilen-Parser-API geliefert .
Kleines Beispiel:
#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;
}
Der automatisch generierte Hilfebildschirm:
$ ./qtopt -h Verwendung: ./qtopt [Optionen] infile Tool für X. Optionen: -h, --help Zeigt diese Hilfe an. -v, --version Zeigt Versionsinformationen an. - + wortreich sein -o, --output Ausgabedatei. Argumente: infile Eingabedatei.
Automatisch generierte Versionsausgabe:
$ ./qtopt -v ToolX 1.2
Einige echte Anrufe:
$ ./qtopt b1 - + -o tmp blah.foo Eingabedateien: ("b1", "blah.foo"), ausführlich: true, Ausgabe: "tmp" $ ./qtopt Eingabedateien: (), ausführlich: false, Ausgabe: "out"
Ein Analysefehler:
$ ./qtopt --hlp Unbekannte Option 'hlp'. $ echo $? 1
Wenn Ihr Programm bereits die Qt-Bibliotheken (> = 5.2) verwendet, ist die Befehlszeilen-Parsing-API praktisch genug, um die Aufgabe zu erledigen.
Beachten Sie, dass integrierte Qt-Optionen von verwendet werden, QApplication
bevor der Optionsparser ausgeführt wird.
argstream
ist ziemlich ähnlich zu boost.program_option
: Es erlaubt das Binden von Variablen an Optionen usw. Es behandelt jedoch keine Optionen, die in einer Konfigurationsdatei gespeichert sind.
Versuchen Sie es mit der CLPP-Bibliothek. Es ist eine einfache und flexible Bibliothek zum Parsen von Befehlszeilenparametern. Nur Header und plattformübergreifend. Verwendet nur ISO C ++ - und Boost C ++ - Bibliotheken. IMHO ist es einfacher als Boost.Program_options.
Bibliothek: http://sourceforge.net/projects/clp-parser/
26. Oktober 2010 - neue Version 2.0rc. Viele Fehler behoben, das vollständige Refactoring des Quellcodes, der Dokumentation, Beispiele und Kommentare wurde korrigiert.
Sie könnten meinen kleinen Options- Header (166 loc so leicht hackbar) options.hpp ausprobieren . Es ist eine einzelne Header-Implementierung und sollte das tun, was Sie verlangen. Außerdem wird die Hilfeseite automatisch gedruckt.