设计简单的计算器-浙大2006年机试,参考王道机试指南

题目描述:
读入一个只包含+ - * /的非负整数计算表达式,计算该表达式的值
输入:
包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格隔开,没有非法表达式。当一行中只有0输入时结束,相应的结果不要输出
输出:对每个测试用例输出一行,即该表达式的值,精确到小数点后2位
样例输入:
1+2
4+2*5-7/11
0
样例输出:
3.00
13.36

//简单的计算器
/*读入一个只包含+,-*,/的非负整数计算表达式,计算该表达式的值*/
/*
样例输入:
1+2
4+2*5-7/11
0
样例输出:
3.00
13.36 
*/ 
#include<stdio.h>
#include<stack>
using namespace std;
char str[220];
 //定义优先级矩阵 
 int mat[][5]={//表达式首尾标记符为0号,+为1号,-为2号,*为3号,/为4号 
  //0,+,-,*,/ 
	1,0,0,0,0,//若mat[i][j]==1,则表示i号运算费用优先级大于j号运算符,=0则为小于j运算符。因为按照先后顺序来的,所以不可能有相等优先级 
 	1,0,0,0,0,//如果符号相同肯定是先遇到的优先级高,现在规定行下标先遇到,列下标的后遇到 
 	1,0,0,0,0,
 	1,1,1,0,0,
 	1,1,1,0,0,
 
 };
 stack<int> op;		//运算符栈,直接保存 
 stack<int> in;		//数字栈
 void getop(bool &reto,int &retn,int &i){//获得表达式下一个元素的函数。如若reto为true,则表示是一个运算符,其编号放在retn中;否则,表示该元素为一个数字,其值保存在retn中。引用变量表示遍历到的字符串下标 
 	if(i==0 && op.empty()==true){
	 	//若此时是字符串第一个字符,且运算符栈为空,我们人为添加编号为0的标记字符
		 reto=true;
		 retn=0;
		 return; 
	 } 
	 if(str[i]==0){//若此时遍历字符串为空字符串,则表示字符串已经被遍历完 
	 	reto=true;	//	返回为运算符
		 retn=0;	//编号为0的标记字符
		 return; 
	 }
	 if(str[i]>='0'&&str[i]<='9'){
	 	reto=flase;
	 	retn=0;	//返回结果为数字串的数值,需要计算,赋初值为0 
	 	for(;str[i]!=' '&&str[i]!=0;i++){
	 		//若字符串未被遍历完,且下一个 不是空格该,则依次遍历其后数字,并计算当前连续数字字符表示的数值
		 	retn*=10;
		 	retn+=str[i]-'0'; //取得某一个数字字符的数值 
	 	}
		 return; 
	 }
	 else {
	 	reto=true;//否则返回运算符 
	 	if(str[i]=='+'){
		 	//	加号返回1
			 retn=1; 
		 } 
		 else if(str[i]=='-'){
		 	retn=2;
		 }
		 else if(str[i]=='*'){
		 	retn=3;
		 }
		 else if(str[i]=='/'){
		 	retn=4;
		 }
		 i+=2;		//i递增,并且直接跳转2,因为后面肯定是一个空格
		 return;		//这个字符读取完成 
	 }
	 if(str[i]==' ') i++;
	 	//	说明字符串还没有遍历结束,应当继续遍历
		//加1,跳过该空格 
	 return; 
}

int main(){
	while(gets(str)){//输入字符串,当其位于文件尾时,gets()返回0
	if(str[0]=='0'&&str[1]=0) break;
	bool retop;
	int retnm;	//定义函数所需要的引用遍历
	int idx=0;	//定义遍历到的字符串下标,初始值为0
	while(!op.empty()) op.pop();	//两个栈在每次开始读取字符时清空 
	while(!op.empty())	op.pop();
	
	while(true){
		getOp(retop,retnum,idx);	//	获取表达式的下一个元素,这样的话每次最后都要重置 
		if(retop==false)	//若该元素是数字
			in.push((double)retnum); 
		else{	//否则为符号 
			double tmp;
			//如果是符号,那么是压栈还是出栈计算呢 
			if(op.empty()==true||mat[retnum][op.top()]==1){		//空栈或当前获取符号优先级比栈顶的优先级高	
				op.push(retnum);	//压栈 
			}
			else {	//当前获得符号比栈顶优先级低,必须出栈计算
				while(mat[retnum][op.pop()]==0){	//	只要当前运算符优先级小于栈顶元素,则重复循环.直到跳出出栈计算的循环,还要把当前读取的符号入栈 
					int ret=op.top();	//	保存栈顶运算符
					op.pop();	//弹出
					double a=in.top();
					in.pop()
					double b=in.top();
					in.pop();
						//从数字栈中弹出两个数字,依次保存在遍历a,b中
					if(ret==1) tmp=a+b;
					else if(ret==2) tmp=a-b;
					else if(ret==3) tmp=a*b;
					else  tmp=a/b;
					
					in.push(tmp);//记得要把结果压栈 
				}
				op.push(retnum);	//记得要把本次读取的运算符入栈 
			}	
		}
		if(op.size()==2 && op.top()==0)break;
		//若运算符堆栈只有两元素,且其栈顶元素为标记运算符,则表达式求值结束 
	}
	printf("%.2f\n",in.top());
	in.pop();
	}
	return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值