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

C 具有不同函数原型的函数查找表,c,function-pointers,function-prototypes,C,Function Pointers,Function Prototypes,除了从if和strcmp系列调用指定函数外,根据用户输入调用指定函数的最佳方法是什么 例如: p 2 2 -> call func_p(2, 2) a 8 -> call func_a(7) m -> call func_m(void) 我知道制作一个由相同原型的函数指针组成的查找表很容易,也很优雅,但是不同的原型呢?我曾考虑在原型中使用…,但我不知道这是否是一个好的解决方案 定义所有函数,使其采用单个数组参数 巴尔马的评论 在本例中,将所有函数统一到同一个原型正

除了从
if
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;
}
#包括
#包括
#包括
#包括
//抽象语法树中的节点。要么是
//价值还是通话
结构Ast{
布尔伊斯卡尔;
联合{
int值;
结构{
字符常量*运算符;
操作数的大小;
结构Ast*操作数;
}呼叫;
};
};
//统一函数类型。也可以通过考试
//int数组,但需要进行求值
//内存分配,所以。。。
typedef int(*函数)(结构Ast*,大小t);
//+功能的实现。求和的值
//参数。(希望得到评估)
整数和(结构Ast*参数,大小\u t num){
int结果=0;
while(num>0){
--num;
结果+=参数[num]。值;
}
返回结果;
}
//实施?函数,忽略任何
//参数,只要求一个整数。
int ask(结构Ast*参数,大小\u t num){
int值;
scanf(“%d”,和值);
返回值;
}
//穷人查找表
静态函数const functions[]={sum,ask};
静态字符常量*常量函数_名称[]={“+”,“?”};
//穷人从上面的静态数组中查找
函数查找(字符常量*名称){
size_t it=sizeof(函数)/sizeof(函数[0]);
而(它>0){
--它;
if(strcmp(名称,函数名[it])==0){
返回函数[it];
}
}
出口(1);
}
//评估Ast。通常一个人不会回来
//一个Ast节点,而不是某个值(假设
//(动态键入)
//此函数在调用Ast节点时也是破坏性的,
//以便绕过任何内存管理。
//所以要小心!
结构Ast*评估(结构Ast*节点){
如果(!node->isCall){
//因此,任何不是调用的东西都是一个值
//自我评估,原封不动地返回!
返回节点;
}
//所以这是一个调用。从
//查找表!
函数f=查找(节点->调用.运算符);
//无条件计算调用的所有操作数。
//因此没有宏或条件,对不起!
大小;
对于(o=0;ocall.countoperans;++o){
//破坏性!
节点->调用操作数[o]=*求值(&(节点->调用操作数[o]);
}
//使用调用节点存储结果值。
//如果任何调用节点使用任何
//分配的内存!
node->isCall=false;
//使用计算的操作数和
//存储结果
节点->值=f(节点->调用.操作数,节点->调用.计数操作数);
返回节点;
}
int main(){
//我不想写解析器,所以这里有一个
//静态Ast值(+21 10(?)
结构Ast节点[]={
{.isCall=false,.value=21},
{.isCall=false,.value=10},
{.isCall=true,.call={
.operator=“?”,.countOperators=0},
{.isCall=true,.call={
.operator=“+”,.CountOperators=3,
.Operators=节点}};
struct Ast*result=evaluate(&(节点[3]);
printf((+21 10(?)=>%d\n),结果->值);
返回0;
}


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

定义所有函数,使它们只接受一个数组参数。这是我的第二个想法-让所有函数都接受
char*
,并根据用户输入的第一个单词调用指定函数。