Какие библиотеки парсеров параметров существуют для C++?
Я хотел бы передать параметры моей программе на C++ следующим образом:
./myprog --setting=value
Есть ли библиотеки, которые помогут мне сделать это легко?
Смотрите также помощники по анализу аргументов для C и Unix
13 ответов
GNU GetOpt.
Простой пример с использованием 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;
}
Вы также можете использовать optarg, если у вас есть опции, которые принимают аргументы.
TCLAP
действительно хороший легкий дизайн и простой в использовании: http://tclap.sourceforge.net/
Мне проще использовать ezOptionParser. Это также один заголовочный файл, не зависящий ни от чего, кроме STL, работает для Windows и Linux (весьма вероятно, и для других платформ), не имеет кривой обучения благодаря примерам, имеет функции, которых нет в других библиотеках (например, импорт / экспорт файлов) с комментариями, произвольными именами опций с разделителями, автоматическим форматированием использования и т. д.) и лицензией LGPL.
И есть библиотека Google доступна.
Действительно, анализ командной строки "решен". Просто выберите один.
Я думаю, что GNU GetOpt не слишком быстро использовать.
Qt и Boost могут быть решением, но вам нужно скачать и скомпилировать много кода.
Поэтому я сам реализовал парсер, который выдает параметры std:: map
Например, позвонив:
./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;
}
Говоря о моем собственном гудке, если можно, я также хотел бы предложить взглянуть на библиотеку разбора опций, которую я написал: dropt.
- Это библиотека C (с оболочкой C++ по желанию).
- Это легкий.
- Он расширяемый (пользовательские типы аргументов могут быть легко добавлены и иметь равные возможности со встроенными типами аргументов).
- Он должен быть очень переносимым (написан на стандартном C) без каких-либо зависимостей (кроме стандартной библиотеки C).
- У него очень неограниченная лицензия (zlib/libpng).
Одна особенность, которую он предлагает, а многие другие не предлагают, - это возможность переопределять более ранние параметры. Например, если у вас есть псевдоним оболочки:
alias bar="foo --flag1 --flag2 --flag3"
и вы хотите использовать bar
но с--flag1
отключено, это позволяет делать:
bar --flag1=0
Qt 5.2 поставляется с API анализатора командной строки.
Небольшой пример:
#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;
}
Пример вывода
Автоматически сгенерированный экран справки:
$./qtopt -h Использование: ./qtopt [options] infile Инструмент для выполнения X. Опции: -h, --help Отображает эту справку. -v, --version Отображает информацию о версии. -+ быть многословным -o, --output Выходной файл. Аргументы: infile Входной файл.
Автоматически сгенерированный вывод версии:
$./qtopt -v ToolX 1.2
Некоторые реальные звонки:
$./qtopt b1 - + -o tmp blah.foo Входные файлы: ("b1", "blah.foo"), verbose: true, вывод: "tmp" $ ./qtopt Входные файлы: (), подробный: false, вывод: "out"
Ошибка разбора:
$./qtopt --hlp Неизвестная опция 'hlp'. $ echo $? 1
Заключение
Если ваша программа уже использует библиотеки Qt (>= 5.2), ее API синтаксического анализа командной строки достаточно удобен для выполнения работы.
Помните, что встроенные опции Qt используются QApplication
перед запуском парсера опций.
argstream
очень похоже на boost.program_option
: он позволяет связывать переменные с опциями и т. д. Однако он не обрабатывает опции, хранящиеся в файле конфигурации.
Попробуйте библиотеку CLPP. Это простая и гибкая библиотека для разбора параметров командной строки. Только заголовок и кроссплатформенность. Используются только библиотеки ISO C++ и Boost C++. ИМХО это проще, чем Boost.Program_options.
Библиотека: http://sourceforge.net/projects/clp-parser/
26 октября 2010 - новый релиз 2.0rc. Исправлено множество ошибок, исправлен полный рефакторинг исходного кода, документации, примеров и комментариев.
Вы можете попробовать мой маленький заголовок options (166 loc, так что его легко взломать) options.hpp. Это реализация с одним заголовком и должна делать то, что вы просите. Он также автоматически распечатывает страницу справки.
Существует пара синтаксических анализаторов C++, вы можете попробовать это с http://clp.sourceforge.net/, очень просто и удобно.