昨天晚上我写了下面的代码来执行一些算术运算(求和,乘法,减法,除法)。
data operation(int oper, data e1, data e2){
data res;
basic b;
//pointer to a funcion that takes two int input and return an int
int (*funIntPtr)(int,int);
float (*funFloatPtr)(float,float);
funIntPtr = NULL;
funFloatPtr= NULL;
//I look for the function to be called
switch (oper) {
case MINUS:
//*functionPtr = &subInt;
switch (e1.b.type) {
case basic_int_value:funIntPtr = subInt;break;
case basic_float_value:funFloatPtr = subFloat;break;
case basic_boolean_value:
yyerror("boolean arithmetic operation are NOT_ALLOWED");
exit(NOT_ALLOWED);
break;
}
break;
case PLUS :
switch (e1.b.type) {
case basic_int_value:funIntPtr = addInt;break;
case basic_float_value:funFloatPtr = addFloat;break;
case basic_boolean_value:
yyerror("boolean arithmetic operation are NOT_ALLOWED");
exit(NOT_ALLOWED);
break;
}
break;
case MULTIPLY:
switch (e1.b.type) {
case basic_int_value:funIntPtr = mulInt;break;
case basic_float_value:funFloatPtr = mulFloat;break;
case basic_boolean_value:
yyerror("boolean arithmetic operation are NOT_ALLOWED");
exit(NOT_ALLOWED);
break;
}
break;
case DIVIDE :
switch (e1.b.type) {
case basic_int_value:funIntPtr = divInt;break;
case basic_float_value:funFloatPtr = divFloat;break;
case basic_boolean_value:
yyerror("boolean arithmetic operation are NOT_ALLOWED");
exit(NOT_ALLOWED);
break;
}
break;
default:
yyerror("what now?");
exit(BUGGY_THE_CLOWN);
break;
}
//look for values to be used
if( funIntPtr == NULL && funFloatPtr == NULL){
yyerror("no function found for the specified operation..");
exit(BUGGY_THE_CLOWN);
}
res.type = basic_dataType;
res.b.type = e1.b.type;//inherithed
switch (e1.b.type) {
case basic_int_value:
{
res.b.i = funIntPtr(e1.b.i, e2.b.i);
}
break;
case basic_float_value:
{
res.b.f = funFloatPtr(e1.b.f, e2.b.f);
}
break;
case basic_boolean_value:
default:
yyerror("no data found for the specified operation..");
exit(BUGGY_THE_CLOWN);
}
return res;
}
在第一部分中,我找到了要使用的函数,在第二部分中,我收集了要使用的输入数据。它工作正常,它有助于达到目的。
typedef struct data{
dataType type;
union{
complex c;
basic b;
};
}data;
data是一个包含基本类型值或复杂值的结构。复杂值是数组类型和结构。关于哪一方,我暂时不在乎。
typedef struct basic{
basicType type;
union{
int i;
float f;
bool b;
};
}basic;
基本值atm只包含整数,浮点数和布尔值。
但我想知道我是否可以让它更紧凑和高效。 例如,我已声明了两个函数指针,但我只使用其中一个。有没有办法概括函数指针?
我知道我必须声明输入类型和返回类型,但在这种情况下,推迟这样的函数特化以便只有一个指针会很棒。 是否有可能或应该改变我解决问题的方式?
任何建设性的建议都被广泛接受:)
答案 0 :(得分:0)
在您的示例中,我没有看到使用的浮点函数:
case basic_float_value:
{
res.b.i = funIntPtr(e1.b.i, e2.b.i);
}
我希望有类似的东西:
case basic_float_value:
{
res.b.f = funFloatPtr(e1.b.f, e2.b.f);
}
这就是你不能使用单个函数指针的原因:float(double)和integer参数传递给函数的方式和返回结果的方式有很大的不同。当然你可以做重型转换,只是为了保存一个函数指针,但这会混淆代码所以我建议反对。
答案 1 :(得分:0)
您可以使用以下结构:
/* Operations enum */
enum operation {
ADD, SUB, DIV, MUL, OP_COUNT
};
/* Operation arity */
static const int arity[OP_COUNT] = {
[ADD] = 2, [SUB] = 2, [DIV] = 2, [MUL] = 2
};
/* Operation function pointer */
typedef double (*Operator)(double* arguments);
/* Map operation to operator */
Operator operators[OP_COUNT] = {
[ADD] = add, [SUB] = sub, [DIV] = div, [MUL] = mul
};
double add(double *arguments) { return arguments[0] + arguments[1]; }
/* and so on for other operators */
此外,您可能希望合并arity
和operators
地图。
还有一件事是声明参数的静态数组可能需要知道arity
值中的最大值。这种结构可以让你实现任意运算符而无需重写代码。
此外,您可以使用任何您想要的通用值结构,而不是double
。