【 C 】转移表(理论与实践)(实现一个简单的计算器)

举报
李锐博恩 发表于 2021/07/15 08:23:16 2021/07/15
【摘要】 首先借用《C 与指针》上对于转移表的解释,然后我们自己编程序操作下: 转移表最好用个例子来解释。下面的代码段取自一个程序,它用于实现一个袖珍式计算器。程序的其他部分已经读入两个数(op1和op2)和一个操作符(oper)。下面的代码对操作符进行测试,最后决定调用哪个函数。 switch(oper){  case ADD:   result=a...

首先借用《C 与指针》上对于转移表的解释,然后我们自己编程序操作下:

转移表最好用个例子来解释。下面的代码段取自一个程序,它用于实现一个袖珍式计算器。程序的其他部分已经读入两个数(op1和op2)和一个操作符(oper)。下面的代码对操作符进行测试,最后决定调用哪个函数。


  
  1. switch(oper)
  2. {
  3.   case ADD:   result=add(op1,op2);break;
  4.   case SUB:    result=sub(op1,op2);break;
  5.   case MUL:    result=mul(op1,op2);break;
  6.   case DIV:     result=div(op1,op2);break;
  7.   ......
  8. }


对于一个新奇的具有上百个操作符的计算器,这条switch语句将会非常之长。为什么要调用函数来执行这些操作呢?把具体操作和选择操作的代码分开是一种 良好的设计方案。更为复杂的操作将肯定以独立的函数来实现,因为它们的长度可能很长。但即使是简单的操作也可能具有副作用,例如保存一个常量值用于以后的 操作。
为了使用switch语句,表示操作符的代码必须是整数。如果它们是从零开始连续的整数,我们可以使用转换表来实现相同的任务。转换表就是一个函数指针数组。
创建一个转换表需要两个步骤。首先,声明并初始化一个函数指针数组。唯一需要留心之处就是确保这些函数的原型出现在这个数组的声明之前。
 


  
  1. double add(double,double);
  2. double sub(double,double);
  3. double mul(double,double);
  4. double div(double,double);
  5. double (*oper_func[])(double,double)={add,sub,mul,div,...};


初始化列表中各个函数名的正确顺序取决于程序中用于表示每个操作符的整型代码。这个例子假定ADD是0,SUB是1,MUL是2,接下去以此类推。
第二个步骤是用下面这条语句替换前面整条switch语句!
result=oper_func[oper](op1,op2);
oper从数组中选择正确的函数指针,而函数调用操作符将执行这个函数。


看完上面的例子可能还不是太清楚,转移表到底怎么用?

下面就用实际例子来试试。

参考实例:

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

转移表

这个例子我参考了好几个程序,为了功能的齐全,改来改去这个最后符合我的要求:


  
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. //函数原型
  5. int my_add(int a, int b);
  6. int my_sub(int a, int b);
  7. int my_mul(int a, int b);
  8. int my_div(int a, int b);
  9. //提示输入函数
  10. void print_menu()
  11. {
  12. printf("******Enter the operation:******\n");
  13. printf(" **** 1:add **** 2:sub ****\n");
  14. printf(" **** 3:mul **** 4:div ****\n");
  15. printf(" **** 0:exit **** 5:clr ****\n");
  16. printf("\n");
  17. }
  18. //定义函数指针数组
  19. int (*oper_func[])(int, int) =
  20. {
  21. NULL, my_add, my_sub, my_mul, my_div //由于0另有用途,所以第0个元素为空指针
  22. };
  23. //主函数开始
  24. int main()
  25. {
  26. int seq;
  27. int a,b;
  28. int result;
  29. Operation:
  30. print_menu();
  31. while(1)
  32. {
  33. printf("Operator:");
  34. scanf("%d", &seq);
  35. //输入对应的数字后,判断是否合法
  36. if( seq >= 0 && seq < 6 )
  37. {
  38. if( seq == 0 )
  39. exit(EXIT_SUCCESS);
  40. else if( seq == 5 )
  41. {
  42. system("cls");
  43. goto Operation;
  44. }
  45. else
  46. {
  47. printf("a: ");
  48. scanf("%d",&a);
  49. printf("b: ");
  50. scanf("%d",&b);
  51. result = oper_func[seq](a, b);
  52. printf("result is %d\n", result);
  53. }
  54. }
  55. else
  56. {
  57. printf("Enter error!!!");
  58. exit(EXIT_FAILURE);
  59. }
  60. }
  61. return 0;
  62. }
  63. //函数定义
  64. int my_add(int a, int b)
  65. {
  66. return a+b;
  67. }
  68. int my_sub(int a, int b)
  69. {
  70. return a-b;
  71. }
  72. int my_mul(int a, int b)
  73. {
  74. return a*b;
  75. }
  76. int my_div(int a, int b)
  77. {
  78. if( b == 0 )
  79. {
  80. printf( "The divisor cannot be 0!!! ");
  81. exit(EXIT_FAILURE);
  82. }
  83. return a/b;
  84. }

程序运行结果如下:

输入4,但被除数b为0的话:

输入5之后,回车之后清除操作:

输入12,之后提示输入错误!

输入0之后,回车退出:

 

 

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/82708015

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。