C 转移表/转换表的深入分析

个人实现例子:


代码如下:

#include <stdio.h>
#include <string.h>
#define M 4
int add(int a, int b);
int sub(int a, int b);
int mul(int a, int b);
int div(int a, int b);
int (*oper_func[])(int, int) = {
 add, sub, mul, div
};
char oper_sequence[M][10] = {
 "add", "sub", "mul", "div"
};
int main()
{
 char oper[10];
 int seq;
 int a,b;
 int result;
 int i;
 printf("Operator:");
 scanf("%s",oper);
 printf("a:");
 scanf("%d",&a);
 printf("b:");
 scanf("%d",&b);
 for(i=0; i<M; i++)
 {
  if(strncmp(oper_sequence[i], oper, 3) == 0)
   seq = i;
 }
 result = oper_func[seq](a, b);
 printf("result is %d/n", result);
 return 0;
}
int add(int a, int b)
{
 return a+b;
}
int sub(int a, int b)
{
 return a-b;
}
int mul(int a, int b)
{
 return a*b;
}
int div(int a, int b)
{
 return a/b;
}

<<C和指针>>原文:
转换表(jump table)
转移表最好用个例子来解释。下面的代码段取自一个程序,它用于实现一个袖珍式计算器。程序的其他部分已经读入两个数(op1和op2)和一个操作符(oper)。下面的代码对操作符进行测试,最后决定调用哪个函数。
switch(oper)
{
  case ADD:   result=add(op1,op2);break;
  case SUB:    result=sub(op1,op2);break;
  case MUL:    result=mul(op1,op2);break;
  case DIV:     result=div(op1,op2);break;
  ......
}
对于一个新奇的具有上百个操作符的计算器,这条switch语句将会非常之长。为什么要调用函数来执行这些操作呢?把具体操作和选择操作的代码分开是一种 良好的设计方案。更为复杂的操作将肯定以独立的函数来实现,因为它们的长度可能很长。但即使是简单的操作也可能具有副作用,例如保存一个常量值用于以后的 操作。
为了使用switch语句,表示操作符的代码必须是整数。如果它们是从零开始连续的整数,我们可以使用转换表来实现相同的任务。转换表就是一个函数指针数组。
创建一个转换表需要两个步骤。首先,声明并初始化一个函数指针数组。唯一需要留心之处就是确保这些函数的原型出现在这个数组的声明之前。
double add(double,double);
double sub(double,double);
double mul(double,double);
double div(double,double);
double (*oper_func[])(double,double)={add,sub,mul,div,...};
初始化列表中各个函数名的正确顺序取决于程序中用于表示每个操作符的整型代码。这个例子假定ADD是0,SUB是1,MUL是2,接下去以此类推。
第二个步骤是用下面这条语句替换前面整条switch语句!
result=oper_func[oper](op1,op2);
oper从数组中选择正确的函数指针,而函数调用操作符将执行这个函数。

(0)

