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

2023-12-03

我正在使用一个简单的命令行应用程序,它接受 ASCII 文本并将其解释为命令。

我尝试通过以下示例最小化此应用程序中的冗余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 语句。如果我想处理这些索引,我必须首先手动设置值。

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

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

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

Thanks!


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

COMMAND(quit)
COMMAND(help)
...

然后,在你的 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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在结构中使用 typedef 来命名和索引文本命令 的相关文章

  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • C++:无法使用scoped_allocator_adaptor传播polymorphic_allocator

    我有一个vector
  • Func 方法参数的首选命名约定是什么?

    我承认这个问题是主观的 但我对社区的观点感兴趣 我有一个缓存类 它采用类型的缓存加载器函数Func
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • 使用向量的 merge_sort 在少于 9 个输入的情况下效果很好

    不知何故 我使用向量实现了合并排序 问题是 它可以在少于 9 个输入的情况下正常工作 但在有 9 个或更多输入的情况下 它会执行一些我不明白的操作 如下所示 Input 5 4 3 2 1 6 5 4 3 2 1 9 8 7 6 5 4 3
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • 我的 strlcpy 版本

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co
  • 不同类型的指针可以互相分配吗?

    考虑到 T1 p1 T2 p2 我们可以将 p1 分配给 p2 或反之亦然吗 如果是这样 是否可以不使用强制转换来完成 或者我们必须使用强制转换 首先 让我们考虑不进行强制转换的分配 C 2018 6 5 16 1 1 列出了简单赋值的约束

随机推荐