1

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

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

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

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

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

4

3 回答 3

0

我检查了 gnu cat 如何处理命令行选项。我用 C 编写了示例。您可以传递以下标志:cli -ab 文件或 cli -b -ac 文件或 cli -bc 文件 -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;
        }
    }
}
于 2013-08-03T01:27:44.920 回答
0

最干净的方法是使用Boostprogram_options

于 2013-08-03T01:12:46.277 回答
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_args,而后者又调用set()arguments。对于每个选项,都会扫描命令行输入并根据需要更新变量。同时,像在 gnu 程序中一样--help,元数据被收集并自动为选项生成输出,如 , 。--usage--version

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

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

于 2013-08-03T02:40:02.657 回答