具有不同函数原型的函数查找表

2024-01-11

除了一系列之外,根据用户输入调用指定函数的最佳方法是什么?if and strcmp?

例如:

p 2 2 -> call func_p(2, 2)
a 8   -> call func_a(7)
m     -> call func_m(void)

我知道制作一个由具有相同原型的函数指针组成的查找表是简单而优雅的,但是不同的原型又如何呢?我想过使用...在原型中,但我不知道这是否是一个好的解决方案。


定义所有函数,以便它们采用单个数组参数。

巴尔马尔的评论

将所有函数统一到同一个原型正是在这种情况下通常所做的事情,尽管我会使用带有两个参数的原型:指向具有实际参数及其大小的数组的指针。这样,并非每个函数都必须自行拆分/解析其参数。

我真的很喜欢这样的东西,所以我做了一个简短的演示。我在我的手机上做了这个,所以它有点粗糙,如果在野外使用,需要一些改进(例如内存管理和错误检测)。这里是:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

// a node in the abstract syntax tree. Either a
// value or a call
struct Ast {
  bool isCall;
  union {
    int value;
    struct {
      char const * operator;
      size_t countOperands;
      struct Ast * operands;
    } call;
  };
};

// unified function type. Could've also passed an
// int array, but then evaluate would've needed
// a memory allocation, so ...
typedef int (*Function)(struct Ast *, size_t);


// implementation of + function. Sums the values of
// parameters. (which are hopefully evaluated)
int sum(struct Ast * parameters, size_t num) {
  int result = 0;
  while (num > 0) {
    --num;
    result += parameters [num]. value;
  }
  return result;
}

// implementation of ? function, ignores any
// parameters and just asks for an integer.
int ask (struct Ast * parameters, size_t num) {
  int value;
  scanf("%d", & value);
  return value;
}

// poor man's lookup table
static Function const functions [] = {sum, ask};
static char const * const function_names [] = {"+", "?"};

// poor man's lookup from above static arrays
Function lookup (char const * name) {
  size_t it = sizeof (functions) / sizeof (functions [0]);
  while (it > 0) {
    --it;
    if (strcmp(name, function_names [it]) == 0) {
      return functions [it];
    }
  }
  exit(1);
}

// evaluate an Ast. Normally one wouldn't return
// an Ast node but rather some value_t (assuming
// dynamic typing)
// this function is also destructive on call Ast nodes,
// in order to get around any memory management.
// so be careful!
struct Ast * evaluate (struct Ast * node) {
  if (! node->isCall) {
    // anything that's not a call is a value, thus
    // self evaluating, return it unchanged!
    return node;
  }
  // so it's a call. Get the associated function from
  // the lookup table!
  Function f = lookup(node->call.operator);
  // unconditionally evaluate all operands of the call.
  // thus no macros or conditionals, sorry!
  size_t o;
  for (o = 0; o < node->call.countOperands; ++o) {
    // destructive!
    node->call.operands[o] = *evaluate(&(node->call.operands[o]));
  }
  // use the call node to store the result value.
  // this will blow up if any call node uses any
  // allocated memory!
  node->isCall = false;
  // call the function with the evaluated operands and
  // store the result
  node->value = f(node->call.operands, node->call.countOperands);
  return node;
}

int main () {
  // I didn't want to write a parser, so here's a
  // static Ast of (+ 21 10 (?))
  struct Ast nodes [] = {
    {.isCall=false, .value=21},
    {.isCall=false, .value=10},
    {.isCall=true, .call = {
        .operator="?", .countOperands=0}},
    {.isCall=true, .call = {
        .operator="+", .countOperands=3,
        .operands=nodes}}};
  struct Ast * result = evaluate(&(nodes [3]));
  printf("(+ 21 10 (?)) => %d\n", result->value);
  return 0;
}

在 ideone 上编写并“测试”。 http://ideone.com/yawecz

另一种方法是使用void *标记有一些函数类型信息。但是将实际参数传递给这样编码的函数相当困难,而且它也不能很好地扩展。

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

