2015上机笔试题-火星计算器

题目描述:

自定义运算符 @,#,$,&,并且优先级@>#>$>&,利用下面的计算法则,计算出一个给定的字符串表示的表达式的值,返回整型结果。

x@y = (x-1)*(y+1);
x#y = (2*x+5)*(3*y+60)
x$y = (x+1)*(2*x+3)*(y-1)*(2*y-3)
x&y = ((x+y+1)*(y-9)+(x+7)/(y-8))

输入:接受多行输入,每行可能有空格。题目保证不会出现除数为0的情况,且所有操作数都是整数。为了简单起见,表达式不含有括号。
输出:对于每一行输入,输出一个运算结果。

输入样例:

1@2
1#2
1@1@1
1#1#1
1$1$1
1&1&1
1#1@1
1@1#1
1$1&1
1&1$1
1  #   1  &       1
12 @        12
123    @   123

输出样例:

0
462 
-2
55881
0
186
420
315
-17
-19
-3608
143
15128

分析:关于计算器一类题目,一般借助于栈来进行处理,同时要注意运算符的优先级。此题中没有括号,很大程度上简化了实现难度。测试运算表达式中没有等号,因此可以添加一个等号作为运算结束标志。且设置等号的优先级比题目所给的所有运算符的优先级都低。
首先,定义两个栈,栈operater,用于存放运算符(char型),将'='压入栈底;栈num,用于存放操作数(整型)。
然后每个运算表达式串s,先在最后添加一个'=',然后从前往后遍历,跳过空格:
      1)如果当前字符和栈operater的栈顶运算符都为‘=’,且num中只有一个元素,那么运算结束,返回num中的栈顶元素。
      2)如果字符是数字,此时下标为i1,那么继续下一个字符,直到当前字符不是数字为止,记此时下标为i2,这时,将[i1,i2)之间的数字字符转换为整型,压入栈num;
      3)如果遇到的字符是运算符:若栈operator的栈顶运算符优先级不低于当前运算符,那么从num的依次次弹出两个整数,与栈operator的栈顶运算符进行
运算,将结果压入栈num中,然后继续处理当前运算符;否则,直接将当前运算符压入栈operator中,接着处理s的下一个字符。

以下是个人理解后写的完整c++代码,欢迎指正:


#include<iostream>
#include<stack>
#include<string>

using namespace std;

static string oper = "@#$&="; /*按照优先级高低,将运算符存放入一个静态字符串内,用于判断两个字符的优先级高低*/
class MarsCal
{
public:
	bool isOperator(char ch)   /*判断字符ch是否为运算符*/
	{
		if(oper.find(ch) != oper.npos )
		{	
			//cout << "true :" << oper.find(ch) << endl;
			return true;
		}
		else
		{
			//cout << "false:" << ch << endl;
			return false;
		}
	}

	char precede(char th1,char th2) /*判断两个运算符的优先级,>表示th1的优先级不低于th2的优先级*/
	{
		if(oper.find(th1) < oper.find(th2) || oper.find(th1) == oper.find(th2))
			return '>';
		else
			return '<';
	}
	
	int operate(int a,char op,int b)  /*进行 a op b 的运算*/
	{
		if(op == '@')
			return (a-1)*(b+1);
		else if(op == '#')
			return (2*a+5)*(3*b+60);
		else if(op == '$')
			return (a+1)*(2*a+3)*(b-1)*(2*b-3);
		else if(op == '&')
			return ((a+b+1)*(b-9)+(a+7)/(b-8));
		else
			return -1;
	}

	void getTwo(stack<int> &num,int &left,int &right) /*从num中获取两个操作数,注意左右和出栈顺序*/
	{
		right = num.top(); /*先出栈的为右操作数*/
		num.pop();
		left = num.top();
		num.pop();
	}
	int cal(string s)  /*计算运算表达式s*/
	{
		s.push_back('=');
		int re = 0;
		stack<char> operater;
		stack<int> num;
		operater.push('=');
		char optrTop;
		for(string::size_type i = 0;i != s.size();)
		{
			if(s[i] == ' ')   /*跳过空格*/
			{
				i++;
				continue;
			}
			optrTop = operater.top();
			if(s[i] == '=' && optrTop == '=')  /*运算结束条件*/
			{
				//cout <<"optTop: "<< optrTop <<endl;
				if(num.size()==1)
					re = num.top();
				break;
			}
			if(isOperator(s[i])) /*处理操作符*/
			{				
				if(!operater.empty())
				{		
					//cout <<"optTop  s[" << i << "] :" << optrTop<< " " << s[i]<< endl;
					char prio = precede(optrTop,s[i]);
					if(prio == '>')
					{
						int left ,right;
						getTwo(num,left,right);
						char theta = operater.top();
						operater.pop();
						//	cout <<"operater pop :" <<theta << endl;
						num.push((operate(left,theta,right)));
						//cout <<"num push :" << operate(left,theta,right) << endl;
						
					}
					else
					{
						operater.push(s[i]);
						i++;
						//cout <<"operater push :" << s[i]<< endl;
					}	
				}
			} 
			else /*处理操作数,考虑到多位整数,需要遍历到不为数字的字符为止*/
			{
				int tmp = 0; 
				while(s[i] != ' ' && !isOperator(s[i]) && i != s.size())
				{
					tmp = tmp * 10 + (s[i]-'0');
					i++;
				}
				num.push(tmp);
				//cout <<"num push :" << tmp<< endl;
			}
		}
		//cout << num.size()<< endl;	
	return re;
	}
};

int main (void)
{
	MarsCal marscal;
	string str = "";
	while(getline(cin,str)) /*该函数能接受含有空格的字符串*/
	{
		cout << marscal.cal(str) << endl;
	}
	system("pause");
	return 0;
}   


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值