- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章如何用c++表驱动替换if/else和switch/case语句由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
目的:使用表驱动法,替换复杂的if/else和switch/case语句.
以switch为例,常用示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
Funcition()
{
switch
(key)
{
case
key1:
statements 1;
break
;
case
key2:
statements 2;
break
;
...
case
keyn:
statements n;
break
;
default
:
break
;
}
}
|
上述switch代码段,实际集成了3种类型逻辑:
1. 实现关键字的处理代码; 2. 将关键字与处理代码关联; 3. 以关键字选择分支,执行处理代码; 。
我们将在一个switch代码中维护3种变化。将1的处理代码段,模块化为函数后,变化点减少为2个.
在分支增加到几十个时,代码维护性变得很差;而且switch对非整数类型无能为力.
做法:
1. 将变化点2,做成一个[关键字:处理函数]映射结构(推荐map容器),在独立函数中赋值。 2. 将变化点3,做成一个查找关键字,执行对应函数的简单函数 。
好处:
1. 独立出“选择分支”变化点,变为固定的处理流程。 2. 独立出“关键字和处理函数的关联”,易于维护.
限制条件:
1. 处理函数类型一样(这在C++中不成问题); 2. 处理函数简单,但每个函数有差异(如果处理较为复杂,请使用创建型设计模式) 。
扩展:
1. 对于处理函数由符合条件分支情况,变化点2使用list结构,按优先级关联处理函数,使用 “职责链”形式的表驱动法.
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
// 3个文件,Client.cpp, TableDrave.h, TableDrive.cpp
// vvvvv Client.cpp begin
// ------------------------------------------------------------
// Name : Client.cpp
// Description : 调用接口
// History :
// ------------------------------------------------------------
#include "TableDrive.h"
// ------------------------------------------------------------
int
main()
{
TableDrive test;
test.HandleKeyword(KEYWORD_A);
test.HandleKeyword(KEYWORD_B);
test.HandleKeyword(KEYWORD_C);
test.HandleKeyword(KEYWORD_START);
test.HandleKeyword(KEYWORD_D);
return
0;
}
// ^^^^^ Client.cpp end
// vvvvv TableDrive.h begin
// ------------------------------------------------------------
// Name : TableDrive.h
// Description : 表驱动头文件
// History :
// ------------------------------------------------------------
#ifndef _TEST_DRIVE_H
#define _TEST_DRIVE_H
#include <map>
// ------------------------------------------------------------
// 测试用关键字
enum
KEYWORD
{
KEYWORD_START = -1,
KEYWORD_A = 0,
KEYWORD_B,
KEYWORD_C,
KEYWORD_D,
KEYWORD_END,
};
// ------------------------------------------------------------
// 可以使用 std:: 单个引用
using
namespace
std;
class
TableDrive
{
public
:
// ------------------------------------------------------------
// Description :
// 根据关键字,执行处理函数
// Parameters :
// string keyword,关键字
// Return Value :
// bool,true,函数执行成功,false,找不到键字对应的函数,或函数执行失败
// Errors :
// 无
// ------------------------------------------------------------
bool
HandleKeyword(
int
keyword);
// ------------------------------------------------------------
// Description :
// 关联关键字到处理函数
// Parameters :
// 无
// Return Value :
// bool,true,正常,false,异常
// Errors :
// 无
// ------------------------------------------------------------
bool
MapKeyToHandle();
TableDrive();
~TableDrive();
private
:
// vv 处理函数,true,执行成功,false,执行失败
bool
HandleKeyA();
bool
HandleKeyB();
bool
HandleKeyC();
// ^^
private
:
// :TRICKY: 成员函数指针定义
typedef
bool
(TableDrive:: *PHandle)(
void
);
map<
int
, PHandle> m_KeyToHandle;
// 关键字对应处理函数
};
#endif
// ^^^^^ TableDrive.h end
// vvvvv TableDrive.cpp begin
// ------------------------------------------------------------
// Name : TableDrive.cpp
// Description : 表驱动实现文件
// History :
// ------------------------------------------------------------
#include <stdio.h>
#include "TableDrive.h"
// ------------------------------------------------------------
// 根据关键字,执行处理函数
bool
TableDrive::HandleKeyword(
int
keyword)
{
typedef
map<
int
, PHandle>::const_iterator CI;
CI iter = m_KeyToHandle.find(keyword);
// 没有搜索到关键字
if
(m_KeyToHandle.end() == iter)
{
printf
(
"\n @@ search Keyword %d fail!\n"
, keyword);
return
false
;
}
// :TRICKY: 注意成员函数指针的引用格式
PHandle pFunction = iter->second;
return
(
this
->*pFunction)();
}
TableDrive::TableDrive()
{
printf
(
"\n vv TableDrive::TableDrive()\n"
);
MapKeyToHandle();
}
TableDrive::~TableDrive()
{
printf
(
"\n ^^ TableDrive::~TableDrive()\n"
);
}
// ------------------------------------------------------------
// 关联关键字到处理函数
bool
TableDrive::MapKeyToHandle()
{
m_KeyToHandle[KEYWORD_A] = &TableDrive::HandleKeyA;
m_KeyToHandle[KEYWORD_B] = &TableDrive::HandleKeyB;
m_KeyToHandle[KEYWORD_C] = &TableDrive::HandleKeyC;
return
true
;
}
// 处理函数 A
bool
TableDrive::HandleKeyA()
{
printf
(
"\n ** A, HandleKeyA()\n\n"
);
return
true
;
}
bool
TableDrive::HandleKeyB()
{
printf
(
"\n ** B, HandleKeyB()\n\n"
);
return
true
;
}
bool
TableDrive::HandleKeyC()
{
printf
(
"\n ** C, HandleKeyC()\n\n"
);
return
true
;
}
// ^^^^^ TableDrive.cpp end
|
关注点:
主要关注3个点,维护第2、3点 。
1. HandleKeyword(),根据关键字,执行处理函数。固定后基本不改变; 2. MapKeyToHandle(),关联关键字到处理函数; 3. Handle(),各个处理函数 。
成员函数指针使用注意 。
1. 声明格式,与C相比,函数指针前要包含类域; typedef bool (TableDrive:: *PHandle)(),
2. 声明位置,包含在类中,否则不能识别类域标志; 。
3. 赋值语法格式,与C相比,函数指针前要包含类域; PHandle pFunction = &TableDrive::HandleKeyA,
4. 调用语法格式,与C相比,需要加上this,并以强制解引用方式调用; (this->*pFunction)(),
1. 菜单调节。一个模块,有几十个菜单参数可以调节,每个菜单调节的步进、范围不同,但都是“触发消息、调节数值”流程.
2. 按键响应。多个按键,属于“按键,执行对应处理函数”流程.
3. 鼠标操控。不同状态下移动鼠标,属于“状态判断、响应鼠标处理函数”流程.
表驱动法 。
到此这篇关于使用c++表驱动法,替换复杂的if/else和switch/case语句的文章就介绍到这了,更多相关c++表驱动法内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.51cto.com/u_15288108/3624835 。
最后此篇关于如何用c++表驱动替换if/else和switch/case语句的文章就讲到这里了,如果你想了解更多关于如何用c++表驱动替换if/else和switch/case语句的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
是否有使用 switch 语句检查数字 0-9 的简单方法?我正在编写一个程序来检查某些字符和数字。就像检查“\0”、“F”或“f”一样,想知道是否还有一种方法可以以类似的方式检查 0-9。我知道我可
我有一些数据需要转换,为此我需要一个超过 50 个案例的切换条件,我需要 3 次相同的案例,但在第三次我需要 50 个案例和一些更多,我不想写两次相同的代码。也许有可能做这样的事情。 switch (
我遇到这种情况,我必须检查两个 GET 变量。在检查语句内的第一个 switch 语句后,必须在第一个 case 循环内的第二个 switch 语句中检查第二个变量。 我无法在这里发布确切的代码,但这
如何使用函数指针代替 switch 语句? 最佳答案 与 ars 发布的链接略有不同的方法:您可以将 switch 语句中的值用作函数指针数组中的数组索引。所以不要写 switch (i) {
我必须评估很多条件。就我而言,我必须做这样的事情: switch(id) { case 5: // switch some other cases here case
switch 按钮位于 switch 语句内,但仅在 switch 语句外部时才有效这是我的代码:
我试图在 switch 语句中有一个 case 跳转到不同的 switch 语句。 在实践中,我希望用户在文本框中键入“关闭页面”,并且在浏览器关闭页面之前,我希望询问用户是否确定。输入“yes”将关
(引用java)我试图确定哪个更好,编写更多代码并可能节省一些计算时间,或者编写更少代码但可能牺牲一些计算时间。这就是我好奇的地方这样做会更有效率吗: switch (availability) {
我正在尝试构建一个 Android 应用程序,该应用程序可以访问加速度计传感器,并在单击按钮时将加速度计值(由 <> 包围)输出到串行 USB。当我更新值并尝试在 onClick 命令中调用它时遇到问
如何使用 Dwoo 模板引擎实现 switch case 语法。 最佳答案 {if 3 == 5} never gonna happen {elseif 3 == 3} if you don'
我想知道一个大的 switch 语句和几个小的 switch 语句之间是否有性能差异。 包含数百个案例的大型 switch 语句。 switch(quest){ case 1:
用户在 2 个选择框中进行选择后,我尝试计算出报值(value)。 看起来 1 需要 2 个 switch 语句。这可能吗? (可能的值比下面的值多得多。为了清楚起见,我删除了它们) var wor
我在主 while 循环内有一个开关,它将运行我的游戏。我正在尝试打破我的开关,以便转到不同的案例。下面的例子更好地解释了这一点: int j = 0; While(1){ switch(j){ ca
我用 Java 创建了一个菜单,其中每个选项都有另一个菜单。我想知道是否可以从内部菜单退出回到主菜单。 编辑:添加了主菜单选项 System.out.println("Main Menu");
我有一个计算新分数的方法。下面的方法有效,但问题是代码本身看起来可以被显着清理。我只是不知道什么是最好的方法。我根据 filterString 和枚举 individualScoreState 分配
在 Lisp 中使用字符串切换语句。 (defun switch(value) (case value (("XY") (print "XY"))
我想做这样的事情: int i = 0; switch(difficulty) { case 1: i++; break; case 2: i--; break; defaul
在 Obj-c 中,我做了一个 switch 语句,我曾经使用 UIsplitviewcontroller 在我的 iPad 应用程序中四处移动现在我想快速地做同样的事情……我试了几个小时,现在我唯一
我想写一个结构如下的报告: \begin{document} \input[option=a]{class} \input[option=b]{class} \in
我正在认真阅读 ngSwitch 的 AngularJS API 引用。当我谈到那部分时的指令: place an expression on the on="..." attribute (or t
我是一名优秀的程序员,十分优秀!