解析多个命令行开关

时间:2013-08-03 01:10:22

标签: c++ command-line command-line-arguments

我正在开发一个扫描目录以获取文件信息的程序。用户可以使用可选开关来扫描某些文件组或以某种方式扫描,或以某种方式输出。

例如,如果用户输入:filesum -rRc,则会执行递归扫描,按升序输出文件,仅扫描与C ++相关的文件扩展名(.cpp | .h | .hpp )。

我如何以最干净的方式做到这一点?我已经研究了getopt,但我根本不理解它的实现,并且很难找到文档的好例子。

我正在考虑将输入开关的命令行参数转换为字符串并解析,但是不需要多个if语句来查看它只是参数中的一个开关或者是否存在某些内容以下是-rc可以完成的吗?或者我也在考虑根据输入的开关使用不同标志的while循环,但如果有更清洁,更简单的方法,我会非常感谢任何建议。感谢。

如果可能的话,宁愿不使用任何第三方库。

3 个答案:

答案 0 :(得分:0)

最简洁的方法是使用Boost program_options

答案 1 :(得分:0)

我检查了gnu cat如何处理命令行选项。我在C中写了一个例子。您可以传递以下标志:cli -ab file或cli -b -ac file或cli -bc file -a

#include <stdio.h>

int main (int argc, char *argv) {
    int c;
    while ((c = getopt(argc, argv, "abc")) != -1) {
        switch (c) {
            case 'a':
                printf("selected: a\n");
                break;
            case 'b':
                printf("selected: b\n");
                break;
            case 'c':
                printf("selected: c\n");
                break;
            default:
                printf("Usage: cli -a/-b/-c\n");
                break;
        }
    }
}

答案 2 :(得分:0)

这很有趣,我现在正在这样做。我只会在这里描述一般的想法。完整代码目前超过500行,并使用更多实用程序进行格式化等。

作为一个例子,我正在制作程序help(非常虚拟)。普通结构包含程序所需的所有选项以及默认值:

struct help_opt
{
    string owner;
    string path;
    bool rec;
    int depth;
    help_opt() : owner(""), path("/"), rec(false), depth(0) { }
};

另一个结构模拟命令行参数:

struct help_args : public help_opt, public arguments <help_args>
{
    template <typename S>
    void define(S& s)
    {
        set(s, owner,   "owner",    'w',  "force <name> as owner",         "name");
        set(s, path,    "output",   'o',  "save all output to <path>",     "path");
        set(s, rec,     "recurse",  'r',  "recurse into sub-topics");
        set(s, depth,   "depth",    'd',  "set <number> as maximum depth", "number");
    }

    string title() const { return "my help"; }
    string usage() const { return "help [<options>] [<topic>]"; }

    string info() const
    {
        return
            "Display help on <topic>, "
            "or list available topics if no <topic> is given.";
    }

    help_args(int argc, char* argv[]) : arguments(argc, argv) { }
};

其中,类arguments是我需要的所有基础设施。所有参数以及元数据(名称,缩写等)都在define()中定义,每个参数都调用方法set()

参数s用于支持多个操作,例如收集用户输入,构建帮助文本或显示用户给出的值。然后我们传递对每个成员的引用,可以根据用户输入给出适当的值,或者保留默认值。然后是参数名称,缩写,完整帮助文本和可选的参数名称。布尔参数被单独处理为标志,没有参数。

其他方法title()info()等指定了程序自定义的信息消息。

实际处理由arguments的构造函数完成。这会在define()中调用help_argsset()会调用arguments中的--help。对于每个选项,扫描命令行输入并根据需要更新变量。同时,收集元数据并自动生成输出,如gnu程序中的--usage--versionhelp_args等选项。

arguments作为模板参数传递给define()的事实是允许从基类调用{{1}},即使它是模板因此不是虚拟的。如果只需要一个操作,那么我们可以切换回普通虚拟方法。

我希望这很干净。我知道有很多工具和库可用,但我真的更喜欢这种方式。我可以在准备好时分享实现,这几乎已经完成了。