先需要了解函数指针数组的使用,依旧通过最简单最容易理解的例子来讲解。
有了上面的概念,让我们通过另一个实例看看驱动表的使用,下面这个小程序几乎每个程序员都应该写过,一个没有考虑精度的加减乘除运算程序,如下:
程序看上去很清晰,但如果要扩展一下功能,就发现要增加更多的case语句,记得ansi c标准中case的最大个数是256个,暂且不论这个值到底是多少,从代码本身来看,增加过多的case使得圈复杂度不断上升,程序维护困难加大。
实现相当简单,如果增加其他操作等功能,仅需要扩展pf数组,程序圈复杂度不会随功能增多而增加,从而也降低了维护成本。
首先看下面这个函数指针数组的使用实例。
1. #include <stdio.h>
2. #include <stdlib.h>
3.
4.
5. int Sum(int a, int b)
6. {
7. return a + b;
8. }
9.
10. int Sub(int a, int b)
11. {
12. return a - b;
13. }
14.
15. typedef int (*pfFun)(int, int);
16.
17. int TestFun(int a, int b, pfFun pf)
18. {
19. int i = 0;
20. i = pf(a, b);
21. return i;
22. }
23.
24. int main(int argc, char *argv[])
25. {
26. int iTmp = 0;
27.
28. pfFun pf[] = {Sum, Sub}; /*定义并一个函数指针数组,包含2个元素,并将其初始化为Sum和Sub函数地址*/
29.
30. iTmp = TestFun(20, 10, pf[0]);
31. printf("Tmp is: %d\n", iTmp);
32.
33. iTmp = TestFun(20, 10, pf[1]);
34. printf("Tmp is: %d\n", iTmp);
35.
36. system("PAUSE");
37.
38. return 0;
39. }
有了上面的概念,让我们通过另一个实例看看驱动表的使用,下面这个小程序几乎每个程序员都应该写过,一个没有考虑精度的加减乘除运算程序,如下:
1. #include <stdio.h>
2. #include <stdlib.h>
3.
4. /*加法*/
5. int Sum(int a, int b)
6. {
7. return a + b;
8. }
9.
10. /*减法*/
11. int Sub(int a, int b)
12. {
13. return a - b;
14. }
15.
16. /*乘法*/
17. int Multi(int a, int b)
18. {
19. return a * b;
20. }
21.
22. /*除法*/
23. int Division(int a, int b)
24. {
25. return (b == 0)? 0:(a / b);
26. }
27.
28. /*操作码*/
29. typedef enum _ENOPCODE
30. {
31. OPCODE_ADD = 0, /*加*/
32. OPCODE_SUB, /*减*/
33. OPCODE_MULTI, /*乘*/
34. OPCODE_DIVISION, /*除*/
35. OPCODE_BUTT
36. }enOpCode;
37.
38. /*通过Switch-case语句计算*/
39. int GetOpResultBySwitch(int a, int b, enOpCode enOp)
40. {
41. int iTmp = 0;
42.
43. switch(enOp)
44. {
45. case OPCODE_ADD:
46. iTmp = Sum(a, b);
47. break;
48.
49. case OPCODE_SUB:
50. iTmp = Sub(a, b);
51. break;
52.
53. case OPCODE_MULTI:
54. iTmp = Multi(a, b);
55. break;
56.
57. case OPCODE_DIVISION:
58. iTmp = Division(a, b);
59. break;
60. default:
61. iTmp = -1;
62. }
63.
64. return iTmp;
65. }
66.
67. int main(int argc, char *argv[])
68. {
69. int iTmp = 0;
70. int a = 10;
71. int b = 30;
72.
73. iTmp = GetOpResultBySwitch(a, b, OPCODE_ADD);
74.
75. printf("Tmp is: %d\n", iTmp);
76.
77. system("PAUSE");
78. return 0;
79. }
程序看上去很清晰,但如果要扩展一下功能,就发现要增加更多的case语句,记得ansi c标准中case的最大个数是256个,暂且不论这个值到底是多少,从代码本身来看,增加过多的case使得圈复杂度不断上升,程序维护困难加大。
这时就可以考虑使用驱动表的方法,同样看一下实现,请关注GetOpResultByTable函数。
1. #include <stdio.h>
2. #include <stdlib.h>
3.
4. /*加法*/
5. int Sum(int a, int b)
6. {
7. return a + b;
8. }
9.
10. /*减法*/
11. int Sub(int a, int b)
12. {
13. return a - b;
14. }
15.
16. /*乘法*/
17. int Multi(int a, int b)
18. {
19. return a * b;
20. }
21.
22. /*除法*/
23. int Division(int a, int b)
24. {
25. return (b == 0)? 0:(a / b);
26. }
27.
28. /*定义函数指针*/
29. typedef int (*pfFun)(int, int);
30.
31. /*操作码*/
32. typedef enum _ENOPCODE
33. {
34. OPCODE_ADD = 0, /*加*/
35. OPCODE_SUB, /*减*/
36. OPCODE_MULTI, /*乘*/
37. OPCODE_DIVISION, /*除*/
38. OPCODE_BUTT
39. }enOpCode;
40.
41. /*使用驱动表计算*/
42. int GetOpResultByTable(int a, int b, enOpCode enOp)
43. {
44. if (OPCODE_BUTT == enOp)
45. {
46. return -1;
47. }
48. pfFun pf[OPCODE_BUTT] = {Sum, Sub, Multi, Division};
49. return pf[enOp](a, b);
50.
51. }
52.
53. int main(int argc, char *argv[])
54. {
55. int iTmp = 0;
56. int a = 10;
57. int b = 30;
58.
59. iTmp = GetOpResultByTable(a, b, OPCODE_ADD);
60. printf("Tmp is: %d\n", iTmp);
61.
62. system("PAUSE");
63. return 0;
64. }
实现相当简单,如果增加其他操作等功能,仅需要扩展pf数组,程序圈复杂度不会随功能增多而增加,从而也降低了维护成本。