题
曾记否,我们小学时,遇到这种四则运算,心情是抓狂的:
输入格式:
输入由若干行组成:
除最后一行之外,每一行是一个长度不超过80的四则运算表达式
最后一行,是一个=字符
输入的所有字符均为英文半角字符,题目保证给定的表达式是正确的,不需要做有效性检查,题目保证所有运算数的长度(含小数点)均不超过5位,运算的中间结果和最终结果的绝对值均不超过100000
输出格式:
对输入的每个表达式,在一行中给出运算结果,保留1位小数。
输入样例:
1
1+2
3-3.8
1.32*(4+(-2))
=
输出样例:
1.0
3.0
-0.8
2.6
代码
#include <math.h>
#include <iostream>
#include <stack>//栈
#include <stdio.h>
using namespace std;
bool shuzi(char a)
{
return (a <= '9' && a >= '0')||(a=='.');//判断字符串中的字符是不是数字
}
int fd(char a)
{
//判断优先级
if (a == '*' || a == '/')
return 3;
else if (a == '+' || a == '-')
return 2;
else if (a == '@')
return -1;
else if (a == '(')
return 1;
else if (a == ')')
return 4;
}
double cla(double a, double b, char chart)
{
switch (chart)
{
case '*':
return a * b;
case '/':
return a / b;
case '+':
return a + b;
case '-':
return a - b;
default:
break;
}
}
double claee(string instr)
{
//先将运算式子转化成后缀表达式,将数据两端将加上#
//遇到数字直接转化,遇到运算符需要判断优先顺序
stack<char> ops;
//放置运算符的栈,栈底放置@
ops.push('@');
string hstr = "";//初始化
//hstr储存后缀表达式
int n = instr.length();
int t=0;
for (int i = 0; i < n; i++)
{
//1+(-2)负号要和2在一起,-2+1负号要和2在一起,2-(+7)正号要和7在一起
if((i==0&&(instr[i]=='+'||instr[i]=='-'))||((!shuzi(instr[i - 1]))&&(!shuzi(instr[i]))&&instr[i-1]!=')'&&instr[i]!='('&&instr[i]!=')'))
{
hstr += '#';
hstr += instr[i];
t=1;//标记此时我们确定的数字前面已经加了#
}
else if (shuzi(instr[i]))
{
//添加数字前的#
if(i==0)hstr += '#';
if (i > 0 && !shuzi(instr[i - 1])&&t==0)
hstr += '#';
//直接加入后缀表达式中
hstr += instr[i];
t=0;
//添加数字后的#
if (i < n-1 && !shuzi(instr[i + 1]))
hstr += '#';
if (i == n - 1)
hstr += '#';
}
else
{
if (instr[i] == '(')
ops.push(instr[i]);
else if (instr[i] == ')')
{
while (ops.top() != '(')//把'('后的运算符放进后缀表达式里
{
hstr += ops.top();
ops.pop();
}
ops.pop();
}
else
{
while (fd(instr[i]) <= fd(ops.top()))//栈顶要放整个栈中最高级的运算符(有且只有一个)
{
hstr += ops.top();//把要比instr[i]高级或同等级的运算符放进后最表达式里,
ops.pop();//然后在栈中删掉他
}
ops.push(instr[i]);
}
}
}
while (ops.top() != '@')
{
hstr += ops.top();
ops.pop();
}
//如 1.32*(4+(-2)) 在hstr中: #1.32##4##-2#+*--->1.32*(4+(-2)),栈后入先出先-2 和 4相加
int n2 = hstr.length();
int i = 0;
int k=0,u=0;
bool isd = false;
double num = 0;
stack<double> stn;
while (i < n2)
{
if (hstr[i] == '#')
{
if (isd) //遇到数字的后一个#
{
k=0;
if(u)
num=0-num;
u=0;
stn.push(num);
num = 0;
isd = false;
}
else isd = true;//遇到数字的前一个#
}
else if(isd&&(!shuzi(hstr[i])))
{
if(hstr[i]=='-')//有可能遇到'-',如#-2#,如果是'+',不用管,不影响答案,判断一下
u=1;
}
else if (shuzi(hstr[i]))
{
if(hstr[i]=='.')//判断是否为小数
{
k=1;
i++;
continue;
}
if(!k)//整数部分
{
num *= 10;
num += (hstr[i] - '0');
}
else//小数部分
{
num+=(double)(hstr[i] - '0')/(1.0*pow(10,k));
k++;
}
}
else//遇到运算符进来
{
double a = stn.top();//栈,后入先出
stn.pop();
double b = stn.top();
stn.pop();
double temp = cla(b, a, hstr[i]);
stn.push(temp);
}
i++;
}
double ans = stn.top();
return ans;
}
int main()
{
string instr;
while (cin>>instr)
{
if(instr=="=")
break;
double sum=claee(instr);
printf("%.1lf\n",sum);
}
return 0;
}