C ++有哪些参数解析器库?[关闭]


76

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

./myprog --setting=value

有没有可以帮助我轻松完成此任务的库?

另请参见C和Unix的参数解析帮助器


最近为现代C ++编写了此代码:github.com/juzzlin/Argengine
juzzlin

Answers:


45

13
对于C ++,这似乎是最明显的选择,但其文档不够完整。尝试在那里找到如何存储和检索文件选项的基本功能。我不喜欢使用它的代码的外观,特别是options.add_options()(option1)(option2)...我认为滥用C ++语法的措辞。
gatopeich

8
使用Boost.Program_options编译代码似乎并不简单,而且除了包含头文件之外,还需要其他链接选项。
理查德

2
您可以花更少的钱获得几乎相同的东西。如果您想要这样的东西--long-option,那么做自己就很简单。
路易斯·马丘卡

在一个极端情况下,对于非常简单的程序,或者您直接使用argv []数组。另一种情况是,为了使您的参数具有更大的灵活性,您可以直接使用argv数组(您可以执行编-1 firstinput -2 second input -obj {constructor arguments ..})。否则,请使用boost,tclap或其他许多方法。
Kemin Zhou

boost::program_options无可救药地过度设计,难以使用且文档不足。完全通过重新设计和重写而大大受益的少数Boost库之一。如果可以避免,请不要使用它。
Laryx Decidua

26

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


14
嗯 我了解此库在C代码中的使用,但是IMO,这太低了,我在以前编写的任何C ++应用程序中都无法接受。找到一个更好的图书馆,如果你不需要纯C.
托马斯Eding

1
还有一个带有值的getopt的GNU示例,例如myexe -c myvalue您可以尝试搜索“使用getopt解析参数的示例”
edW

这是GNU本身提供的示例示例^^
finnmglas

19

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


1
从版本0.1.3开始,许可证现在为MIT。我正在一个新项目而不是TCLAP上进行尝试,到目前为止看起来非常有希望。文件配置选项非常好。
肖恩

6
我刚刚尝试了exOptionParser,但是它有很多问题。首先,我收到58条关于unsigned int到int转换的警告。它还尝试增加列表迭代器(不能那样使用)并崩溃。它的界面也是如此糟糕。它在各处使用引用,而不仅仅是返回所需的数据。即使它建立在C ++ STL之上,它看起来也像C库。
安德鲁·拉尔森

注意; 检测未知参数不起作用。此外,如果未将标头放在其他标头之前,则会产生编译错误。我会寻找另一种解析器..
Totte卡尔森

19

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


4
我用过getopt,google的gflag,Boost和tclap的program_options很棒。关于tclap,我不能说太多好事,尤其是考虑到可用的替代品。我所掌握的范围是,帮助格式化与我的眼睛习惯“不同”。
肖恩

16

并且有一个可用的Google库

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


(感谢@QPaysTaxes注意到链接已断开;我不知道为什么您的编辑被拒绝,但您绝对正确)。
Max Lybbert

5
我想不出一个对问题的帮助较小的答复。``解决了。选一个。' 抱歉,但是““”。经过大约15分钟的思考时间,我得出了大约30种有关如何解决该问题的方案。我怀疑“正确”的响应更类似于解释特定问题集如何导致特定代码实现集。但是,嘿,谢谢您的来电。
MarkWayne

10

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

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

所以我自己实现了一个解析器,该解析器生成了一个std :: map <std :: string,std :: string>参数。

例如,调用:

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

2
您所说的“ ...使用起来不太即时”是什么意思?你能详细说明吗?
彼得·莫滕森


7

如果可以的话,我也想嘟嘟响,我还建议您看一下我编写的一个选项解析库:dropt

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

它提供了许多其他功能所没有的功能,就是可以覆盖早期的选项。例如,如果您具有外壳程序别名:

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

而您想使用bar但已--flag1禁用,则可以执行以下操作:

bar --flag1=0

1
这看起来很整洁。很高兴我向下滚动;对于纯C语言来说,没有什么好用的,请保存!
Asherah

听起来不错,但似乎太大了。另外,我只是在寻找一种从参数中解析出scanf格式说明符的方法,我已经编写了自己的(虽然更基本的)解析器。
MarcusJ '16

1
@MarcusJ您似乎说这太大了(它比大多数其他命令行选项解析器小得多),却希望它解析printf / scanf格式说明符(这不是命令行的东西),这似乎有点奇怪选项解析器通常会做)...
jamesdlin

是的,我知道我对此有一些特定的要求,我将继续重写我的选项解析器,但是我确实看过了您的代码,传入一个结构以包含各种选项的想法真的很有趣(到目前为止,我的代码只是硬编码的)。它本身并不太大,只是我只有一个.c / .h项目,而您的代码将使我已经拥有的代码量增加一倍,因此对于我的特定项目来说太大了。
MarcusJ '16

5

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 [选项]文件中
做X的工具。

选项:
  -h,--help显示此帮助。
  -v,--version显示版本信息。
  -+冗长
  -o,--output输出文件。

参数:
  infile输入文件。

自动生成的版本输出:

$ ./qtopt -v
ToolX 1.2

一些真实的电话:

$ ./qtopt b1-+ -o tmp blah.foo
输入文件:(“ b1”,“ blah.foo”),详细:true,输出:“ tmp”
$ ./qtopt          
输入文件:(),详细:false,输出:“ out”

解析错误:

$ ./qtopt --hlp
未知选项“ hlp”。
$ echo $?
1个

结论

如果您的程序已经使用Qt(> = 5.2)库,则其命令行解析API足够方便来完成工作。

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


3

argstream完全类似于boost.program_option:它允许将变量绑定到选项等。但是,它不处理存储在配置文件中的选项。


3

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

库:http//sourceforge.net/projects/clp-parser/

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


1

您可以尝试使用我的小选项标头(166个位置,很容易被黑客入侵)options.hpp。它是一个单头实现,应该按照您的要求进行。它还会自动打印帮助页面。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.