我正在使用一个简单的命令行应用程序,它接受ASCI文本并将其解释为命令。
我试图通过http://gcc.gnu.org/onlinedocs/cpp/Concatenation.html上的示例来最小化这个应用程序中的冗余。
例如:考虑一个解释命名命令的C程序。可能需要一个命令表,也许是一个声明如下的结构数组:
struct command
{
char *name;
void (*function) (void);
};
struct command commands[] =
{
{ "quit", quit_command },
{ "help", help_command },
...
};
如果不需要给予每个命令名两次,一次在字符串常量中,一次在函数名中,这样会更干净。一个以命令名作为参数的宏可以使这变得不必要。字符串常量可以通过字符串化来创建,函数名可以通过将参数与`_command '连接起来来创建。下面是如何做到的:
#define COMMAND(NAME) { #NAME, NAME ## _command }
struct command commands[] =
{
COMMAND (quit),
COMMAND (help),
...
};
现在,假设我想要一个命令字符串和索引(即:int)值,而不是字符串和函数指针。
struct command
{
char *name;
int command_idx;
};
现在,我有了一种命名命令的方法,并且有了某种索引,以后我可以用它来以编程的方式识别每个命令。例如,我有一个switch语句,它对命令索引进行操作。如果我想处理这些索引,我必须首先手动设置值。
我可以手动创建一个枚举数据类型,但我必须在一个单独的枚举语句中定义枚举常量。enum命令{ cmd_quit = 0,cmd_help },最后,我仍然不得不输入每个命令名两次:一次是通过COMMAND()宏,另一次是在我的枚举中。
是否有任何方法可以使用C预处理器来创建一个宏,创建“command”结构(具有string和int成员),并在我通过COMMAND()宏添加更多命令时自动编号int值(command_idx)?
我也知道我可以在每个可能的命令上使用strcmp()调用,并与用户提供的输入进行比较,但我希望通过command_idx值直接索引命令,而不是每次都对大量命令列表进行strcmp(即:O(1)而不是O(n))。我还想避免不惜一切代价多次键入命令名。
谢谢!
2条答案
按热度按时间ylamdve61#
您可以使用宏重定义来实现这一点。首先,您创建一个文件,其中简单地列出了名为
commands.inc
的命令:然后,在你的C源代码中,你可以多次使用
#include "commands.inc"
,使用不同的COMMAND()
定义来控制它的工作方式。例如:(Note这个特殊的例子依赖于C99的改进,它允许在
enum
声明和复合初始化程序中的列表末尾添加一个尾随的,
-在C89中,通过在末尾添加一个伪条目,可以轻松解决这个问题)。hwazgwia2#
问题:
是否有任何方法可以使用C预处理器来创建一个宏,创建“command”结构(具有string和int成员),并在我通过COMMAND()宏添加更多命令时自动编号int值(command_idx)?
是的,既然你也把这个问题标记为C++:
我只是使用了
map
而不是花哨的新C++11哈希表,因为map
可以与旧的编译器一起工作,并且在真实的削减纳秒。