当前位置:   article > 正文

【华为机试】HJ50 四则运算_符号运算华为机试

符号运算华为机试

知识点与难度

字符串、基础数学、栈、中等难度

描述

输入一个表达式(用字符串表示),求这个表达式的值。

保证字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。且表达式一定合法。

数据范围:表达式计算结果和过程中满足 ∣val∣≤1000  ,字符串长度满足 1≤n≤1000 

输入描述:

输入一个算术表达式

输出描述:

得到计算结果

输入输出示例:

输入:

3+2*{1+2*[-4/(8-6)+7]}

输出:

25

我的代码:

  1. #include <iostream>
  2. #include <stack>
  3. using namespace std;
  4. int checkNumber(char c) {
  5. if ('0' <= c && c <= '9') {
  6. return c - '0';
  7. }
  8. return -1;
  9. }
  10. int getPriority(char c) {
  11. if (c == '+' || c == '-') {
  12. return 0;
  13. } else if (c == '*' || c == '/') {
  14. return 1;
  15. } else if (c == '#' || c == '(' || c == '{' || c == '[') {
  16. return -1;
  17. } else {
  18. return 2;
  19. }
  20. }
  21. float getCalculation(char opt, float n1, float n2) {
  22. //cout << n1 << opt << n2 << endl;
  23. if (opt == '+') {
  24. return n1 + n2;
  25. } else if (opt == '-') {
  26. return n1 - n2;
  27. } else if (opt == '*') {
  28. return n1 * n2;
  29. } else {
  30. return n1 / n2;
  31. }
  32. }
  33. int main() {
  34. string s;
  35. int start = 1;
  36. int minus = 0;
  37. stack<float> num;
  38. stack<char> op;
  39. op.emplace('#');
  40. float temp;
  41. int n;
  42. int priority;
  43. float n1; //数一
  44. float n2; //数二
  45. char opt; //运算符
  46. int key = 0;
  47. while (cin >> s) { // 注意 while 处理多个 case
  48. int i = 0;
  49. while (i < s.length()) {
  50. // 负数的特殊处理
  51. if (start == 1) {
  52. if (s[i] == '-') {
  53. minus = 1;
  54. i++;
  55. }
  56. start = 0;
  57. }
  58. //读取数字
  59. temp = 0;
  60. while (i < s.length() && (n = checkNumber(s[i])) != -1) {
  61. temp = temp * 10 + n;
  62. key = 1;
  63. i++;
  64. }
  65. if (key != 0) {
  66. if (minus == 1) {
  67. num.emplace(-temp);
  68. minus = 0;
  69. } else {
  70. num.emplace(temp);
  71. }
  72. key = 0;
  73. }
  74. //读取操作符
  75. while (i < s.length() && (n = checkNumber(s[i])) == -1) {
  76. if (start == 1) {
  77. if (s[i] == '-') {
  78. minus = 1;
  79. i++;
  80. }
  81. start = 0;
  82. continue;
  83. }
  84. priority = getPriority(s[i]);
  85. if (priority == 2) { //右括号
  86. while (getPriority(op.top()) != -1) {
  87. opt = op.top();
  88. op.pop();
  89. n2 = num.top();
  90. num.pop();
  91. n1 = num.top();
  92. num.pop();
  93. n1 = getCalculation(opt, n1, n2);
  94. num.emplace(n1);
  95. }
  96. op.pop();
  97. } else if (priority == -1) { //左括号
  98. op.emplace(s[i]);
  99. start = 1;
  100. } else { //运算符
  101. while (priority <= getPriority(op.top()) ) {
  102. opt = op.top();
  103. op.pop();
  104. n2 = num.top();
  105. num.pop();
  106. n1 = num.top();
  107. num.pop();
  108. n1 = getCalculation(opt, n1, n2);
  109. num.emplace(n1);
  110. }
  111. op.emplace(s[i]);
  112. }
  113. i++;
  114. }
  115. }
  116. while (num.size() > 1) {
  117. opt = op.top();
  118. op.pop();
  119. n2 = num.top();
  120. num.pop();
  121. n1 = num.top();
  122. num.pop();
  123. n1 = getCalculation(opt, n1, n2);
  124. num.emplace(n1);
  125. }
  126. cout << num.top() << endl;
  127. }
  128. }
  129. // 64 位输出请用 printf("%lld")

