基于标准c++实现计算器
一.需求实现
1.实现功能
支持运算符:+,-,*,/。其他符号:()
支持数据类型:正整数(负数与小数后续实现)
2.实现方法
符号优先等级处理方法:符号等级制
运算式表达式处理方法:双栈法
二 双栈法实现表达式计算思路
设计两个栈来分别储存运算符和数字,运算符栈用‘#’表示开始与结束
让运算符和数字依次入栈
出栈规则:当前入栈的运算符比栈顶的运算符优先级低
总的来说就是有括号先算括号内,算完括号内再算整体
例:12+(2*3+5)
输入:#12+(2*3+5)#
数字栈 | 符号栈 | 过程 |
# | 扫描字符串得到#,将其压入symbol栈 | |
1 | 扫描字符串得到1,将其压入number栈 | |
12 | 扫描字符串得到2,将其压入number栈 | |
12 | #+ | 扫描字符串得到+,将其压入symbol栈 |
12 | #+( | 扫描字符串得到(,'('优先级大于‘+’,将‘(’压入symbol栈 |
122 | #+( | 扫描字符串得到2,将其压入number栈 |
122 | #+(* | 扫描字符串得到*,'*'优先级小于‘(’,但通过代码将‘(’后的符号的优先级高于‘(’,将'*'压入symbol栈 |
1223 | #+(* | 扫描字符串得到3,将其压入number栈 |
126 | #+(+ | 扫描字符串得到+,'+'优先级小于将‘*’,将'*'从symbol栈弹出,数字栈弹出两个数2/3,2与3运算得到6,6压入number栈,'+'压入symbol栈 |
1265 | #+(+ | 扫描字符串得到5,将其压入number栈 |
12 11 | #+ | 扫描字符串得到')',')'优先级小于将‘+’,将'+'从symbol栈弹出,数字栈弹出两个数6/5,6与5运算得到11,11压入number栈,'('弹symbol栈 |
23 | # | 扫描字符串得到'#',‘#’是终止符,将'+'从symbol栈弹出,数字栈弹出两个数12/11,12与11运算得到23,23压入number栈 |
三 实现代码
1.运算优先级功能实现
(1)运算符号等级
int SymbolPri(char sym) //量化符号优先级
{
switch (sym)
{
case '#': return 0;
case ')': return 1;
case '+':
case '-': return 2;
case '/':
case '*': return 3;
case '(': return 4;
default:return -1;
}
}
(2)运算优先级的获取
int PreOrder(char sym1, char sym2) //比较两个符号的优先级
{
int i = SymbolPri(sym1); // i为即将入栈的符号,j为栈顶符号
int j = SymbolPri(sym2);
if (sym2 == '(') //( )内的 + - * / 还能进栈但是 + - * / 对应的数字小于 ( 对应的数字 所以把这里设置成 1 让()内的 + - * / 可以进栈
return 1;
if (i == -1 || j == -1)
return -1;
if (i > j)
return 1;
else if (i == j)
return 0;
else
return -1;
}
2.运算表达式处理并计算
int Calculate(char* s)
{
int x;
bool flag = false; //标志位,判断两栈是否为空
stack<char> symbol; //符号栈
char c; //用来保存symbol栈顶的数据
stack<int> number; //数字栈
int num1, num2, num; //num1/num2用来保存数字栈栈顶的数字 num 用来压入数据
symbol.push('#');
number.push(1);
cout << '#' << "is pushed1" << endl;
char* p = s; //输入缓存到char *p中
while (*p != '#')
{
if (isNumber(p)) //碰到数字
{
p = getNum(p, num);
number.push(num);
cout << num << "is pushed2" << endl;
}
else //碰到符号
{
c = symbol.top();
if (PreOrder(*p, c) > 0) //判断符号优先级 要入栈符号优先级大于栈顶符号
{
symbol.push(*p);
cout << *p << "is pushed3" << endl;
}
else //要入栈符号优先级小于栈顶符号 弹出栈顶符号,数字栈弹出两个数字,进行计算
{
symbol.pop();
cout << c << "is pushed4" << endl;
num1 = number.top();
number.pop();
cout << num1 << "is poped5" << endl;
num2 = number.top();
number.pop();
cout << num2 << "is poped6" << endl;
x = express(num2, num1, c);
number.push(x); //计算结果压入数字栈中
cout << x << "is pushed7" << endl;
if ((*p == '+') || (*p == '-') || (*p == '*') || (*p == '/')) //计算完后符号p为+-*/继续压入栈中
{
symbol.push(*p);
cout << *p << "is pushed8" << endl;
}
if (*p == ')')
{
c = symbol.top();
if (c != '(')
{
c = symbol.top();
symbol.pop();
num1 = number.top();
number.pop();
cout << num1 << "is poped9" << endl;
num2 = number.top();
number.pop();
cout << num2 << "is poped10" << endl;
x = express(num2, num1, c);
number.push(x);
cout << x << "is pushed11" << endl;
c = symbol.top();
symbol.pop();
cout << c << "is poped12" << endl;
}
else //c = '('
{
symbol.pop();
cout << c << "is poped13" << endl;
}
}
}
}
p++;
}
if (*p == '#')
{
c = symbol.top();
symbol.pop();
cout << c << "is poped14" << endl;
num1 = number.top();
number.pop();
cout << num1 << "is poped15" << endl;
num2 = number.top();
number.pop();
cout << num2 << "is poped16" << endl;
x = express(num2, num1, c);
cout << x << "is pushed17" << endl;
number.push(x);
c = symbol.top();
while (c != '#')
{
c = symbol.top();
symbol.pop();
cout << c << " is poped18" << endl;
num1 = number.top();
number.pop();
cout << num1 << " is poped19" << endl;
num2 = number.top();
number.pop();
cout << num2 << " is poped20" << endl;
x = express(num2, num1, c);
number.push(x);
cout << x << " is pushed21" << endl;
c = symbol.top();
symbol.pop();
cout << c << "is poped22" << endl;
}
num = number.top();
number.pop();
cout << "结果是:" << num << endl;
return num;
}
}
四.完整代码
#include<iostream>
#include<stack>
using namespace std;
int SymbolPri(char sym) //量化符号优先级
{
switch (sym)
{
case '#': return 0;
case ')': return 1;
case '+':
case '-': return 2;
case '/':
case '*': return 3;
case '(': return 4;
default:return -1;
}
}
int PreOrder(char sym1, char sym2) //比较两个符号的优先级
{
int i = SymbolPri(sym1); // i为即将入栈的符号,j为栈顶符号
int j = SymbolPri(sym2);
if (sym2 == '(') //( )内的 + - * / 还能进栈但是 + - * / 对应的数字小于 ( 对应的数字 所以把这里设置成 1 让()内的 + - * / 可以进栈
return 1;
if (i == -1 || j == -1)
return -1;
if (i > j)
return 1;
else if (i == j)
return 0;
else
return -1;
}
bool isNumber(char* p) //判断输入字符是数字或符号
{
if (*p >= '0' && *p <= '9')
return true;
else
return false;
}
char* getNum(char* p, int& num) //将数字字符转化为数字
{
num = 0;
while (isNumber(p))
{
num = 10 * num + (*p - '0');
p++;
}
p--; //???????
return p;
}
int express(int num1, int num2, char sym) //运算法则
{
cout << num1 << sym << num2 << "is calculatded" << endl;
switch (sym)
{
case '+':return num1 + num2;
case '-':return num1 - num2;
case '*':return num1 * num2;
case '/':return num1 / num2;
default:cout << "wrong" << endl;
}
}
int Calculate(char* s)
{
int x;
bool flag = false; //标志位,判断两栈是否为空
stack<char> symbol; //符号栈
char c; //用来保存symbol栈顶的数据
stack<int> number; //数字栈
int num1, num2, num; //num1/num2用来保存数字栈栈顶的数字 num 用来压入数据
symbol.push('#');
number.push(1);
cout << '#' << "is pushed1" << endl;
char* p = s; //输入缓存到char *p中
while (*p != '#')
{
if (isNumber(p)) //碰到数字
{
p = getNum(p, num);
number.push(num);
cout << num << "is pushed2" << endl;
}
else //碰到符号
{
c = symbol.top();
if (PreOrder(*p, c) > 0) //判断符号优先级 要入栈符号优先级大于栈顶符号
{
symbol.push(*p);
cout << *p << "is pushed3" << endl;
}
else //要入栈符号优先级小于栈顶符号 弹出栈顶符号,数字栈弹出两个数字,进行计算
{
symbol.pop();
cout << c << "is pushed4" << endl;
num1 = number.top();
number.pop();
cout << num1 << "is poped5" << endl;
num2 = number.top();
number.pop();
cout << num2 << "is poped6" << endl;
x = express(num2, num1, c);
number.push(x); //计算结果压入数字栈中
cout << x << "is pushed7" << endl;
if ((*p == '+') || (*p == '-') || (*p == '*') || (*p == '/')) //计算完后符号p为+-*/继续压入栈中
{
symbol.push(*p);
cout << *p << "is pushed8" << endl;
}
if (*p == ')')
{
c = symbol.top();
if (c != '(')
{
c = symbol.top();
symbol.pop();
num1 = number.top();
number.pop();
cout << num1 << "is poped9" << endl;
num2 = number.top();
number.pop();
cout << num2 << "is poped10" << endl;
x = express(num2, num1, c);
number.push(x);
cout << x << "is pushed11" << endl;
c = symbol.top();
symbol.pop();
cout << c << "is poped12" << endl;
}
else //c = '('
{
symbol.pop();
cout << c << "is poped13" << endl;
}
}
}
}
p++;
}
if (*p == '#')
{
c = symbol.top();
symbol.pop();
cout << c << "is poped14" << endl;
num1 = number.top();
number.pop();
cout << num1 << "is poped15" << endl;
num2 = number.top();
number.pop();
cout << num2 << "is poped16" << endl;
x = express(num2, num1, c);
cout << x << "is pushed17" << endl;
number.push(x);
c = symbol.top();
while (c != '#')
{
c = symbol.top();
symbol.pop();
cout << c << " is poped18" << endl;
num1 = number.top();
number.pop();
cout << num1 << " is poped19" << endl;
num2 = number.top();
number.pop();
cout << num2 << " is poped20" << endl;
x = express(num2, num1, c);
number.push(x);
cout << x << " is pushed21" << endl;
c = symbol.top();
symbol.pop();
cout << c << "is poped22" << endl;
}
num = number.top();
number.pop();
cout << "结果是:" << num << endl;
return num;
}
}
int main()
{
char mychar[100];
cin.getline(mychar, 50); //#作为终止符
cout << Calculate(mychar) << endl;
return 0;
}