2010-02-23 62 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