我的代码分析:

首先定义符号栈数字栈,当输入数字时入数字栈,当输入符号时,查看当前符号与符号栈顶元素的优先级,若优先级当前符号大于栈顶符号,则入栈,否则,符号栈弹出一个运算符,数字栈弹出两个数字,运算后的结果压入数字栈。特殊的,输入左括号时直接入栈,输入右括号时出栈运算直到左括号出栈。当输入完成时,进行出栈运算,直到栈底只剩一个元素,该元素即为计算结果。

checkNumber() 用来检验是否为数字,是数字返回数字0-9,不是返回-1。

getPriority() 用来获取运算符优先级,加减为0,乘除为1,所有左括号与#号为-1,右括号为2。

getCalculation() 进行二元运算返回结果。

因为在表达式与括号内的头部可能出现负数,因此要校验一下开头是不是负数,用start变量标识是否为表达式或括号的开头,用minus变量标识开头是否为负数。之后循环读取数字,压入数字栈。接下来读取操作符,根据输入进行运算。表达式读取完成,出栈运算,直到只剩下一个元素。

top1代码:

  1. #include <iostream>
  2. #include <string.h>
  3. using namespace std;
  4. int char_i = 0;//使用全局变量,防止递归产生的无线循环
  5. int cal(char *character){
  6. int result = 0;
  7. int num[100] = {0};
  8. int num_index = 0;
  9. char sigh = '+';
  10. int len = strlen(character);
  11. while(char_i<len){
  12. int num_m = 0;
  13. if(character[char_i]=='('||character[char_i]=='['||character[char_i]=='{'){
  14. char_i++;
  15. num_m = cal(character);
  16. }
  17. while (1)
  18. {
  19. if (character[char_i] >= '0' && character[char_i] <= '9')
  20. {
  21. num_m = num_m * 10 + character[char_i] - '0';
  22. char_i++;
  23. }
  24. else
  25. break;
  26. }
  27. switch(sigh){
  28. case '+':
  29. num[num_index] = num_m;
  30. num_index++;
  31. break;
  32. case '-':
  33. num[num_index] = -num_m;
  34. num_index++;
  35. break;
  36. case '*':
  37. num[num_index-1] *= num_m;
  38. break;
  39. case '/':
  40. num[num_index-1] /= num_m;
  41. break;
  42. default:
  43. break;
  44. }
  45. sigh = character[char_i];
  46. if (character[char_i] == '}' || character[char_i] == ']' || character[char_i] == ')') {//结束本次递归,返回括号内运算的结果
  47. char_i++;
  48. break;
  49. }
  50. char_i++;
  51. }
  52. for (int i = 0; i < num_index; i++)
  53. {
  54. result += num[i];
  55. }
  56. return result;
  57. }
  58. int main() {
  59. char character[100] = { 0 };
  60. int result = 0;
  61. cin >> character;
  62. result = cal(character);
  63. cout << result << endl;
  64. }

top1代码分析:

只使用一个数字数组,将整个表达式转换成一个加法运算。预设一个‘+’运算符,这样当第一个数字为负数时,补了一个+0,之后的加法运算就是向数字数组中添加一个正数,减法运算添加一个负数,乘除法则是取前一个数字进行运算后返回数组。对于括号则是进行递归调用,计算完括号中的内容后返回。

总结:

将整个表达式转换成一个加法运算,我觉得还挺妙的,对于括号这种形式的运算,也要想到递归的算法来简化问题。

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

闽ICP备14008679号