-
题目描述:
-
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
-
输入:
-
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
-
输出:
-
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
-
样例输入:
-
1 + 2 4 + 2 * 5 - 7 / 11 0
-
样例输出:
-
3.00 13.36
#include "stdafx.h"
#include <stack>
using namespace std;
char str[220];
int mat[][5]={
1,0,0,0,0,
1,0,0,0,0,
1,0,0,0,0,
1,1,1,0,0,
1,1,1,0,0,
};
stack<int> op;
stack<double> in;
void getOp(bool &reto,int &retn,int &i){
//获得表达式中下个元素函数,若函数运行结束的时候,引用变量reto为true,表示元素为一个运算符,编号保存在retn中。
//否则,为数字,值保存在retn中。
if(i==0&&op.empty()==true){//第一个字符,人为添加为0的标记字符。注意,第一次执行后,该标记字符入栈了,op不为空了,后面不会再执行了。
//该标记字符用于循环的退出,由于是标记字符强行添加的,所以不用i++
reto=true;
retn=0;
return;
}
if(str[i]==0){//遍历完毕。
reto=true;
retn=0;
return;
}
if(str[i]>='0'&&str[i]<='9'){//当前为数字
reto=false;
}
else//运算符
{
reto=true;
if(str[i]=='+')retn=1;
if(str[i]=='-') retn=2; if(str[i]=='*') retn=3; if(str[i]=='/') retn=4;
i+=2;//i递增,跳过该运算符和后面的空格
return;}
retn=0;//计算数字
for(;str[i]!=' '&&str[i]!=0;i++){//读出连续的数字,并使i的下标前进
retn*=10;
retn+=str[i]-'0';//减去0的ascii码,得到数字。
}
if(str[i]==' ')i++;return;//i递增+1;
}
int main(){
while(gets(str)){
if(str[0]=='0'&&str[1]==0)break;
bool retop; int retnum;
int idx=0;
while(!op.empty()) op.pop();
while (!in.empty()) in.pop();//清空栈
while (true)
{
getOp(retop,retnum,idx);//获得运算符和值
if(!retop) in.push((double)retnum);//数字直接压入数字栈k
else
{
double tmp;
if(op.empty()==true||mat[retnum][op.top()]==1) op.push(retnum);//满足入栈条件,压入op栈
else
{//不满足,取栈顶元素与数字栈的两个数字运算,将值压入数字栈中;
while (mat[retnum][op.top()]==0)
{
int ret=op.top();
op.pop();
double a=in.top();in.pop();
double b=in.top();in.pop();
if(ret==1) tmp=a+b;
if(ret==2) tmp=b-a;
if(ret==3) tmp=a*b;
if(ret==4) tmp=b/a;
in.push(tmp);
}
op.push(retnum);
}
}
if(op.size()==2&&op.top()==0) break;
}
printf("%.2lf\n",in.top());
}
return 0;
}
引用的作用是给一个变量起一个别名,例如有一个变量a,想给他起一个别名b,可以写成:int a; int &b=a;
这样声明后,代表a和b就是同一变量单元,而&不是代表取地址符号,而是引用声明符,说明定义了b可并没有为它另开辟内存单元,b和a就是同一变量。
在声明一个引用型变量时,必须同时为它初始化,即声明它代表哪一个变量,在声明一个变量的引用后,在本函数执行期间,该引用一直与其代表的变量相联系,不能再作为其他变量的别名。下面举个不对的例子:
int a;
int b;
int &c=a;int &c=b;
这样企图让C既是A又是B的别名是不对的。
引用的出现主要是把它作为函数参数,以扩充函数传递数据的功能。用传递变量别名的方法实现函数传递数据。下面举个例子:
#include "iostream.h"
void swap(int &a,int &b)
{
int temp;
temp=a;
a=b;
b=temp;
}
void main()
{
int i=3,j=5;
swap(i,j);
cout<<"i=";
cout<<i;
cout<<"j=";
cout<<j;
}
ps:上交10年的机试题没有要求有空格,那么只需要修改
void getOp(bool &reto,int &retn,int &i){
//获得表达式中下个元素函数,若函数运行结束的时候,引用变量reto为true,表示元素为一个运算符,编号保存在retn中。
//否则,为数字,值保存在retn中。
if(i==0&&op.empty()==true){//第一个字符。
reto=true;
retn=0;
return;
}
if(str[i]==0){//遍历完毕。
reto=true;
retn=0;
return;
}
if(str[i]>='0'&&str[i]<='9'){//当前为数字
reto=false;
}
else//运算符
{
reto=true;
if(str[i]=='+')retn=1;
if(str[i]=='-') retn=2; if(str[i]=='*') retn=3; if(str[i]=='/') retn=4;
i++;//i变为递增1
return;}
retn=0;//计算数字
for(;str[i]>='1 '&&str[i]!=0;i++){//读出连续的数字,并使i的下标前进 判断语句为>='1' 运算字符的asic码小于数字的
retn*=10;
retn+=str[i]-'0';//减去0的ascii码,得到数字。
}
if(str[i]==' ')i++;return;//i递增+1;
}