C ++有哪些参数解析器库?

时间:2008-10-31 13:54:51

标签: c++ parsing option

我想以下列方式将参数传递给我的C ++程序:

./myprog --setting=value

是否有任何图书馆可以帮助我轻松完成这项工作?

另见Argument-parsing helpers for C and Unix

13 个答案:

答案 0 :(得分:37)

答案 1 :(得分:22)

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

答案 2 :(得分:19)

TCLAP是一个非常好的轻量级设计,易于使用: http://tclap.sourceforge.net/

答案 3 :(得分:17)

我发现使用ezOptionParser更容易。它也是一个单独的头文件,除了STL之外不依赖于任何东西,适用于Windows和Linux(很可能也适用于其他平台),由于这些示例没有学习曲线,还有其他库不具备的功能(例如带注释的文件导入/导出,带分隔符的任意选项名称,自动使用格式等),并且是LGPL许可。

答案 4 :(得分:14)

并且有Google library可用。

实际上,命令行解析已“解决”。只需选一个。

答案 5 :(得分:8)

GNU C库中有these个工具,其中包含GetOpt

如果您正在使用Qt并且喜欢GetOpt界面,froglogic已发布了一个不错的界面here

答案 6 :(得分:7)

我认为GNU GetOpt不能立即使用。

Qt和Boost可能是一个解决方案,但您需要下载并编译大量代码。

所以我自己实现了一个解析器,它生成了一个std :: map&lt; std :: string,std :: string&gt;参数。

例如,呼叫:

 ./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;
}

答案 7 :(得分:6)

如果可能的话,我自己也会发出自己的号角,我还想建议看一下我写过的解析库的选项:dropt

  • 这是一个C库(如果需要,可以使用C ++包装器)。
  • 它很轻。
  • 它是可扩展的(自定义参数类型可以轻松添加,并与内置参数类型具有相同的基础)。
  • 它应该是非常可移植的(用标准C编写),没有依赖性(除了C标准库)。
  • 它有一个非常无限制的许可证(zlib / libpng)。

它提供的一个功能是许多其他功能不能覆盖之前的选项。例如,如果您有一个shell别名:

alias bar="foo --flag1 --flag2 --flag3"

并且您希望使用bar但禁用--flag1,则可以执行以下操作:

bar --flag1=0

答案 8 :(得分:3)

argstreamboost.program_option非常相似:它允许将变量绑定到选项等。但是它不处理存储在配置文件中的选项。

答案 9 :(得分:3)

尝试CLPP库。它是用于命令行参数解析的简单而灵活的库。仅限标题和跨平台。仅使用ISO C ++和Boost C ++库。恕我直言,它比Boost.Program_options更容易。

图书馆:http://sourceforge.net/projects/clp-parser/

2010年10月26日 - 新版本2.0rc。修复了许多错误,修改了源代码,文档,示例和注释的完全重构。

答案 10 :(得分:3)

Qt 5.2带有command line parser 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
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.

自动生成的版本输出:

$ ./qtopt -v
ToolX 1.2

一些真实的电话:

$ ./qtopt b1 -+ -o tmp blah.foo
Input files:  ("b1", "blah.foo") , verbose:  true , output:  "tmp"
$ ./qtopt          
Input files:  () , verbose:  false , output:  "out"

解析错误:

$ ./qtopt --hlp
Unknown option 'hlp'.
$ echo $?
1

结论

如果你的程序已经使用了Qt(&gt; = 5.2)库,那么它的命令行解析API就足以让你完成工作。

请注意,在选项解析器运行之前,QApplication会使用内置Qt选项。

答案 11 :(得分:1)

你可以尝试我的小选项标题(166 loc很容易被黑客攻击)options.hpp。它是一个单头实现,应该按照你的要求做。它还会自动打印帮助页面。

答案 12 :(得分:-2)

有一对C ++参数解析器,你可能想从http://clp.sourceforge.net/尝试这个,非常简单方便。