相关推荐

  • C 转移表/转换表的深入分析

    个人实现例子: 复制代码 代码如下: #include <stdio.h>#include <string.h>#define M 4int add(int a, int b);int sub(int a, int b);int mul(int a, int b);int div(int a, int b);int (*oper_func[])(int, int) = { add, sub, mul, div};char oper_sequence[M][10] = { "

  • C#数值转换-隐式数值转换表参考

    什么是隐式转换 Implicit Conversion 隐式转换就是直接使用,比如可以把一个 byte 类型直接用在 int 上. 比如以下直接把 byte 的 b 赋给 int 的 n,之间是直接用的,没存在什么额外的关键字,全由系统自动完成类型转换. 复制代码 代码如下: byte b = 1; int n = b; 隐式数值转换表(摘自 MSDN) 从 到 sbyte short.int.long.float.double 或 decimal byte short.ushort.int.u

  • C#数值转换-显式数值转换表(参考)

    什么是显式转换Explicit Conversion就是在将一种类型转换成另外一种类型时,需要额外的代码来完成这种转换. 复制代码 代码如下: int n = 1; byte b = (byte)n; // 正确,显式转换 byte b2 = n;      // 错误 显式转换需要注意,它的结果不一定是我们想要的. 复制代码 代码如下: int n = 256; byte b = (byte)n; // 结果是 0 上面的结果是 0,因为超过 255 了,它就从 0 开始:如果 n 是 257

  • oracle表空间表分区详解及oracle表分区查询使用方法

    此文从以下几个方面来整理关于分区表的概念及操作:1.表空间及分区表的概念2.表分区的具体作用3.表分区的优缺点4.表分区的几种类型及操作方法5.对表分区的维护性操作.(1.) 表空间及分区表的概念表空间:是一个或多个数据文件的集合,所有的数据对象都存放在指定的表空间中,但主要存放的是表, 所以称作表空间. 分区表: 当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区.表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间

  • C#实现顺序表(线性表)完整实例

    本文实例讲述了C#实现顺序表(线性表)的方法.分享给大家供大家参考,具体如下: 基本思想是使用数组作为盛放元素的容器,数组一开始的大小要实现确定,并使用一个Pointer指向顺序表中最后的元素.顺序表中的元素是数组中元素的子集.顺序表在内存中是连续的,优势是查找,弱势是插入元素和删除元素. 为避免装箱拆箱,这里使用泛型,代替object.使用object的例子可以参照本站这篇文章:http://www.jb51.net/article/87603.htm,这个链接中的例子实现的是队列,并没 有使

  • 详解oracle的分表之表分区的具体使用和示例

    此文从以下几个方面来整理关于分区表的概念及操作: 1.表空间及分区表的概念 2.表分区的具体作用 3.表分区的优缺点 4.表分区的几种类型及操作方法 5.对表分区的维护性操作. (1.) 表空间及分区表的概念 表空间: 是一个或多个数据文件的集合,所有的数据对象都存放在指定的表空间中,但主要存放的是表, 所以称作表空间. 分区表: 当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区.表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上

  • MySQL如何快速修改表的表结构

    快速修改MySQL某张表的表结构--摘录自<MySQL管理之道> ALTER TABLE 表名 MODIFY 列名 数据类型; 这个命令可以修改表结构 此外,也可以如下方法修改表结构: 先创建一张表,如下: > create table t1 (id int, name varchar(5), rmb decimal(9,1)); 如果要修改name列为varchar(10)的,可以这样操作: alter table t1 modify name varchar(7); 也可以如下操作:

  • Postgresql 实现查询一个表/所有表的所有列名

    假设postgres有数据库testdb 在testdb下执行下列sql语句,得到所有表的信息 select * from information_schema.columns where table_schema='public' and table_name<>'pg_stat_statements'; 在testdb下执行下列sql语句,得到所有表的列名 select column_name from information_schema.columns where table_sche

  • Mysql如何同时交换两个表的表名详解

    Mysql同时交换两个表的表名 表重命名有两种方式,所以交换两表名也有两种方式: 1 . lock tables t1 write ,t2 write; alter table t1 rename to t3; alter table t2 rename to t1; alter table t3 rename to t2; unlock tables; 2 . rename table t1 to t3,t2 to t1,t2 to t3; MySQL命令rename:修改表名 rename命

  • MySQL派生表联表查询实战过程

    目录 前情提要: 查询过程: 总结: 前情提要: 公司运营的一个商城系统,忽然发现订单提现功能有问题,有大量的商户体现金额和订单金额不一致.于是产生了需求,需要把提现表和供应商表作为一个结果集,连接上订单表中的订单金额,通过计算订单表的金额和体现表商户提现的金额进行比对,查看商户是多提现了还是少提现了. 下面记录我的查询过程. 查询过程: 刚开始,第一步我以提现表为主表,查询出来相关结果.MySQL语句如下 SELECT count(ysw.supply_id) AS '提现次数',ysw.us

随机推荐