2010-02-23 17 views
3

我正在研究C语言中的小解析器和“方程求解器”,这个过程的一部分就是对算术运算进行算术运算。 每个标记包含void *指向数值数据的指针,以及枚举,它定义数据的类型。算术运算void *指向数值数据

这是函数的示例,它通过添加两个其他标记来创建新标记。为了做到这一点,我需要

  1. 检查类型
  2. 做手术
  3. 创建结果新的令牌

一个

Token* _CreateTokenByAddition(Token* arg1, Token* arg2){ 
    Token *tokenResult; 
    if ((arg1->_type == tk_IntData) && (arg2->_type == tk_IntData)){ 

     int* intResult = malloc(sizeof(int)); 
     *intResult = *(int*)arg1->_data + *(int*)arg2->_data; 

     tokenResult = CreateTokenFromValue(intResult, tk_IntData); 
    }else 
    if ((arg1->_type == tk_IntData) && (arg2->_type == tk_FloatData)){ 

     float* intResult = malloc(sizeof(float)); 
     *intResult = *(int*)arg1->_data + *(float*)arg2->_data; 
     tokenResult = CreateTokenFromValue(intResult, tk_FloatData); 
    }else 
    if ((arg1->_type == tk_FloatData) && (arg2->_type == tk_IntData)){ 

     float* intResult = malloc(sizeof(float)); 
     *intResult = *(float*)arg1->_data + *(int*)arg2->_data; 
     tokenResult = CreateTokenFromValue(intResult, tk_FloatData); 
    } 
    else 
    if ((arg1->_type == tk_FloatData) && (arg2->_type == tk_FloatData)){ 

     float* intResult = malloc(sizeof(float)); 
     *intResult = *(float*)arg1->_data + *(float*)arg2->_data; 
     tokenResult = CreateTokenFromValue(intResult, tk_FloatData); 
    } 
    return tokenResult; 
} 

我有 - ,*,/几乎相同的功能。我可能需要创造更多。

问题是: 如何创建一个支持所有简单操作的通用函数,如+ - * /? 我不想把这个函数放在宏中,然后通过替换数学操作数来复制它4次。 无论如何我可以简化数据类型检查和从void指针转换?

任何方式,我可以让这个代码,更好?

假设:我没有任何非数值数据类型(如字符串)

感谢

酷,非常感谢这些答复,我看你的函数指针的意思。 我将考虑它并使用这些方法之一。谢谢

回答

4

简短回答: c没有提供任何syntaxtical帮助。

好消息:您可以通过使用函数指针来支持c中的多态。 有很多问题解释如何做已经出现在堆栈溢出。在一分钟内,我会编辑一个或两个链接...

不喜欢我发现这个用法的答案,所以在这里。

对于每个操作,编写一组采用所有类型合法组合的函数。每个人只做一个组合,所以很容易。然后构造函数指针的表像这样

typedef Token* (*mathfuncptr)(void *, void *); 

Token* _Add_IntInt(void *, void *); 
Token* _Add_IntFloat(void *, void *); 
Token* _Add_FloatInt(void *, void *); 
/* ... */ 

mathfuncptr Add_table[AddTypeCount][AddTypeCount] = { 
    {_Add_IntInt, _Add_IntFloat}, 
    {_Add_FloatInt, _Add_FloatFloat} 
}; 
mathfuncptr Mul_table[MultTypeCount][MultTypeCount] = { /* ... */ 

现在你一般附加功能决定了两类它并通过索引到表中调用正确的函数。

+0

想要获得第一个答案优势吗? – rpetrich 2010-02-23 22:41:57

0

你可以用函数指针和switch语句轻松做到这一点。

3

你可以把数学运算中的函数指针,然后用使用这些函数指针的通用功能:

typedef int (*bin_op)(int, int); 
typedef float (*bin_fop)(float, float); 

Token* _CreateTokenByOp(Token* arg1, Token* arg2, bin_op op, bin_fop, fop) { 
    ... 
    *intResult = op(*(int*)arg1->_data, *(int*)arg2->_data); 
    ... 
} 

int add(int a, int b) { return a+b; } 
float addf(float a, float b) { return a+b; } 
... 

Token* _CreateTokenByAddition(Token* arg1, Token* arg2) { 
    return _CreateTokenByOp(arg1, arg2, &add, &addf); 
} 

话虽这么说,C是不一般在创建通用的功能和使用功能非常好指针可能会导致代码很模糊。使用支持面向对象和类似概念的C++语言可以让你的生活在这里变得更容易。

1
  • 你可以使用一个switch而不是多个if-else

  • 一个函数指针表,由与这些类型相对应的枚举进行索引。

如:

typedef enum type_info_ { INT = 0, FLOAT, ... , UNKNOWN } TI; 

    typdef void *(*generic_add_t)(void const*, void const*); 

    void *float_add(void const* l, void const* r) { 
     float *result = malloc(sizeof *result); 
     *result = *((float const *)l) + *((float const *)r); 
     return result; 
    } 




generic_add_t fp_table[] = { float_add, ... }; 

,并用它作为:

TI curr_type = UNKNOWN; 
    // ... 
    fp[ curr_type ]; 

如果你懒得推出的所有加法器,定义一个宏:

#define MAKE_ADDER(type) \ 
void *type##_add(void const* l, void const* r) { \ 
     type *result = malloc(sizeof *result); \ 
     *result = *((type const *)l) + *((type const *)r); \ 
     return result; \ 
    } 

并将其用作:

MAKE_ADDER(float) 
MAKE_ADDER(int) 

... 
+0

以不变的正确性比我好... – dmckee 2010-02-23 22:54:46