具有不同函数原型的函数查找表 的相关文章

  • Tensorflow 中的自定义资源

    由于某些原因 我需要为 Tensorflow 实现自定义资源 我试图从查找表实现中获得灵感 如果我理解得好的话 我需要实现3个TF操作 创建我的资源 资源的初始化 例如 在查找表的情况下填充哈希表 执行查找 查找 查询步骤 为了促进实施 我
  • 赋值运算符和复制构造函数有什么区别?

    我不明白C 中赋值构造函数和复制构造函数之间的区别 是这样的 class A public A cout lt lt A A lt lt endl The copy constructor A a b The assignment cons
  • Qt - 无法让 lambda 工作[重复]

    这个问题在这里已经有答案了 我有以下功能 我想在其中修剪我的std set
  • 如何进行带有偏差的浮点舍入(始终向上或向下舍入)?

    我想以偏置舍入浮动 要么总是向下 要么总是向上 代码中有一个特定的点 我需要这个 程序的其余部分应该像往常一样四舍五入到最接近的值 例如 我想四舍五入到最接近的 1 10 倍数 最接近 7 10 的浮点数约为 0 69999998807 但
  • 获取两个字符串之间的公共部分c# [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要的是获取两个单词之间的共同部分并获取差异 例子 场景1 word1 感言 word2 Test 将返回 公共部分Test 不同之
  • 当我单击 C# 中的“取消”按钮时重定向到新页面(Web 部分)

    Cancel button tc new TableCell btnCancel new Button btnCancel Text Cancel btnCancel Click new EventHandler btnCanel Clic
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • try-catch 中未处理的异常

    try list from XElement e in d Descendants wix File where e Attribute Name Value Contains temp Name e Parent Parent Attri
  • 在 Xcode4 中使用 Boost

    有人设置 C Xcode4 项目来使用 Boost 吗 对于一个简单的 C 控制台应用程序 我需要在 Xcode 中设置哪些设置 Thanks 用这个来管理它 和这个
  • 获取从属性构造函数内部应用到哪个属性的成员?

    我有一个自定义属性 在自定义属性的构造函数内 我想将属性的属性值设置为属性所应用到的属性的类型 是否有某种方式可以访问该属性所应用到的成员从我的属性类内部 可以从 NET 4 5 using CallerMemberName Somethi
  • C++派生模板类继承自模板基类,无法调用基类构造函数[重复]

    这个问题在这里已经有答案了 我试图从基类 模板 继承 派生类也是模板 它们具有相同的类型 T 我收到编译错误 非法成员初始化 Base 不是基类或成员 为什么 如何调用基类构造函数 include
  • 两组点之间的最佳匹配

    I ve got two lists of points let s call them L1 P1 x1 y1 Pn xn yn and L2 P 1 x 1 y 1 P n x n y n 我的任务是找到它们点之间的最佳匹配 以最小化它
  • 组合框项目为空但数据源已满

    将列表绑定到组合框后 其 dataSource Count 为 5 但组合框项目计数为 0 怎么会这样 我习惯了 Web 编程 而且这是在 Windows 窗体中进行的 所以不行combo DataBind 方法存在 这里的问题是 我试图以
  • 用于从字符串安全转换的辅助函数

    回到 VB6 我编写了一些函数 让我在编码时无需关心字符串的 null 和 数字的 null 和 0 等之间的区别 编码时 没有什么比添加特殊情况更能降低我的工作效率了用于处理可能导致一些不相关错误的数据的代码 9999 10000 如果我
  • “MyClass”的类型初始值设定项引发异常

    以下是我的Windows服务代码 当我调试代码时 我收到错误 异常 CSMessageUtility CSDetails 的类型初始值设定项引发异常 using System using System Collections Generic
  • 过期时自动重新填充缓存

    我当前缓存方法调用的结果 缓存代码遵循标准模式 如果存在 则使用缓存中的项目 否则计算结果 在返回之前将其缓存以供将来调用 我想保护客户端代码免受缓存未命中的影响 例如 当项目过期时 我正在考虑生成一个线程来等待缓存对象的生命周期 然后运行
  • 32位PPC rlwinm指令

    我在理解上有点困难rlwinmPPC 汇编指令 旋转左字立即然后与掩码 我正在尝试反转函数的这一部分 rlwinm r3 r3 0 28 28 我已经知道什么了r3 is r3在本例中是一个 4 字节整数 但我不确定这条指令到底是什么rlw
  • 以编程方式使用自定义元素创建网格

    我正在尝试以编程方式创建一个网格 并将自定义控件作为子项附加到网格中 作为 2x2 矩阵中的第 0 行第 0 列 为了让事情变得更棘手 我使用了 MVVM 设计模式 下面是一些代码可以帮助大家理解这个想法 应用程序 xaml cs base
  • 热重载时调用方法

    我正在使用 Visual Studio 2022 和 C 制作游戏 我想知道当您热重新加载应用程序 当它正在运行时 时是否可以触发一些代码 我基本上有 2 个名为 UnloadLevel 和 LoadLevel 的方法 我想在热重载时执行它
  • 从类模板参数为 asm 生成唯一的字符串文字

    我有一个非常特殊的情况 我需要为类模板中声明的变量生成唯一的汇编程序名称 我需要该名称对于类模板的每个实例都是唯一的 并且我需要将其传递给asm关键字 see here https gcc gnu org onlinedocs gcc 12

