Какие библиотеки парсеров параметров существуют для 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;
}

Эти инструменты есть в библиотеке GNU C, которая включает в себя GetOpt.

Если вы используете Qt и вам нравится интерфейс GetOpt, froglogic опубликовал хороший интерфейс здесь.

Говоря о моем собственном гудке, если можно, я также хотел бы предложить взглянуть на библиотеку разбора опций, которую я написал: 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/, очень просто и удобно.

Другие вопросы по тегам