您的位置:首页 > 其它

第四次作业

2016-04-13 16:48 232 查看
github链接地址

问题分析

算式计算(注意优先级与负数)

命令行输入输出

计算

看了题目本来是一头雾水,后来看了大神推荐的前缀中缀后缀表达式才有了头绪,先转换,后计算。他人思路如下:

转换思路:将优先级高的运算甩在前面,同级先出现在前面。

具体实现:以后缀表达式为例。
1.初始化栈1(存储后缀表达式),栈2(运算符的中转站),从左到右扫描算式。
2.数字直接进1。
3.运算符进2,但是符号进去之前判断优先级.
3-1.如果栈里面高或者**相等**就弹出并压入1,继续比较。这样在表达式中优先级高的符号先出现,先运算。同级先出现,先进表达式。
3-2.如果栈为空,或者栈顶元素优先级或者为“(”,直接进2。
4.括号进2。
4-1.“(”直接进2。
4-2.“)”出现要把它们之间运算符全部弹出并进1,这样括号里面的运算也先进表达式,括号任务完成,可以不要了。
5.表达式扫描完以后,将2内元素依次弹出并压入1

计算方法:扫描后缀表达式(先进先扫)。
1.遇见数字进栈。
2.遇见运算符就把栈前两个元素拉出来运算,结果再进栈。
最后栈顶元素即为所得算式结果

举个例子 `1+2*(3+4)-5` 。后缀表达式:(栈底到栈顶)`1 2 3 4 + * + 5 - `按照运算规则就是`1+2*(3+4)-5`

接下来是自己的(对负数处理)

1.因为Scan得到的是队列,正好从左到右,所以选择转换成后缀

2.选择用队列而不是栈来存储后缀表达式,因为转换的时候只进不出而最后计算需要先进先扫,毫无疑问,队列更合适

3.想了下,出现负数有两种情况。
3-1.在算式开头,运算时把0压进栈,这样计算-a就相当于0-a。
3-2.在左括号右边,这样在输入“(”时,加一个判断,如果下一个元素为“-”,就把0压进后缀表达式。

代码

转换成后缀表达式
void Calculation::trans(queue<string>*s)
{
string c;

while (s->empty() == false)
{

//读取队列第一个元素
c = s->front();

//c为运算符时,先判断优先级,低活着平级先将栈顶元素弹出,再与新的栈顶元素比较,直到高于或者栈空或者“(”进入
if (c == "*" || c == "/")
{
while (sign.empty() == false && (sign.top() == "*" || sign.top() == "/"))
{
after.push(sign.top());
sign.pop();
}
sign.push(c);
s->pop();
}

if (c == "+" || c == "-")
{
while (sign.empty() == false && (sign.top() == "+" || sign.top() == "-" || sign.top() == "*" || sign.top() == "/"))
{
after.push(sign.top());
sign.pop();
}
sign.push(c);
s->pop();
}

//为括号时
if (c == "(")
{
//判断下一个元素是否为“-”是的话说明下个数是负数,后缀表达式压入0
sign.push(c);

s->pop();
if (s->front() == "-")
{
after.push("0");
}

}
//将括号间运算符弹出并压入后缀表达式,括号舍弃
if (c == ")")
{
while (sign.top() != "(")
{
after.push(sign.top());
sign.pop();
}
sign.pop();
s->pop();
}

//数字直接进栈
else if (isdigit(c[0]))
{
after.push(c);
s->pop();
}

}

//运算符全部进后缀表达式
while (sign.empty() == false)
{
after.push(sign.top());
sign.pop();
}
}

计算后缀表达式

double Calculation::count()
{
string c;
stringstream ss;

num.push(0);//考虑第一个数为负数
while (after.empty() == false)
{
double flag = 0;//存每次栈顶元素与下个元素运算结果
c = after.front();

//为运算符就把前两个元素弹出来参与运算,并将结果存入栈中
if (c == "+")
{
double a = num.top();
num.pop();
double b = num.top();
num.pop();
flag = b + a;
num.push(flag);
}

if (c == "-")
{
double a = num.top();
num.pop();
double b = num.top();
num.pop();
flag = b - a;
num.push(flag);
}

if (c == "*")
{
double a = num.top();
num.pop();
double b = num.top();
num.pop();
flag = b*a;
num.push(flag);
}

if (c == "/")
{
double a = num.top();
num.pop();
double b = num.top();
num.pop();
flag = b / a;
num.push(flag);
}

//数字直接存入栈中
else if (isdigit(c[0]))
{
double temp;
ss << c;
ss >> temp;
num.push(temp);
ss.clear();
}
after.pop();
}
//栈顶元素为最终运算结果
return num.top();
}

命令行

怎么说呢,现在还不是太懂,而且它坑了我很久,一开始运行了是这样的



之后我怎么改代码都没用,后来无意间少写了一句,运行之后还是输出了结果,我就知道不是代码的问题,我就重新建了一个项目,最后成功输出了,截屏如下:



意外状况

一开始写完代码传参直接归0。。。后来大神自愿接过这个烂摊子,先不传参,把代码理了理,其中左右括号一个中文输入,一个英文输入,这样的错误让我觉得很对不住他。但是运算结果还是有很多不正确,他就告诉我检查时把计算和转换分开检查,然后我就辛劳的开工了

由于看资料时把别人的话看漏了,就是转换成后缀,判断优先级,同级也要弹出。结果还以为别人的错了,自己有劳心劳力的把减法全部变成加上一个负数,除法变成乘上他的倒数,最后还是悻悻的改回来
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: