[关闭]
@rg070836rg 2015-08-16T15:06:19.000000Z 字数 2068 阅读 1589

表达式求值

data_structure

一、 程序思路

1. 问题分析:

表达式是由运算对象、运算符和圆括号组成的式子。在这个程序中只讨论简单的算术运算。为了实现运算符的优先运算,用两个栈分别存储表达式:
OPND:运算对象栈,用来存储运算对象和运算结果;
OPTR:运算符栈,用来存储运算符;

2. 算法思想:

规定@为表达式的定界符,输入的表达式以@为结束标志

  • (1) 将栈OPND初始化为空,OPTR初始化为表达式的定界符@;

  • (2) 依次读入表达式的每个字符,进行如下操作,直到读到@且OPTR栈的栈顶元素为@:

    1. 若当前字符是操作数,则进OPND栈,继续读下一个字符;
    2. 若当前字符是运算符,且比OPND的栈顶运算符的优先级高,则进OPTR栈,继续读入下一个字符;
    3. 若当前字符是运算符,且比OPND的栈顶运算符的优先级低,则从OPTR栈弹出一个运算符,从OPND栈弹出两个操作数,进行运算,并让运算结果进栈OPND,继续处理当前字符;
    4. 若当前字符是运算符,且与OPND的栈顶运算符的优先级相等,则从弹出OPTR栈的栈顶运算符,继续读入下一个字符;
  • (3) 输出OPND的栈顶元素(即表达式的运算结果)。

二、代码实现:

1、用数组prcd表示各运算符之间的优先级关系

  1. const char prcd[7][7] = {'>', '>', '<', '<', '<', '>', '>',
  2. '>', '>', '<', '<', '<', '>', '>',
  3. '>', '>', '>', '>', '<', '>', '>',
  4. '>', '>', '>', '>', '<', '>', '>',
  5. '<', '<', '<', '<', '<', '=', ' ',
  6. '>', '>', '>', '>', ' ', '>', '>',
  7. '<', '<', '<', '<', '<', ' ', '='};

2、函数PtrToInt

将运算符与它在数组中的下标相关联,使得利用数组prcd来比较栈顶运算符与当前运算符之间的优先级关系。

  1. int PtrToInt(char c)
  2. {
  3. if('+' == c) return 0;
  4. if('-' == c) return 1;
  5. if('*' == c) return 2;
  6. if('/' == c) return 3;
  7. if('(' == c) return 4;
  8. if(')' == c) return 5;
  9. if('@' == c) return 6;
  10. else
  11. {
  12. cerr<<"输入的运算符不合法!"<<endl;
  13. exit(1);
  14. }
  15. }

3、函数Operater

用来计算left oper right这个式子的值,并返回。

  1. float Operater(float left, char oper, float right)
  2. {
  3. switch(oper)
  4. {
  5. case '+':
  6. {
  7. return left + right;
  8. break;
  9. }
  10. case '-':
  11. {
  12. return left - right;
  13. break;
  14. }
  15. case '*':
  16. {
  17. return left * right;
  18. break;
  19. }
  20. case '/':
  21. {
  22. if(0 == right)
  23. {
  24. cerr<<"除数不能为0!"<<endl;
  25. exit(1);
  26. }
  27. return left / right;
  28. break;
  29. }
  30. default:
  31. {
  32. cerr<<"输入的运算符不合法!!"<<endl;
  33. exit(1);
  34. }
  35. }
  36. }

4、函数Calculate

用来计算表达式的值,用两个栈OPND和OPTR分别存放运算对象和运算符。依次读入表达式的字符,进行操作数和运算符的判断,并进入各自的栈。根据运算符的优先级,进行计算,最后得出结果,返回表达式的值。

  1. float Calculate ()
  2. {
  3. SeqStack<float, MaxSize> OPND; //运算对象栈
  4. SeqStack<char, MaxSize> OPTR; //运算符栈
  5. OPTR.Push('@'); //初始化运算符栈
  6. float left, right; //左操作数,右操作数
  7. char oper; //双目运算符
  8. cout<<"请输入要计算的表达式:"<<endl;
  9. char ch;
  10. ch = getchar();
  11. while(ch != '@' || OPTR.GetTop() != '@')
  12. {
  13. if(ch >= '0' && ch <= '9')
  14. {
  15. OPND.Push(ch - '0');
  16. ch = getchar();
  17. }
  18. else
  19. {
  20. switch(prcd[PtrToInt(OPTR.GetTop())][PtrToInt(ch)])
  21. {
  22. case '<':
  23. {
  24. OPTR.Push(ch);
  25. ch = getchar();
  26. break;
  27. }
  28. case '>':
  29. {
  30. oper = OPTR.Pop();
  31. right = OPND.Pop();
  32. left = OPND.Pop();
  33. OPND.Push(Operater(left, oper, right));
  34. break;
  35. }
  36. case '=':
  37. {
  38. oper = OPTR.Pop();
  39. ch = getchar();
  40. break;
  41. }
  42. }
  43. }
  44. }
  45. return OPND.GetTop();
  46. }

5、测试结果

  1. int main()
  2. {
  3. double result = Calcu();
  4. cout << result << endl;
  5. return 0;
  6. }

简单的案例:
此处输入图片的描述

此处输入图片的描述
错误的案例:
此处输入图片的描述

三、总结

基本的实现了算数操作,但有关功能还待后续版本。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注