核心部分伪代码:
stack 符栈,数栈;
c=getchar()
while(c!='\n' || !符栈.empty()){
if(c是操作数) 数栈.push();c=getchar();
else if(符栈.empty()) 符栈.push(c);c=getchar();
else switch(precede(符栈.top(),c)){//比较栈运算符和当前运算符的优先级
case '<': 符栈.push(c); c=getchar();break;
case '=': 符栈.pop(); c=getchar();break;//脱括号
case '>': { //栈顶优先级更高,运算
b=数栈.top();数栈.pop();
a=数栈.top();数栈.pop();
o=符栈.top();符栈.pop();
数栈.push(operate(a,o,b));
break;//不需要getchar(),因为当前c还没有任何操作
}
}
}
printf(数栈.top())
实现的时候需要注意:数据类型,操作数是多位数。
除了本篇的思路,计算器还可以用中缀表达式和后缀表达式(逆波兰表达式)实现。
//只有四则运算
#include<bits/stdc++.h>
using namespace std;
char precede(char a, char b){ //运算符的优先关系
char mark[4][4] = { {'>','>','<','<'},
{'>','>','<','<'},
{'>','>','>','>'},
{'>','>','>','>'}
};
char ch[4]={'+','-','*','/'};
for(int i=0;i<4;i++){
if(a==ch[i])
for(int j=0;j<4;j++)
if(b==ch[j]) return mark[i][j];
}
}
double operate(double a, char o, double b){ //二元运算
switch(o){
case '+': return a+b;
case '-': return a-b;
case '*': return a*b;
case '/': return a/b;
}
}
int main (){
string s;
stack<double>digit; //操作数栈
stack<char>mark; //运算符栈
double op1;
double a,b;
char o;
while(getline(cin, s) && s != "0") {
for(int i=0; s[i]; i++) { //跳过空格,获取到的就只有数字或者符号
if(s[i]==' ') continue;
else if(isdigit(s[i])) {
op1 = 0;
while(isdigit(s[i])) {
op1 = op1 * 10 + s[i] - '0';
i++;
}
i--;
digit.push(op1);
}else if(mark.empty()) mark.push(s[i]); //在第一个运算符的时候字符栈里是空的
else switch(precede(mark.top(),s[i])){ //比较当前运算符和栈运算符的优先级
case '<': mark.push(s[i]); break;
case '>': { //栈顶优先级更高,就进行运算
b=digit.top();digit.pop();
a=digit.top();digit.pop();
o=mark.top();mark.pop();
digit.push(operate(a,o,b));
i--;
break;
}
}
}
while(!mark.empty()){ //这个时候,只剩下前面低优先级运算符和一个高优先级运算符,以及操作数
b=digit.top();digit.pop();
a=digit.top();digit.pop();
o=mark.top();mark.pop();
digit.push(operate(a,o,b));
}
printf("%.2f\n",digit.top());
}
return 0;
}
//四则运算和括号.略微修改上面的就行
#include<bits/stdc++.h>
using namespace std;
char precede(char a, char b){ //运算符的优先关系
char mark[6][6] = { {'>','>','<','<','<','>'},
{'>','>','<','<','<','>'},
{'>','>','>','>','<','>'},
{'>','>','>','>','<','>'},
{'<','<','<','<','<','='},
{'>','>','>','>',' ','>'}
};
char ch[6]={'+','-','*','/','(',')'};
for(int i=0;i<6;i++){
if(a==ch[i])
for(int j=0;j<6;j++)
if(b==ch[j]) return mark[i][j];
}
}
double operate(double a, char o, double b){ //二元运算
switch(o){
case '+': return a+b;
case '-': return a-b;
case '*': return a*b;
case '/': return a/b;
}
}
int main (){
string s;
stack<double>digit; //操作数栈
stack<char>mark; //运算符栈
double op1;
double a,b;
char o;
while(getline(cin, s) && s != "0") {
for(int i=0; s[i]; i++) { //跳过空格,获取到的就只有数字或者符号
if(s[i]==' ') continue;
else if(isdigit(s[i])) {
op1 = 0;
while(isdigit(s[i])) {
op1 = op1 * 10 + s[i] - '0';
i++;
}
i--;
digit.push(op1);
}else if(mark.empty()) mark.push(s[i]); //在第一个运算符的时候字符栈里是空的
else switch(precede(mark.top(),s[i])){ //比较当前运算符和栈运算符的优先级
case '<': mark.push(s[i]); break;
case '=': mark.pop(); break;
case '>': { //栈顶优先级更高,就进行运算
b=digit.top();digit.pop();
a=digit.top();digit.pop();
o=mark.top();mark.pop();
digit.push(operate(a,o,b));
i--;
break;
}
}
}
while(!mark.empty()){ //这个时候,只剩下前面很多低优先级运算符和一个高优先级运算符,以及操作数
b=digit.top();digit.pop();
a=digit.top();digit.pop();
o=mark.top();mark.pop();
digit.push(operate(a,o,b));
}
printf("%.2f\n",digit.top());
}
return 0;
}