在struct中使用typedef来命名和索引文本命令

Clo*_*oud 2 c c++ c-preprocessor

我正在使用一个简单的命令行应用程序,它接收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 },
   ...
 };
Run Code Online (Sandbox Code Playgroud)

如果必须给每个命令名两次,一次在字符串常量中,一次在函数名中,则更清楚.将命令名称作为参数的宏可以使其不必要.字符串常量可以使用字符串化创建,函数名称可以通过将参数与`_command'连接来创建.以下是它的完成方式:

 #define COMMAND(NAME)  { #NAME, NAME ## _command }

 struct command commands[] =
 {
   COMMAND (quit),
   COMMAND (help),
   ...
 };
Run Code Online (Sandbox Code Playgroud)

现在,假设我想要一个命令字符串和索引(即:int)值,而不是字符串和函数指针.

 struct command
 {
   char *name;
   int command_idx;
 };
Run Code Online (Sandbox Code Playgroud)

现在,我有一种命名命令的方法,并且有一些我稍后可以用来以编程方式识别每个命令的索引.例如,我有一个对命令索引进行操作的switch语句.如果我想处理这些索引,我必须先手动设置值.

我可以手动创建枚举数据类型,但后来我在单独的枚举语句中定义了枚举常量.IE:枚举命令{cmd_quit = 0,cmd_help},最后,我仍然需要两次输入每个命令名:一次通过COMMAND()宏,再一次在我的枚举中.

是否有任何方法使用C预处理器允许我创建一个宏创建"命令"结构(使用字符串和int成员),并自动编号int值(command_idx),因为我通过COMMAND()添加更多命令宏?

我也知道我可以对每个可能的命令使用strcmp()调用,并与用户提供的输入进行比较,但是我希望通过command_idx值直接将命令索引到命令中,而不是strcmp每次都反对大量命令(即:O(1)而不是O(n)).我还想避免不惜一切代价多次输入命令名.

谢谢!

caf*_*caf 5

您可以使用宏重定义来实现此目的.首先,创建一个只列出命令的文件commands.inc:

COMMAND(quit)
COMMAND(help)
...
Run Code Online (Sandbox Code Playgroud)

然后,在您的C源代码中,您可以#include "commands.inc"多次使用不同的有效定义COMMAND()来控制它的工作方式.例如:

struct command
{
   char *name;
   int command_idx;
};

#define COMMAND(NAME) CMD_ ## NAME,

enum command_enum {
#include "commands.inc"
};

#undef COMMAND

#define COMMAND(NAME) { #NAME, CMD_ ## NAME },

struct command commands[] =
{
#include "commands.inc"
};

#undef COMMAND
Run Code Online (Sandbox Code Playgroud)

(请注意,此特定示例依赖于C99改进,允许,enum声明和复合初始化器中的列表末尾进行尾随- 您可以通过在末尾添加虚拟条目来轻松解决C89中的问题).