目录
前言
表驱动法是一种编程模式(scheme)---从表里面查找信息而不使用逻辑语句(if和 case)。
- 事实上,凡是能通过逻辑语句来选择的事物,都可以通过查表来选择。
- 对简单的情况而言,使用逻辑语句更为容易和直白。但随着逻辑链的越来越复杂,查表法也就愈发显得更具吸引力。
18.1 表驱动法使用总则
在适当的环境下,采用表驱动法,所生成的代码会比复杂的逻辑代码更简单、更容易修改,而且效率更高。假设你希望把字符划分成字母、标点符号和数字三类,那么你也许会用到下面这种复杂的逻辑链:
另一方面,如果用一个查询表(lookup table),就可以把每一个字符的类型保存在一个用字符编码访问的数组里。那么上述的复杂代码片段就可以替换为:
这段代码假设 charTypeTable 数组己经提前创建好了。这时你把程序中的信息存放在数据里而不是逻辑里——也就是说,放在表中而不是if检测中。
18.1.1 使用表驱动法的两个问题
在使用表驱动法的时候,必须要解决两个问题:
1、首先,你必须要回答怎样从表中查询条目的问题。你可以用一些数据来直接访问表。比如说,如果你希望把数据按月进行分类,那么创建一个月份表是非常直截了当的。你可以用一个下标从1到12的数组实现它。
另一些数据可能很难直接用于查表。例如,假设你希望按照社会安全号码做数据分类,那么除非你可以承受在表里面存放 999-99-9999 条记录,否则就不能用社会安全号码直接查表。你会被迫采用一种更为复杂的方法。下面是从表里面查询记录的方法列表:
- 直接访问(Direct access)
- 索引访问 (Indexed access)
- 阶梯访问(Stair-step access)
本章后面部分将就这其中的每一种访问方法展开详细讨论。
2、在使用表驱动法的时候,需要解决的第二个问题是,你应该在表里面存些什么。
- 有的时候,表查询出来的结果是数据。如果你遇到的是这种情况,那么就可以把这些数据保存到表里面。
- 在另外一些情况下,表查询出来的结果是动作(action)。在这种情况下,你可以保存一个描述该动作的代码,或者,在有些语言里,你可以保存对实现该动作的子程序的引用。
无论是哪一种情况,表都会变得更为复杂。
18.2 直接访问表
和所有的查询表一样,直接访问表代替了更为复杂的逻辑控制结构。之所以说它们是“直接访问”的,是因为你无须绕很多复杂的圈子就能够在表里面找到你想要的信息。如图 18-1 所示,就可以直接找出你想要的条目来。
18.2.1 示例:一个月中的天数
假设你需要计算每个月中的天数(为了说明起见,此处不考虑闰年)。笨做法就是写一个大的if语句:
如果把闰年也考虑进来,那么那条长长的 if语句将会变得更为复杂了。
计算每月的天数是一个很适合用直接访问表描述的例子,因为你可以用month 变量去表里面查询记录。一般来说,你可以用原本控制着很多 if语句的数据去直接访问表。
18.2.2 示例:保险利率
假设你在写一个计算医疗保险费率的程序,这些费率是随着年龄、性别、婚姻状况以及吸烟与否的不同情况而变化的。如果你不得不用逻辑控制结构来表示不同费密的话,那么可能会写出下面的代码。
这是简化的逻辑结构,它应该已经能让你对事情的复杂度有足够的了解了。它还没有显示已婚的女士、所有的男土或者18至65 岁之间的人士。你可以想象:如果要把整个费率表编写出来该有多复杂。
你也许会说,“是的,可为什么你要为每一个年龄都做一次判断呢?为什么不把这些费率放进用年龄作下标的数组里?”好问题,而一种显而易见的改进就是把在每一年龄的费率存在一个独立数组里。
然而,更好的做法是把这些费率存入所有因素索引的数组里,而不仅仅是按年龄索引。你可以在 Visual Basic 中这样声明数组:
在声明了这个数组以后,你还需要找一种把数据存进去的方法。你可以使用赋值语句、从磁盘文件中读入数据、计算出这些数据、或者执行任何合适的操作。一旦备好了这些数据,在需要计算费率时,你就可以直接获取结果了。前面那段复杂的逻辑就可以用类似于下面这样简单的语句取而代之:
18.2.3 例子:灵活的消息格式
可以考虑去书中看一下详细的例子以及讲解,此处略。
18.3 索引访问表
略
18.4 阶梯访问表
略
18.5 表查询的其他示例
略