当前位置:   article > 正文

C++实现中缀表达式转后缀_设计算法,键键盘输入数值型中缀表达式,将其转换为后缀表达式并输出

设计算法,键键盘输入数值型中缀表达式,将其转换为后缀表达式并输出

1.目的:

        实现中缀表达式转为后缀,并计算得到计算结果输出显示。

2.输入输出介绍:

        在英文输入下,键入你的表达式(注:这里只实现了 +-*/ 没有更复杂的幂次等计算)

之后,你将看到输出三部分:

        ①.将您输入的表达式的数字部分 和 操作符部分 分开,以独占一行的方式打印输出;

        ②.表达式的后缀输出;

        ③.计算结果。

        

3.完整代码,照例,无偿放在这里了:

  1. /*
  2. 1.要实现的目标是:根据输入的数学表达式,得到计算结果
  3. 2.分析:
  4. 数学表达式使用 字符串接受;
  5. 从表达式中摘出来需要得到数字部分;
  6. 需要两个栈
  7. 字符串类型的;一个栈用于中缀表达式转后缀;一个在后缀计算结果时候用
  8. */
  9. // 栈 先使用自定义实现;后面可以改成使用 STL容器
  10. #include<iostream>
  11. using namespace std;
  12. #include<string>
  13. #include<vector>
  14. #include<ctype.h> // 当判断的字符是数字时,函数返回1~9的非零值,当判断的字符不是数字时,函数返回 0
  15. // 自定义栈的数据结构
  16. typedef struct lNode{
  17. string data;
  18. struct lNode* next;
  19. }LNode, *LinkStack;
  20. // 初始化 构造成不带头结点的
  21. void init(LinkStack& s)
  22. {
  23. s = NULL;
  24. }
  25. // 判空
  26. bool isEmpty(LinkStack s)
  27. {
  28. if (s == NULL)
  29. return true;
  30. else
  31. {
  32. return false;
  33. }
  34. }
  35. // 进栈操作 为了方便对栈顶的操作 这里使用 --- 新元素 指向 老元素 --- 的结构
  36. void pushStack(LinkStack& s, string ele)
  37. {
  38. LNode* newNode = new LNode;
  39. newNode->data = ele;
  40. newNode->next = s;
  41. s = newNode; // 由于 要改变 栈顶指针的值 这里需要使用引用
  42. }
  43. // 出栈操作
  44. void popStack(LinkStack& s, string& ret)
  45. {
  46. if (isEmpty(s))
  47. {
  48. return;
  49. }
  50. ret = s->data;
  51. LNode* temp = s;
  52. s = s->next;
  53. delete temp;
  54. }
  55. // 读栈顶元素
  56. string getTop(LinkStack s)
  57. {
  58. if (!isEmpty(s))
  59. {
  60. return s->data;
  61. }
  62. }
  63. //销毁栈
  64. void destroyStack(LinkStack& s)
  65. {
  66. LNode* temp = s;
  67. while (temp != NULL)
  68. {
  69. LNode* nextNode = temp->next;
  70. delete temp;
  71. temp = nextNode;
  72. }
  73. s = NULL; // 将外部栈指针置为 NULL
  74. }
  75. // 获取用户输入
  76. string getExpression()
  77. {
  78. string expression;
  79. cout << "请输入您的表达式,以回车结束" << endl;
  80. getline(cin, expression);
  81. return expression;
  82. }
  83. // 中缀转后缀
  84. // 首先将 数字 与 +-*/ 操作符 区分出来,放入容器中,, 比如把 (32.1+2)*7/4 分成 ( 32.1 + 2 ) * 7 / 4
  85. vector<string> lookBetter(string expression)
  86. {
  87. vector<string> vS;
  88. string str;
  89. for (auto c : expression)
  90. {
  91. if (isdigit(c) || c =='.')
  92. {
  93. str += c;
  94. }
  95. else
  96. {
  97. if (!str.empty())
  98. {
  99. vS.push_back(str);
  100. str.clear();
  101. }
  102. if (c == ' ')
  103. {
  104. // 跳过空格
  105. continue;
  106. }
  107. str = c;
  108. vS.push_back(str);
  109. str.clear();
  110. }
  111. }
  112. if (!str.empty())
  113. {
  114. vS.push_back(str);
  115. str.clear();
  116. }
  117. return vS;
  118. }
  119. // 判断字符串 是否可以转成小数
  120. bool isNumber(const string& str) // 使用 const 限定不能修改; 使用引用直接在本体上操作,不需要复制一份,提高性能
  121. {
  122. try {
  123. stod(str); // 字符串 转 double类型
  124. return true;
  125. }
  126. catch(const invalid_argument& e)
  127. {
  128. return false;
  129. }
  130. catch (const out_of_range& e)
  131. {
  132. return false;
  133. }
  134. }
  135. // 中缀表达式 转后缀
  136. vector<string> mid2back(string expression)
  137. {
  138. LinkStack S;
  139. init(S);
  140. vector<string> ret;
  141. vector<string> vS = lookBetter(expression);
  142. for (vector<string>::iterator itBegin = vS.begin(); itBegin != vS.end(); itBegin++)
  143. {
  144. if (isNumber(*itBegin)) // 如果是数字部分 直接放入后缀容器
  145. {
  146. ret.push_back(*itBegin);
  147. }
  148. else
  149. {
  150. // 这里用的 string 类型,需要使用双引号
  151. if ((*itBegin) == "(") // 如果是"(" 直接入栈
  152. {
  153. pushStack(S, (*itBegin));
  154. }
  155. if ((*itBegin) == "+" || (*itBegin) == "-") // 如果是 "+"或"-" 将栈中遇到的所有+—*/ 出栈,,直到遇到第一个非 +—*/ ,,之后再将自己入栈
  156. {
  157. if (isEmpty(S))
  158. pushStack(S, (*itBegin));
  159. else
  160. {
  161. while (!isEmpty(S) && (getTop(S) == "+" || getTop(S) == "-" || getTop(S) == "*" || getTop(S) == "/"))
  162. {
  163. // 这里的非空判断是必要的 场景为 2+3-1 时 -将+出栈后,栈由非空变为空
  164. string popEle;
  165. popStack(S, popEle);
  166. ret.push_back(popEle);
  167. }
  168. pushStack(S, (*itBegin));
  169. }
  170. }
  171. if ((*itBegin) == "*" || (*itBegin) == "/") // 如果是 "*"或"/" 将栈中遇到的所有 */ 出栈,,直到遇到第一个非 */ ,,之后再将自己入栈
  172. {
  173. if (isEmpty(S))
  174. pushStack(S, (*itBegin));
  175. else
  176. {
  177. while (!isEmpty(S) && getTop(S) == "*" || getTop(S) == "/")
  178. {
  179. string popEle;
  180. popStack(S, popEle);
  181. ret.push_back(popEle);
  182. }
  183. pushStack(S, (*itBegin));
  184. }
  185. }
  186. if ((*itBegin) == ")") // 如果是")" 将遇到的"("之前的所有元素出栈放入后缀容器中,
  187. {
  188. string popEle;
  189. while (getTop(S) != "(")
  190. {
  191. popStack(S, popEle);
  192. ret.push_back(popEle);
  193. }
  194. popStack(S, popEle); // 将"(" 出栈,不添加到 后缀容器中 ")"不入栈
  195. }
  196. }
  197. }
  198. // 最后 如果 栈内非空,将栈中元素 出栈
  199. while (!isEmpty(S))
  200. {
  201. string popEle;
  202. popStack(S, popEle);
  203. ret.push_back(popEle);
  204. }
  205. return ret;
  206. }
  207. // 计算后缀表达式 得到正确结果
  208. double compute(vector<string> vS)
  209. {
  210. LinkStack S2;
  211. init(S2);
  212. for (vector<string>::iterator itBegin = vS.begin(); itBegin != vS.end(); itBegin++)
  213. {
  214. if (isNumber(*itBegin)) // 如果是数字 直接入栈
  215. {
  216. pushStack(S2, *itBegin);
  217. }
  218. else
  219. {
  220. string leftValue;
  221. string rightValue;
  222. popStack(S2, rightValue); // 先出栈的为右值
  223. popStack(S2, leftValue);
  224. if (*itBegin == "+")
  225. {
  226. double l = stod(leftValue);
  227. double r = stod(rightValue);
  228. pushStack(S2, to_string(l + r));
  229. }
  230. if (*itBegin == "-")
  231. {
  232. double l = stod(leftValue);
  233. double r = stod(rightValue);
  234. pushStack(S2, to_string(l - r));
  235. }
  236. if (*itBegin == "*")
  237. {
  238. double l = stod(leftValue);
  239. double r = stod(rightValue);
  240. pushStack(S2, to_string(l * r));
  241. }
  242. if (*itBegin == "/")
  243. {
  244. double l = stod(leftValue);
  245. double r = stod(rightValue);
  246. pushStack(S2, to_string(l / r));
  247. }
  248. }
  249. }
  250. if (!isEmpty(S2))
  251. {
  252. string ret;
  253. popStack(S2, ret);
  254. double retValue = stod(ret);
  255. return retValue;
  256. }
  257. }
  258. // 测试案例
  259. void test()
  260. {
  261. string expression = getExpression();
  262. vector<string> vS = lookBetter(expression);
  263. for (auto ele : vS)
  264. {
  265. cout << ele << endl;
  266. }
  267. cout << "----------------------" << endl;
  268. vector<string> mB = mid2back(expression);
  269. for (string ele : mB)
  270. {
  271. cout << ele<<" ";
  272. }
  273. cout << endl << "----------------------" << endl;
  274. double value = compute(mB);
  275. cout << "计算结果是:" << value << endl;
  276. }
  277. int main()
  278. {
  279. test();
  280. system("pause");
  281. return 0;
  282. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/754219
推荐阅读
相关标签
  

闽ICP备14008679号