随机推荐

  • R - 导入带有日期列的 xlsx 文件

    当我尝试读取 Excel 文件时 它总是与日期 时间混淆 library openxlsx download file http ec europa eu economy finance db indicators surveys docu
  • Flask-SQLAlchemy:通过一个关系进行多个过滤器

    我有两个模型 标签和照片 它们具有多对多关系 如下所示 tag identifier db Table tag identifier db Column photo id db Integer db ForeignKey photo id
  • 将消息从内容脚本发送到另一个脚本

    我正在开发一个 Google Chrome 扩展 我的目的是将消息从 script1 js 发送到 script2 js 这是我在manifest json中写的内容 matches https www google fr css styl
  • 响应式设计和图像尺寸

    问 就图像加载时间和性能而言 哪种技术最有效 场景1 是否通过使用媒体查询来加载不同尺寸的图像 如下 Smartphone media screen and max width 320px img page 1 img background
  • Android 版 facebook connect 返回空白登录屏幕?

    我正在尝试使用旧的 facebook 连接身份验证来验证我的 android 客户端 以获得开始使用 facebook 的网络服务所需的必要会话 ID 和其他凭据 我遇到的问题是 当我的 Android 应用程序启动并尝试加载 facebo
  • 防止 UIWebView 内出现烦人的 HTML5 地理位置警报

    每当脚本请求地理位置时 使用HTML5的地理定位 API UIWebView请求使用 iOS 定位服务的权限 这非常烦人 特别是当您加载静态时HTML文件时 它会不断询问每个文件的权限 即使用户已经为应用程序本身授予了此权限 有办法预防吗
  • Datatable:日期/时间排序插件未排序

    我有一个基本的 Spring Boot 应用程序 嵌入式 Tomcat Thymeleaf 模板引擎 我想订购数据表的 1 个日期列 在我的 POJO 中 public String getTimeFormatted DateTimeFor
  • ContentResolver.query() 方法抛出“无效令牌限制”错误

    内部版本号为 RQ1A 201205 003 或更高版本的 Pixel 设备上会出现以下错误 我想知道错误的原因以及如何处理 这是错误还是规格更改 code ContentResolver resolver getContentResolv
  • Visual Studio C++ Link1104无法打开文件MSVCURTD.lib

    我已经在 Visual Studio 2017 社区中打开了一个用 Visual Studio 2012 Express 用 C 编写 制作的项目 当我尝试编译时出现以下错误 LINK1104 无法打开文件 MSVCURTD lib 如果我
  • 重播 GIF 动画/单击时重新加载 GIF

    我有一个很大的 GIF 动画 我让它显示一个加载图标 直到 GIF 加载完毕 加载后就会显示 GIF 效果很好 但我想添加一个 重播 按钮来触发 GIF 重播 重新加载 加载和GIF的代码 HTML div class loading im
  • Linq to Entities 删除

    是否有内置方法可以使用主键通过 Linq to Entities 进行删除 目前的解决方法是创建一个名为DeleteTable的存储过程 表是表名 然后在 C LINQ To Entities 中我只需执行 context DeleteTa
  • 如何在 Appveyor 构建之前运行 VCUpgrade?

    我们分发了一组 Visual Studio 2010 项目文件 用户应该根据自己的口味进行升级 我们的 appveyor yml file http github com weidai11 cryptopp blob master appv
  • R Shiny with Leaflet - 单击后更改标记的颜色

    我正在开发一个闪亮的应用程序 它显示带有标记的传单地图 标记是可点击的 我收集被点击标记的 ID 但我还想更改单击标记的颜色 当标记为蓝色时 它应更改为红色标记 反之亦然 到目前为止 我已经有了跟踪单击的标记的代码 并且可以将 ID 存储在
  • 什么会导致 %5B0%5D 添加到 url

    我试图找出为什么删除过滤器的链接在我的网站上不起作用 似乎是因为链接已更改为包含 5B0 5D 和其他各种字母和数字 并添加了 据我所知 这是序列化函数导致的 还有其他什么可能导致这种情况 或者它绝对是序列化函数吗 它被称为百分比编码 ht
  • 在 netbeans 中运行 Web 应用程序

    我正在使用 netbeans 和 apache tomcat 来运行 Web 应用程序 我不断收到此错误 In place deployment at C WorkingDirectory Projects GreenWheelsProje
  • 从 iTunes Connect 中删除新的应用程序版本

    我在 iTunes Connect 中使用错误的版本号创建了应用程序的新版本 我想删除处于 准备上传 状态的新版本 我该怎么做呢 关于此还有其他问题 但他们没有提供任何答案 适用于已上传二进制文件的版本 或者已过时 我就此向 Apple 提
  • 在 C++ 中提供指针恒定视图的更好方法

    我有一个类必须返回一个constant一些指向软件上层的指针的视图 在内部 指针必须是非常量 因为类需要在内部操作对象 我没有看到任何选项可以在不复制所有指针的情况下向更高级别的客户端提供指针的常量视图 这看起来很浪费 如果我管理数百万个对
  • 如何连接到 TT X_TRADER API 以使用 python 创建自动交易系统?

    我已经在内部开发论坛中多次看到这个问题 因此想提供一个快速示例 说明如何立即在 python 中实现这一点 首先 请注意 我们所做的只是连接到相关的 X TRADER com 对象 因此以下所有内容仍然适用 https www tradin
  • 如何将复选框与文本对齐到屏幕右侧?

    我里面有一个复选框TableRow 我想将复选框和文本对齐到屏幕的右侧 但是当我使用android gravity right 它仅将文本与屏幕右侧对齐 但不与正方形 复选框本身 对齐 它们似乎是单独对齐的 复选框位于屏幕的左侧 文本位于屏
  • 具有不同函数原型的函数查找表

    除了一系列之外 根据用户输入调用指定函数的最佳方法是什么 if and strcmp 例如 p 2 2 gt call func p 2 2 a 8 gt call func a 7 m gt call func m void 我知道制作一