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

Jim*_*Jim 70 c++ parsing option

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

./myprog --setting=value
Run Code Online (Sandbox Code Playgroud)

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

另请参阅C和Unix的Argument-parsing helpers

Igo*_*nov 39

Boost.Program_options

  • 这似乎是C++最明显的选择,但其文档不够完整.尝试找到如何存储和检索文件中的选项,这是一项基本功能.我不喜欢使用它的代码看起来如何,特别是措辞`options.add_options()(option1)(option2)...`我认为这是滥用C++语法. (9认同)
  • 使用Boost.Program_options编译代码似乎并不简单,除了包含头文件之外,还需要链接选项等等. (7认同)
  • 你可以得到更多相同的东西.如果你想要`--long-option`之类的东西,那么自己做起来相当简单. (2认同)

Mar*_*Gil 24

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;
}
Run Code Online (Sandbox Code Playgroud)

如果您有接受参数的选项,也可以使用optarg.

  • Ughh.我理解在C代码中使用这个库,但IMO,这在我编写的任何C++应用程序中都是不可接受的.如果您不需要纯C.,找一个更好的库. (12认同)

che*_*kow 19

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

  • 我使用过getopt,google的gflags,来自Boost的program_options和tclap是非常棒的*.我不能说tclap足够好的东西,特别是考虑到可用的替代方案.我所拥有的抱怨的程度是,它有助于格式化与我的眼睛习惯的"不同". (4认同)

小智 17

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

  • 我刚尝试了exOptionParser,但它有很多问题.首先,我得到58个关于unsigned int到int转换的警告.它还尝试增加列表迭代器(不能像这样使用)和崩溃.它的界面也很糟糕.它使用遍布各处的引用,而不仅仅返回您想要的数据.它看起来像一个C库,即使它是建立在C++ STL之上的. (6认同)

Max*_*ert 14

并且有一个Google库可用.

实际上,命令行解析是"已解决".选择一个.

  • 我想不出对问题的更无帮助的回答。‘解决了。选一个。' 抱歉,但是“呃”。经过大约 15 分钟的思考这个问题,我想出了大约 30 种不同的解决方案。我怀疑“正确”的响应更类似于解释一组特定的关注点如何导致一组特定的代码实现。但是,嘿,谢谢你打来电话。 (5认同)

Dus*_*ell 8

GNU C库中有这些工具,包括GetOpt.

如果您正在使用Qt并且喜欢GetOpt界面,那么froglogic已经在这里发布了一个很好的界面.


Luc*_*nzo 8

我认为GNU GetOpt不是太直接使用.

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

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

例如,调用:

 ./myProgram -v -p 1234
Run Code Online (Sandbox Code Playgroud)

地图将是:

 ["-v"][""]
 ["-p"]["1234"]
Run Code Online (Sandbox Code Playgroud)

用法是:

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 */
}
Run Code Online (Sandbox Code Playgroud)

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_;
};
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

  • *“...不是太直接使用”*是什么意思?你能详细说明一下吗? (2认同)

jam*_*lin 7

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

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

它提供的许多其他功能不具备覆盖早期选项的功能.例如,如果您有一个shell别名:

alias bar="foo --flag1 --flag2 --flag3"
Run Code Online (Sandbox Code Playgroud)

并且你想使用bar但有--flag1残疾,它允许你做:

bar --flag1=0
Run Code Online (Sandbox Code Playgroud)