如果程序被指定像这样运行,那么在c++中解析命令行参数的最佳方式是什么:

prog [-abc] [input [output]]

是否有某种方法可以在标准库中实现这一点,或者我需要自己编写代码?


相关:

在unicode c++应用程序中解析命令行参数


当前回答

我可以建议使用模板化的c++命令行解析器库(GitHub上的一些分支是可用的),API非常直接并且(引用自网站):

该库完全在头文件中实现,因此很容易 与其他软件一起使用和分发。它是MIT授权的 无后顾之忧的发行许可证。

这是手册中的一个例子,为了简单起见,这里有颜色:

#include <string>
#include <iostream>
#include <algorithm>
#include <tclap/CmdLine.h>

int main(int argc, char** argv)
{

    // Wrap everything in a try block.  Do this every time,
    // because exceptions will be thrown for problems.
    try {

    // Define the command line object, and insert a message
    // that describes the program. The "Command description message"
    // is printed last in the help text. The second argument is the
    // delimiter (usually space) and the last one is the version number.
    // The CmdLine object parses the argv array based on the Arg objects
    // that it contains.
    TCLAP::CmdLine cmd("Command description message", ' ', "0.9");

    // Define a value argument and add it to the command line.
    // A value arg defines a flag and a type of value that it expects,
    // such as "-n Bishop".
    TCLAP::ValueArg<std::string> nameArg("n","name","Name to print",true,"homer","string");

    // Add the argument nameArg to the CmdLine object. The CmdLine object
    // uses this Arg to parse the command line.
    cmd.add( nameArg );

    // Define a switch and add it to the command line.
    // A switch arg is a boolean argument and only defines a flag that
    // indicates true or false.  In this example the SwitchArg adds itself
    // to the CmdLine object as part of the constructor.  This eliminates
    // the need to call the cmd.add() method.  All args have support in
    // their constructors to add themselves directly to the CmdLine object.
    // It doesn't matter which idiom you choose, they accomplish the same thing.
    TCLAP::SwitchArg reverseSwitch("r","reverse","Print name backwards", cmd, false);

    // Parse the argv array.
    cmd.parse( argc, argv );

    // Get the value parsed by each arg.
    std::string name = nameArg.getValue();
    bool reverseName = reverseSwitch.getValue();

    // Do what you intend.
    if ( reverseName )
    {
            std::reverse(name.begin(),name.end());
            std::cout << "My name (spelled backwards) is: " << name << std::endl;
    }
    else
            std::cout << "My name is: " << name << std::endl;


    } catch (TCLAP::ArgException &e)  // catch any exceptions
    { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; }
}

其他回答

我在一些项目中使用过GetPot: http://getpot.sourceforge.net/

主要特点:所有东西都在一个头文件中,没有构建的麻烦。只需将它保存在你机器上的某个地方,并在你的文件中使用main()

最近没有更新,但它有很好的文档记录,工作得很好。

你的C/ c++程序总是有一个主函数。它是这样的:

    int main(int argc, char**argv) {
        ...
    }

这里argc是一些命令行参数,已经传递给你的程序,argv是一个包含这些参数的字符串数组。因此,命令行参数由调用方进程分隔开(不像在windows中那样是一行)。

现在你需要整理它们:

命令名总是第一个参数(索引0)。 选项只是指定程序应如何工作的特殊参数。按照惯例,它们从-号开始。通常-对于一个字母的选项和-对于任何更长。所以在你的任务中“选项”都是参数,从-开始,而不是第0个。 参数。只是所有其他不是程序名或选项的参数。

还有另一种选择是精益平均c++选项解析器:

http://optionparser.sourceforge.net

它是一个只包含头文件的库(实际上只有一个头文件),与所有其他建议不同 也是独立的,即它没有任何依赖关系。特别是,它不依赖于STL。它甚至不使用异常或任何其他需要库支持的东西。这意味着它可以与普通C语言或其他语言链接,而无需引入“外国”库。

像boost::program_options一样,它的API提供了方便的直接访问选项, 也就是说,你可以这样写代码

如果 (选项[帮助]) ... ;

and

int VERBOSE = options[VERBOSE].count();

然而,与boost::program_options不同的是,这只是使用一个带有(用户提供的)enum索引的数组。这提供了没有权重的关联容器的便利。

它有良好的文档记录,并具有公司友好的许可证(MIT)。

tlmc++ OP包含了一个很好的格式化程序,用于使用可以执行的消息 行换行和列对齐在本地化程序时非常有用,因为它可以确保即使在具有较长消息的语言中输出也会很好。它还省去了手动格式化80列的麻烦。

您可以使用GNU GetOpt (LGPL)或各种c++端口之一,例如getoptpp (GPL)。

一个简单的例子使用GetOpt你想要的东西(prog [-ab] input)如下:

// C Libraries:
#include <string>
#include <iostream>
#include <unistd.h>

// Namespaces:
using namespace std;

int main(int argc, char** argv) {
    int opt;
    string input = "";
    bool flagA = false;
    bool flagB = false;

    // Retrieve the (non-option) argument:
    if ( (argc <= 1) || (argv[argc-1] == NULL) || (argv[argc-1][0] == '-') ) {  // there is NO input...
        cerr << "No argument provided!" << endl;
        //return 1;
    }
    else {  // there is an input...
        input = argv[argc-1];
    }

    // Debug:
    cout << "input = " << input << endl;

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

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