简单计算器
题目
设计一个计算机,输入一个字符串储存的数学表达式,可以计算包括“(”、“)”、“+”、“-”四种符号的数学表达式,输入的数学表达式字符串保证是合法的。[输入的数学表达式中可能存在空格字符]
思路
因为字符串的格式是合法的,并不需要排除干扰项,但首先需要解决的是以下问题:
①给我的字符串如何识别出并转化为数字的多少和所需进行的运算法则。
②识别后,计算的过程该如何正确的模拟出来,使得计算顺序不出错。
③什么样的情况下进行计算。
为了解决上述问题,可以进入一个概念——“状态机”(有限循环自动机)。
状态机:指的是在不同的状态下进行不同的操作,在某些特定的情况下状态机的状态可以发生转换。
状态机的形式:
以下为解决方案:
①当string字符串中的字符为以下几种情况时,进行如下操作:
(1)当为空格时,直接跳过。
(2)当为’0’至’9’的数字时,跳转状态机为数字存储的形式。
(3)当不为’0’至’9’的数字时,跳转状态机为操作形式。
注意:在状态机的状态发生变化时,需要进行推格操作。
②这里计算结果先后出现的形式其实类似于栈的先进先出进行的操作,所以在这设置了两个栈:一个数字栈,当识别出一个完整的数字后,存入其中,等待计算操作;另一个是操作字符栈,为‘+’或‘-’字符时便存入其中。
③需要辨识是否可进行计算操作,可使用标识compute_flag来作为条件,是否进行计算,为0时,不进行计算,为1时进行,当出现以下情况,compute_flag的值发生变化:
(1)出现‘+’或‘-’字符,compute_flag = 1;
(2)出现’(‘时,compute_flag = 0;
(3)出现’)'时,一定进行计算。
代码如下:
#include<iostream>
#include<string>
#include<stack>
using namespace std;
class Solution {
public:
int calculate(std::string s) {
static const int STATE_BEGIN = 0;
static const int NUMBER_STATE = 1;
static const int OPERATION_STATE = 2;
std::stack<int> number_stack;
std::stack<char> operation_stack;
int number = 0;
int STATE = STATE_BEGIN;
int compuate_flag = 0;
for (int i = 0; i < s.length(); i++){
if (s[i] == ' '){
continue;
}
switch(STATE){ // 三种状态机的转换
case STATE_BEGIN:
if (s[i] >= '0' && s[i] <= '9'){
STATE = NUMBER_STATE;
}
else{
STATE = OPERATION_STATE;
}
i--; //退格操作
break;
case NUMBER_STATE:
if (s[i] >= '0' && s[i] <= '9'){
number = number * 10 + s[i] - '0';
}
else{
number_stack.push(number);
if (compuate_flag == 1){ //可以进行计算
compute(number_stack, operation_stack);
}
number = 0;
i--;
STATE = OPERATION_STATE;
}
break;
case OPERATION_STATE:
if (s[i] == '+' || s[i] == '-'){
operation_stack.push(s[i]);
compuate_flag = 1;
}
else if (s[i] == '('){
STATE = NUMBER_STATE;
compuate_flag = 0;
}
else if (s[i] >= '0' && s[i] <= '9'){
STATE = NUMBER_STATE;
i--;
}
else if (s[i] == ')'){
compute(number_stack, operation_stack);
}
break;
}
}
if (number != 0){
number_stack.push(number);
compute(number_stack, operation_stack);
}
if (number == 0 && number_stack.empty()){
return 0;
}
return number_stack.top();
}
private:
void compute(std::stack<int> &number_stack,
std::stack<char> &operation_stack){
if (number_stack.size() < 2){
return;
}
int num2 = number_stack.top();
number_stack.pop();
int num1 = number_stack.top();
number_stack.pop();
if (operation_stack.top() == '+'){
number_stack.push(num1 + num2);
}
else if(operation_stack.top() == '-'){
number_stack.push(num1 - num2);
}
operation_stack.pop();
}
};
int main(){
std::string s = "1+121 - (14+(5-6) )";
Solution solve;
cout << "number:" << solve.calculate(s) << endl;
return 0;
}
致谢
本章知识点和思路由小象学院相关视频提供,由本人学习并梳理得出,希望自己加深记忆的同时,也能给大家提供更多有关于一些算法的知识点。
你的评论将会是对我最大的支持,谢谢!