C++实现四则运算的由来
有些人可能很奇怪,为什么四则运算要自己写代码,直接cout不就行了吗,其实不然,当我们想写一个程序进行四则运算时,程序接收到的四则运算表达式是string字符串类型,不能直接进行运算,所以要我们自己写代码。
实现四则运算的方法
我们平时见到的四则运算表达式被称为‘‘中缀表达式’’中缀表达式的意思就是运算符在操作数的中间,例如1+1 ,1+2+(3+4),这些都是中缀表达式,这些运算表达式符合我们人类的思考逻辑方式,但是愚蠢的计算机用“后缀表达式”进行运算会更加方便,后缀表达式也被称为逆波兰表式。
中缀表达式 | 后缀表达式 |
a+b | ab+ |
a*b | ab* |
a+b*c | abc*+ |
网上大部分的教程都是一步到位用中缀表达式直接进行运算,利用栈的先进后出的特性设立一个数字栈,一个运算符栈,不过这种一步到位的方法不太适合新手,不利于新手理解,其实在中缀表达式计算的中间还存在有一步,就是中缀表达式先转换为后缀表达式,我们先对这一步的原理进行讲解,最后再一步到位,学习中缀表达式直接运算。
我们首先来学习如何将中缀表达式化为后缀表达式,这里我们要用到栈的力量,
化为后缀表达式我们仅仅需要用到一个栈,运算符栈
首先我们需要了解各种运算符他们的所对应的优先级
运算符的优先级排序
1. (
2. + -
3. * /
4. )
优先级排序从小到大如上所示,下面我们对中缀表达式进行遍历
例:1+(2-3)*4+4/2
首先,当我们遇到数字时直接添加到后缀表达式末尾,
那我们开始了,首先从中缀表达式中拿下来 ‘1’放到后缀表达式末尾
然后把‘+’拿下来,首先判断运算符栈是否为空栈,若为空栈直接入栈,倘若不是空栈, 将其与栈顶元素相比较,若比栈顶元素优先级大,
直接入栈,若比栈顶元素优先级小,或等于栈顶元素优先级,则将栈顶元素出栈
放进后缀表达式中,此处可以判断为空栈,直接入栈
这里忘了说一点,遇到左括号,不用理会优先级,直接入栈,例子这里就直接入栈
接下来遇到“2”,送入后缀表达式 ,然后是"-",因为其比栈顶元素"("优先级高,所以直 接入栈,遇到3,送入后缀表达式,
然后遇到右括号,当我们遇到右括号时,也是一种特殊情况,右括号不用进栈,
而是将运算符栈中的元素从栈顶依次拿出放入后缀表达式中,直到遇到左括号,则将左括号 出栈,操作停止。
得到后缀表达式:123-
然后到“*”这个运算符,计算按照优先级入栈,比栈顶的元素“+”高,入栈,数字送入后缀表达式,“-”比"*"优先级小,则将栈顶的*出栈送入后缀表达式中
后续,就由各位网友自己来完成啦
最后我们得到后缀表达式:1 2 3 - 4* + 4 2 / +
后缀表达式就符合计算机思考的方式,方便我们加下来用程序进行运算。下面来介绍一
下后缀表达式的计算方法。
后缀表达式的计算方法
后缀表达式的计算就相当简单了。准备一个数字栈。从左到右扫描后缀表达式,如果是数字,放入数字栈。如果是符号,从数字栈中弹出两个数字,第一个取出的数字为右运算数,第二个为左运算数,进行运算。然后将结果放进数字栈中。如此反复,直到读完整个表达式后,留在数字栈中的那个数字就是最终结果。
直接通过中缀表达式计算
接下来,就是直接通过中缀表达式进行计算,从前面我们了解到在中缀表达式转化为后缀表达式时用到了 运算符栈,在计算后缀表达式时用到了数字栈,那么直接计算的话,我们就可以通过同时建立两个栈,一个数字栈,一个运算符栈来完成。
下面来展示下相应的C++代码
#include<iostream>
#include<string>
#include<stack>
#include <ctype.h>
#include <stdlib.h>
using namespace std;
int youxianji(char);
void calcutor(string);
int main()
{
string str="1+(2-3)*4+4/2"; //要计算的四则运算表达式
calcutor(str);
}
int youxianji(char op) //优先级判断函数,通过接受字符串内的每个字符进行判断
{
if(op=='(')
return 1;
else if(op=='+'||op=='-')
return 2;
else if(op=='*'||op=='/')
return 3;
//else
//return 4;
}
void calcutor(string str) //计算函数接受字符串
{
stack<double>number; //创建数字栈
stack<char>operator1; //创建字符栈
int i=0,j;
int length=str.size(); //获取字符串长度
string number2; //用来获取字符串中的数字
while(i<length) //首先进行长度判断
{
if(str[i]>='0'&&str[i]<='9') //判断是否为数字
{
j=i;
while(j<length&&str[j]>='0'&&str[j]<='9') //获取后一个运算符之前的所有数字
{
j++;
}
number2=str.substr(i,j-i); //利用了字符串截取函数
number.push(atoi(number2.c_str())); //这里用到了c语言的atoi函数
i=j;
}
/*else if(str[i]=='+'||str[i]=='-'||str[i]=='*'str[i]=='/')
{
if()
}*/
if((operator1.empty()||str[i]=='(')) //当运算符栈为空,或字符为左括号时直接进栈
{
operator1.push(str[i]);
}
else if(str[i]==')') //当字符为右括号时的操作
{
while(operator1.top()!='(') //直到碰到左括号
{
double b,c,d;
b=number.top(); //拿出两个操作数,第一个为右操作数,第二个为左操作数,并弹栈
number.pop();
c=number.top();
number.pop();
if(operator1.top()=='+')
{
d=c+b;
}
else if(operator1.top()=='-')
{
d=c-b;
}
else if(operator1.top()=='*')
{
d=c*b;
}
else if(operator1.top()=='/')
{
d=c/b;
}
number.push(d);
operator1.pop(); //将操作符弹出
}
operator1.pop(); //将左括号弹出
}
else if((str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/')&&(youxianji(operator1.top())<youxianji(str[i]))) //当运算符栈不为空时,先判断字符是否为运算符(其实这一步可以在判断优先级的函数里完成),再判断优先级
{
operator1.push(str[i]);
}
else if((str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/')&&(youxianji(operator1.top())>=youxianji(str[i])))
{
double b,c,d;
b=number.top();
number.pop();
c=number.top();
number.pop();
if(operator1.top()=='+')
{
d=c+b;
}
else if(operator1.top()=='-')
{
d=c-b;
}
else if(operator1.top()=='*')
{
d=c*b;
}
else if(operator1.top()=='/')
{
d=c/b;
}
number.push(d);
operator1.pop();
operator1.push(str[i]);
}
i++;
}
while(!operator1.empty()) //遍历完成后,倘若运算符栈不是空栈,则继续将运算符栈中的运算符一个个弹出,并到数字栈中弹栈进行运算
{
double b,c,d;
b=number.top();
number.pop();
c=number.top();
number.pop();
if(operator1.top()=='+')
{
d=c+b;
}
else if(operator1.top()=='-')
{
d=c-b;
}
else if(operator1.top()=='*')
{
d=c*b;
}
else if(operator1.top()=='/')
{
d=c/b;
}
number.push(d);
operator1.pop();
}
double e,f;
e=number.top();
f=number.size();
cout<<number.top()<<endl;
cout<<f;
}
总结
在截取数字时用到了C语言的atoi函数,所以要使用相应的头文件stdlib.h,并且c++在使用这个函数时给这个函数传参需要用到c_str函数来将c++的string类型转换为字符串指针类型,才能让c语言的函数接受。ctype.h头文件可以不用用到,因为一开始想用isdigit()函数,但是后面发现不可行。
如果大家想让这个程序可以接受用户输入来进行运算,可以自行添加cin等操作,加个while死循环等操作。