我有一个像这样的结构:
typedef enum any_type{
ANY_TYPE_CHAR,
ANY_TYPE_UCHAR,
ANY_TYPE_SHORT,
ANY_TYPE_USHORT,
ANY_TYPE_INT,
ANY_TYPE_UINT,
ANY_TYPE_LONG,
ANY_TYPE_ULONG,
ANY_TYPE_FLOAT,
ANY_TYPE_DOUBLE,
} any_type;
typedef struct any{
any_type type;
union{
char as_char;
unsigned char as_uchar;
short as_short;
unsigned short as_ushort;
int as_int;
unsigned int as_uint;
long as_long;
unsigned long as_ulong;
float as_float;
double as_double;
};
} any;
表示一个变量,它是指定的类型之一。这些结构有四种可能的操作,即加法,减法,乘法和除法。
我的问题是,是否有一种有效的方法对它们进行这些操作而不为每个案例做很多if语句?这会导致4 * 10 * 10 = 400
if
/ else if
语句单独进行这四项操作,这当然效率不高!
我的代码位于C
提前致谢。
答案 0 :(得分:3)
这将需要大量代码,因为combinatorial explosion是问题的一部分。
使用表驱动方法:定义两个表,一个用于在类型之间进行转换,另一个用于对它们执行操作。
对于转换,请创建一个函数指针类型
void mapwidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawPixmap(int x, int y, int w, int h, pixMap);
}
并在typedef any (*convert_any)(any val, any_type target);
上创建一个转换表:
convert_any conversion [] = { convert_char, convert_uchar, convert_short, ... };
对于每种类型都有这样的实现(你需要其中的十种):
any_type
对于操作,请创建另一个函数指针类型:
static any convert_char(any val, any_type target) {
any res = { .type = target };
switch (target) {
case ANY_TYPE_CHAR: res.as_char = val.as_char; break;
case ANY_TYPE_INT: res.as_int = (int)val.as_char; break;
...
}
return res;
}
您需要制作一个包含此类指针的3D数组 - 每个操作三次一个,左操作数的类型以及右操作数的类型。
实现看起来像这样:
typedef any (*operation_any)(any left, any right);
将有四十个这样的实现 - 每个结果类型和操作对一个。 3D表将包含400个条目,具体取决于操作需要生成的结果类型。调用将查找3D数组,查找static any add_int(any left, any right) {
any lhs = conversion[left.type](left, ANY_TYPE_INT);
any rhs = conversion[right.type](right, ANY_TYPE_INT);
any res {.type = ANY_TYPE_INT, .as_int = lhs.as_int + rhs.as_int};
return res;
}
static any add_double(any left, any right) {
any lhs = conversion[left.type](left, ANY_TYPE_DOUBLE);
any rhs = conversion[right.type](right, ANY_TYPE_DOUBLE);
any res {.type = ANY_TYPE_DOUBLE, .as_double = lhs.as_double + rhs.as_double };
return res;
}
指针,传递两个参数,并获得如下结果:
operation_any
答案 1 :(得分:3)
为了避免组合噩梦,请考虑有3组类型,无符号整数,有符号整数,浮点。
目标是确定操作要使用的3个组中的哪个组。然后获取每个类型和目标组的操作数值。根据该组进行数学计算。然后按组和最高排名类型保存。
对于10种类型中的每种类型,创建10个函数来获取数据并返回最宽的无符号整数。另外10个用于有符号整数,最后10个用于浮点。
对于10种类型的每种类型,执行相同操作以创建设置数据的功能。到目前为止60个小功能。
要访问正确的功能,请使用函数中的表查找。另外3个获取功能,还有3个用于设置。
最后是一个示例添加功能。它寻找最高排名类型,并根据3组之一获取/添加/设置。
现在为-,/,*
添加3个函数。总共约60 + 6 + 4个功能。
奖励:要添加像%
这样的新功能,只需要再写一个函数。
#include<assert.h>
typedef enum any_type{
// Insure these are in rank order
// ANY_TYPE_CHAR left out for now
ANY_TYPE_SCHAR,
ANY_TYPE_UCHAR,
ANY_TYPE_SHORT,
ANY_TYPE_USHORT,
ANY_TYPE_INT,
ANY_TYPE_UINT,
ANY_TYPE_LONG,
ANY_TYPE_ULONG,
ANY_TYPE_FLOAT,
ANY_TYPE_DOUBLE,
ANY_TYPE_N,
} any_type;
typedef struct any{
any_type type;
union{
signed char as_schar;
unsigned char as_uchar;
short as_short;
unsigned short as_ushort;
int as_int;
unsigned int as_uint;
long as_long;
unsigned long as_ulong;
float as_float;
double as_double;
};
} any;
/////////////////////////////////////
unsigned long any_uget_schar(const any *x) {
return (unsigned long) x->as_schar;
}
unsigned long any_uget_uchar(const any *x) {
return x->as_uchar;
}
/* 8 more */
unsigned long any_get_unsigned(const any *x) {
static unsigned long (*uget[ANY_TYPE_N])(const any *x) = {
any_uget_schar, any_uget_uchar, /* 8 others */ };
assert(x->type < ANY_TYPE_N);
return (uget[x->type])(x);
}
/////////////////////////////////////
signed long any_sget_schar(const any *x) {
return x->as_schar;
}
signed long any_sget_uchar(const any *x) {
return x->as_uchar;
}
/* 8 more */
signed long any_get_signed(const any *x) {
static signed long (*sget[ANY_TYPE_N])(const any *x) = {
any_sget_schar, any_sget_uchar, /* 8 others */ };
assert(x->type < ANY_TYPE_N);
return sget[x->type](x);
}
/////////////////////////////////////
double any_get_fp(const any *x); // similar for floating point
/////////////////////////////////////
void any_uset_schar(any *x, unsigned long y) {
x->as_schar = (signed char) y;
}
void any_uset_uchar(any *x, unsigned long y) {
x->as_uchar = (unsigned char) y;
}
/* 8 more */
void any_set_unsigned(any *x, unsigned long y) {
static void (*uset[ANY_TYPE_N])(any *x, unsigned long y) = {
any_uset_schar, any_uset_uchar, /* 8 others */ };
assert(x->type < ANY_TYPE_N);
uset[x->type](x,y);
}
/* 10 more for any_sset_... */
/* 10 more for any_fset_... */
///////////////////////////////////////////////
static const char classify[] = "susususuff";
any any_get_add(any a, any b) {
any sum;
sum.type = max(a.type, b.type);
assert(sum.type < ANY_TYPE_N);
switch (classify[sum.type]) {
case 's':
any_set_signed(&sum, any_get_signed(&a) + any_get_signed(&b));
break;
case 'u':
any_set_unsigned(&sum, any_get_unsigned(&a) + any_get_unsigned(&b));
break;
case 'f':
any_set_fp(&sum, any_get_signed(&a) + any_get_signed(&b));
break;
default:
assert(0);
}
return sum;
}
答案 2 :(得分:0)
你应该制作expr结构。这意味着AST的一个节点(Abstruct Syntax Tree)。它有操作。对于lhs,rhs,这意味着+, - ,*,/。 do_expr caluculate表达式。最后,dump_any打印该值。
#include <stdio.h>
#include <assert.h>
typedef enum any_type{
ANY_TYPE_CHAR,
ANY_TYPE_UCHAR,
ANY_TYPE_SHORT,
ANY_TYPE_USHORT,
ANY_TYPE_INT,
ANY_TYPE_UINT,
ANY_TYPE_LONG,
ANY_TYPE_ULONG,
ANY_TYPE_FLOAT,
ANY_TYPE_DOUBLE,
} any_type;
typedef struct any{
any_type type;
union{
char as_char;
unsigned char as_uchar;
short as_short;
unsigned short as_ushort;
int as_int;
unsigned int as_uint;
long as_long;
unsigned long as_ulong;
float as_float;
double as_double;
};
} any;
typedef enum op_type{
OP_PLUS,
OP_MINUS,
OP_MULT,
OP_DIVID,
} op_type;
typedef struct {
int op;
any lhs;
any rhs;
} expr;
int
do_expr(expr* e, any *r) {
switch (e->op) {
case OP_PLUS:
r->type = e->lhs.type;
r->as_int = e->lhs.as_int + e->rhs.as_int;
return 0;
break;
default:
fprintf(stderr, "unknown operation\n");
break;
}
return 1;
}
void
dump_any(any* a) {
switch (a->type) {
case ANY_TYPE_INT:
printf("%d\n", a->as_int);
break;
default:
assert(!"unknown type");
break;
}
}
int
main(int argc, char* argv[]) {
expr e1 = {
.op = OP_PLUS,
.lhs = { .type = ANY_TYPE_INT, as_int: 1, },
.rhs = { .type = ANY_TYPE_INT, as_int: 2, },
};
any ret;
if (do_expr(&e1, &ret) == 0) {
dump_any(&ret);
}
return 0;
}
答案 3 :(得分:0)
很抱歉,您必须进行大小写切换,因为编译器必须为不同类型生成不同的CPU指令。操作的类型由变量的选择定义。