WHCSRL 技术网

C++实现计算器,运用栈,输出后缀表达式,有负数、小数处理

  1. #include <iostream>
  2. #include <stack>
  3. #include <vector>
  4. #include <string>
  5. using namespace std;
  6. enum Member_type{
  7. NUM, SIGN
  8. };
  9. struct member {
  10. member(double n) {
  11. m_type = NUM;
  12. num = n;
  13. }
  14. member(char n) {
  15. m_type = SIGN;
  16. sign = n;
  17. }
  18. Member_type m_type;
  19. double num;
  20. char sign;
  21. };
  22. int main() {
  23. string source, num_tmp;
  24. stack<char> sign;
  25. vector<member*> suffix;
  26. cin >> source;
  27. //中缀转后缀
  28. for (int idx = 0; idx < source.size();idx++) {
  29. char c = source[idx];
  30. bool negative = false;
  31. switch(c){
  32. case '-':
  33. //判断-号的作用是什么,是负数?还是运算符号?
  34. if (isdigit(source[idx + 1])) {
  35. if (idx == 0)
  36. negative = true;
  37. else if (!isdigit(source[idx - 1]))
  38. negative = true;
  39. }
  40. if (negative) {
  41. num_tmp.clear();
  42. num_tmp.push_back('-');
  43. ++idx;
  44. goto dealNum;//跳转到处理数字的地方执行
  45. }//此处没有break,当判断出-号的作用不是负数符号而是运算符号时,顺序执行下面的代码块
  46. case '+':
  47. //+-优先级高于栈顶元素,直接入栈。
  48. //因为+-优先级最低,所以只有当栈为空的时候才能直接入栈
  49. if (sign.empty())
  50. sign.push(c);
  51. else {
  52. //弹出比+-优先级高或相等的运算符,括号不考虑的情况下,符合条件的有+-*/
  53. while (!sign.empty() && sign.top() != '(') {
  54. suffix.emplace_back(new member(sign.top()));
  55. sign.pop();
  56. }
  57. sign.push(c);
  58. }
  59. break;
  60. case '*':
  61. case '/':
  62. //*/优先级高于栈顶元素,直接入栈
  63. if (sign.empty() || sign.top() == '+' || sign.top() == '-')
  64. sign.push(c);
  65. else {
  66. //弹出比*/优先级高或者相等的运算符,括号不考虑的情况下,符合条件的只有*/
  67. while (!sign.empty() && (sign.top() == '*' || sign.top() == '/')) {
  68. suffix.emplace_back(new member(sign.top()));
  69. sign.pop();
  70. }
  71. sign.push(c);
  72. }
  73. break;
  74. case '(':
  75. //左括号直接入栈
  76. sign.push(c);
  77. break;
  78. case ')':
  79. //依次弹出运算符,加入到后缀表达式中,直到碰到左括号
  80. while (sign.top() != '(') {
  81. suffix.emplace_back(new member(sign.top()));
  82. sign.pop();
  83. }
  84. sign.pop();
  85. break;
  86. default:
  87. //数字直接加入后缀表达式
  88. //+-*/的ascII码都小于'0'
  89. //截取数字
  90. num_tmp.clear();
  91. dealNum:while (source[idx] >= '0' || source[idx] == '.') {
  92. num_tmp.push_back(source[idx]);
  93. ++idx;
  94. }
  95. --idx;
  96. suffix.emplace_back(new member(stod(num_tmp)));
  97. break;
  98. }
  99. }
  100. //当扫描的中缀表达式结束时,栈中的的所有运算符出栈
  101. while (!sign.empty()) {
  102. suffix.emplace_back(new member(sign.top()));
  103. sign.pop();
  104. }
  105. //输出后缀表达式
  106. for (auto x : suffix) {
  107. if (x->m_type == SIGN)
  108. cout << x->sign<<' ';
  109. else
  110. cout<<x->num<<' ';
  111. }
  112. cout << endl;
  113. //计算后缀表达式的结果
  114. stack<double> nums;
  115. for (auto x : suffix) {
  116. if (x->m_type == NUM)
  117. nums.push(x->num);
  118. else {
  119. double b = nums.top();
  120. nums.pop();
  121. double a = nums.top();
  122. nums.pop();
  123. switch (x->sign) {
  124. case '+':
  125. nums.push(a + b);
  126. break;
  127. case '-':
  128. nums.push(a - b);
  129. break;
  130. case '*':
  131. nums.push(a * b);
  132. break;
  133. case '/':
  134. nums.push(a / b);
  135. break;
  136. }
  137. }
  138. }
  139. cout << nums.top() << endl;
  140. return 0;
  141. }

推荐阅读