我正在开发一个扫描目录以获取文件信息的程序。用户可以使用可选开关来扫描某些文件组或以某种方式扫描,或以某种方式输出。
例如,如果用户输入:filesum -rRc
,则会执行递归扫描,按升序输出文件,仅扫描与C ++相关的文件扩展名(.cpp | .h | .hpp 等)。
我如何以最干净的方式做到这一点?我已经研究了getopt,但我根本不理解它的实现,并且很难找到文档的好例子。
我正在考虑将输入开关的命令行参数转换为字符串并解析,但是不需要多个if语句来查看它只是参数中的一个开关或者是否存在某些内容以下是-rc
可以完成的吗?或者我也在考虑根据输入的开关使用不同标志的while循环,但如果有更清洁,更简单的方法,我会非常感谢任何建议。感谢。
如果可能的话,宁愿不使用任何第三方库。
答案 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_args
,set()
会调用arguments
中的--help
。对于每个选项,扫描命令行输入并根据需要更新变量。同时,收集元数据并自动生成输出,如gnu程序中的--usage
,--version
,help_args
等选项。
将arguments
作为模板参数传递给define()
的事实是允许从基类调用{{1}},即使它是模板因此不是虚拟的。如果只需要一个操作,那么我们可以切换回普通虚拟方法。
我希望这很干净。我知道有很多工具和库可用,但我真的更喜欢这种方式。我可以在准备好时分享实现,这几乎已经完成了。