说明
实现具有加减乘除和乘方(幂运算)的整形数字运算功能的计算器,且支持带括号的运算。以字符串形式作为输入。
思路:
根据运算符优先级的大小分层的思想来完成设计。由于括号的优先级最高,第一层需要解析出字符串中的括号;首先准备一个栈stack,从左向右判断每一个字符如果不是右括号")“则入栈,直到碰到右括号,开始出栈,遇到第一个出栈的左括号”(“为止,两个括号中间的字符组成的运算优先级最高,进行计算,将结果转为字符入栈,直至原始字符串中所有的字符入栈;第二层借助两个向量vector,一个是vector一个是vector分别存放字符串中的数字和运算符,从左向右按字符串顺序解析;第三层,由于运算符中乘方的优先级最高,因此遍历符号向量,遇到”^“时,计算对应数字向量中两个数字的乘方,依次“剔除”所有幂符号;第四层,剩下的运算符中,乘除的优先级高于加减,采取第三层同样的思路,从左向右遍历剩余运算法,遇到乘除则计算,完成"×"和”/“的运算;第五层,符号vector中只剩余"+"和”-",从左向右完成数字vector中的加减法运算。按照以上分层思路即可轻松实现。
流程图:
代码如下:
//实现一个计算器功能
#include <iostream>
#include <vector>
#include <stack>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <math.h>
using namespace std;
/*================================================
calc() 分离字符串中的数字和运算符
statistics() 统计字符串中的数字和运算符
calculation() 计算字符串的值
del_power() 去除字符串中的乘方
del_multi() 去除字符串中的乘号和除号
=================================================*/
/* 函数声明 */
void del_multi(vector<int> num, vector<char> symbol, int* add_sub_num, char* add_sub_symbol, int* symbol_length);
void del_power(vector<int> &num, vector<char> &symbol);
void statistics(const char* expr, int expr_len, vector<int> &num, vector<char> &symbol);
int calculation(const char* expr);
int calc(const char* expr);
/* 识别括号 */
int calc(const char* expr)
{
int expr_len = strlen(expr);
stack<char> element;
for(int i = 0; i < expr_len; i++)
{
if(expr[i] != ')')
{
element.push(expr[i]);
}
else
{
string strTemp = "";
while(element.top() != '(') /* 判断一对括号 */
{
strTemp = element.top() + strTemp;
element.pop();
}
element.pop();
int result = calculation(strTemp.c_str()); /* 将括号内的运算完成计算 */
stack<char> temp;
while (result != 0)
{
temp.push((result % 10) + '0');
result = result / 10;
}
while(!temp.empty())
{
element.push(temp.top());
temp.pop();
}
}
}
string str = "";
while(!element.empty())
{
str = element.top() + str;
element.pop();
}
int result = calculation(str.c_str()); /* 计算不含有括号的字符串 */
return result;
}
/* 计算解析完成的不带括号的字符串 */
int calculation(const char* expr)
{
int expr_len = strlen(expr);
int result = 0;
vector<int> num; //数字vector
vector<char> symbol; //运算符vector
statistics(expr, expr_len, num, symbol); //字符串解析出数字和运算符
del_power(num, symbol); /* 去除乘方 */
int symbol_len = symbol.size();
int* add_sub_num = new int[symbol_len + 1]; //数字长度比运算符多1
char* add_sub_symbol = new char[symbol_len];
int symbol_length = 0;
del_multi(num, symbol, add_sub_num, add_sub_symbol, &symbol_length); /* 去除乘除号 */
result = add_sub_num[0];
for(int iter = 0; iter < symbol_length; ++iter)
{
if('+' == add_sub_symbol[iter])
{
result += add_sub_num[iter + 1];
}
else
{
result -= add_sub_num[iter + 1];
}
}
//cout<<"the result is: "<<result<<endl;
delete[] add_sub_num;
delete[] add_sub_symbol;
return result;
}
/* 解析出字符串中的数字和运算符 */
void statistics(const char* expr, int expr_len, vector<int> &num, vector<char> &symbol)
{
int temp = 0;
for(int expr_element = 0; expr_element < expr_len; expr_element++)
{
if('0' <= expr[expr_element] && expr[expr_element] <= '9')
{
temp = temp * 10 + (expr[expr_element] - '0');
}
if(('+' == expr[expr_element]) || ('-' == expr[expr_element]) || ('*' == expr[expr_element]) || ('/' == expr[expr_element]) || ('^' == expr[expr_element]))
{
num.push_back(temp);
symbol.push_back(expr[expr_element]);
temp = 0;
}
}
num.push_back(temp);
}
/* 去除运算符中的乘号和除号 */
void del_multi(vector<int> num, vector<char> symbol, int* add_sub_num, char* add_sub_symbol, int* symbol_length)
{
int symbol_len = symbol.size();
int len = 0;
int i;
for(i = 0;i < symbol_len; i++)
{
if('*' == symbol[i])
{
num[i + 1] = num[i] * num[i + 1];
}
else if('/' == symbol[i])
{
num[i + 1] = num[i] / num[i + 1];
}
else
{
add_sub_num[len] = num[i];
add_sub_symbol[len] = symbol[i];
len++;
}
}
add_sub_num[len] = num[i];
*symbol_length = len;
}
/* 去除运算符中的乘方符号 */
void del_power(vector<int> &num, vector<char> &symbol)
{
vector<int> del_power_num;
vector<char> del_power_symbol;
int symbol_len = symbol.size();
int i;
for(i = 0; i < symbol_len; i++)
{
if('^' == symbol[i])
{
num[i + 1] = pow(num[i], num[i + 1]);
}
else
{
del_power_num.push_back(num[i]);
del_power_symbol.push_back(symbol[i]);
}
}
del_power_num.push_back(num[i]);
num.assign(del_power_num.begin(),del_power_num.end());
symbol.assign(del_power_symbol.begin(),del_power_symbol.end());
}
int main()
{
cout<<"测试用例:"<<endl;
cout<<"1+2*3+4-5 = "<<calc("1+2*3+4-5")<<endl;
cout<<"3^3*4+6/3 = "<<calc("3^3*4+6/3")<<endl;
cout<<"(3+2)*((3+9)/3) = "<<calc("(3+2)*((3+9)/3)")<<endl;
cout<<"5+6*2/(2+1)-9+2^10 = "<<calc("5+6*2/(2+1)-9+2^10")<<endl;
cout<<"((3-1)*(5-2)+10)/2^3 = "<<calc("((3-1)*(5-2)+10)/2^3")<<endl;
system("pause");
return 0;
}