赞
踩
知识点与难度
字符串、基础数学、栈、中等难度
描述
输入一个表达式(用字符串表示),求这个表达式的值。
保证字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。且表达式一定合法。
数据范围:表达式计算结果和过程中满足 ∣val∣≤1000 ,字符串长度满足 1≤n≤1000
输入描述:
输入一个算术表达式
输出描述:
得到计算结果
输入输出示例:
输入:
3+2*{1+2*[-4/(8-6)+7]}
输出:
25
我的代码:
- #include <iostream>
- #include <stack>
- using namespace std;
-
- int checkNumber(char c) {
- if ('0' <= c && c <= '9') {
- return c - '0';
- }
- return -1;
- }
-
- int getPriority(char c) {
- if (c == '+' || c == '-') {
- return 0;
- } else if (c == '*' || c == '/') {
- return 1;
- } else if (c == '#' || c == '(' || c == '{' || c == '[') {
- return -1;
- } else {
- return 2;
- }
- }
-
- float getCalculation(char opt, float n1, float n2) {
- //cout << n1 << opt << n2 << endl;
- if (opt == '+') {
- return n1 + n2;
- } else if (opt == '-') {
- return n1 - n2;
- } else if (opt == '*') {
- return n1 * n2;
- } else {
- return n1 / n2;
- }
- }
-
- int main() {
- string s;
- int start = 1;
- int minus = 0;
- stack<float> num;
- stack<char> op;
- op.emplace('#');
- float temp;
- int n;
- int priority;
- float n1; //数一
- float n2; //数二
- char opt; //运算符
- int key = 0;
- while (cin >> s) { // 注意 while 处理多个 case
- int i = 0;
- while (i < s.length()) {
- // 负数的特殊处理
- if (start == 1) {
- if (s[i] == '-') {
- minus = 1;
- i++;
- }
- start = 0;
- }
- //读取数字
- temp = 0;
- while (i < s.length() && (n = checkNumber(s[i])) != -1) {
- temp = temp * 10 + n;
- key = 1;
- i++;
- }
- if (key != 0) {
- if (minus == 1) {
- num.emplace(-temp);
- minus = 0;
- } else {
- num.emplace(temp);
- }
- key = 0;
- }
- //读取操作符
- while (i < s.length() && (n = checkNumber(s[i])) == -1) {
- if (start == 1) {
- if (s[i] == '-') {
- minus = 1;
- i++;
- }
- start = 0;
- continue;
- }
- priority = getPriority(s[i]);
- if (priority == 2) { //右括号
- while (getPriority(op.top()) != -1) {
- opt = op.top();
- op.pop();
- n2 = num.top();
- num.pop();
- n1 = num.top();
- num.pop();
- n1 = getCalculation(opt, n1, n2);
- num.emplace(n1);
- }
- op.pop();
-
- } else if (priority == -1) { //左括号
- op.emplace(s[i]);
- start = 1;
- } else { //运算符
- while (priority <= getPriority(op.top()) ) {
- opt = op.top();
- op.pop();
- n2 = num.top();
- num.pop();
- n1 = num.top();
- num.pop();
- n1 = getCalculation(opt, n1, n2);
- num.emplace(n1);
- }
- op.emplace(s[i]);
- }
- i++;
- }
- }
- while (num.size() > 1) {
- opt = op.top();
- op.pop();
- n2 = num.top();
- num.pop();
- n1 = num.top();
- num.pop();
- n1 = getCalculation(opt, n1, n2);
- num.emplace(n1);
- }
- cout << num.top() << endl;
- }
- }
- // 64 位输出请用 printf("%lld")
我的代码分析:
首先定义符号栈与数字栈,当输入数字时入数字栈,当输入符号时,查看当前符号与符号栈顶元素的优先级,若优先级当前符号大于栈顶符号,则入栈,否则,符号栈弹出一个运算符,数字栈弹出两个数字,运算后的结果压入数字栈。特殊的,输入左括号时直接入栈,输入右括号时出栈运算直到左括号出栈。当输入完成时,进行出栈运算,直到栈底只剩一个元素,该元素即为计算结果。
checkNumber() 用来检验是否为数字,是数字返回数字0-9,不是返回-1。
getPriority() 用来获取运算符优先级,加减为0,乘除为1,所有左括号与#号为-1,右括号为2。
getCalculation() 进行二元运算返回结果。
因为在表达式与括号内的头部可能出现负数,因此要校验一下开头是不是负数,用start变量标识是否为表达式或括号的开头,用minus变量标识开头是否为负数。之后循环读取数字,压入数字栈。接下来读取操作符,根据输入进行运算。表达式读取完成,出栈运算,直到只剩下一个元素。
top1代码:
- #include <iostream>
- #include <string.h>
-
- using namespace std;
-
- int char_i = 0;//使用全局变量,防止递归产生的无线循环
-
- int cal(char *character){
- int result = 0;
-
- int num[100] = {0};
- int num_index = 0;
-
- char sigh = '+';
- int len = strlen(character);
- while(char_i<len){
- int num_m = 0;
- if(character[char_i]=='('||character[char_i]=='['||character[char_i]=='{'){
- char_i++;
- num_m = cal(character);
- }
-
- while (1)
- {
- if (character[char_i] >= '0' && character[char_i] <= '9')
- {
- num_m = num_m * 10 + character[char_i] - '0';
- char_i++;
- }
- else
- break;
- }
-
- switch(sigh){
- case '+':
- num[num_index] = num_m;
- num_index++;
- break;
- case '-':
- num[num_index] = -num_m;
- num_index++;
- break;
- case '*':
- num[num_index-1] *= num_m;
- break;
- case '/':
- num[num_index-1] /= num_m;
- break;
- default:
- break;
- }
- sigh = character[char_i];
- if (character[char_i] == '}' || character[char_i] == ']' || character[char_i] == ')') {//结束本次递归,返回括号内运算的结果
- char_i++;
- break;
- }
- char_i++;
-
-
- }
-
-
- for (int i = 0; i < num_index; i++)
- {
- result += num[i];
- }
-
- return result;
-
-
-
- }
-
-
- int main() {
- char character[100] = { 0 };
- int result = 0;
- cin >> character;
-
- result = cal(character);
-
- cout << result << endl;
- }
top1代码分析:
只使用一个数字数组,将整个表达式转换成一个加法运算。预设一个‘+’运算符,这样当第一个数字为负数时,补了一个+0,之后的加法运算就是向数字数组中添加一个正数,减法运算添加一个负数,乘除法则是取前一个数字进行运算后返回数组。对于括号则是进行递归调用,计算完括号中的内容后返回。
总结:
将整个表达式转换成一个加法运算,我觉得还挺妙的,对于括号这种形式的运算,也要想到递归的算法来简化问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。