CDOJ 1074 秋实大哥搞算数(栈_表达式求值)

秋实大哥搞算数

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
秋实大哥大学物理挂科了,于是在下学期的前两周的某一天要悲剧的补考。为了不给学校的挖掘机大楼做贡献,秋实大哥决定在假期里努力复习。当然,良好的计算能力也是非常必要的,毕竟是涉及计算自己做多少分的题能够通过考试的问题。现在他给自己出了一大堆长长的只有涉及整形四则运算式子,然后埋头计算结果。为了检验自己的计算能力,他请你来帮忙。

Input

第一行一个整数T,表示式子的总数。

接下来每一行有一个长度不超过10^6的表达式,只包含正整数和四则运算符号('+', '-', '*', '/')。

保证输入合法。

Output

对于每一个表达式,输出相应的结果,占一行。

保证运算及结果在long long范围以内。

Sample input and output

Sample Input Sample Output
2
12+5/4-1
4*5/3
12
6


首先,思想就是两个栈(后进先出)嘛,一个栈存放运算符,一个栈存放数。怎么用栈呢?

为了方便知道表达式是否结束,在输入了这个表达式后,我又在后面加了一个'='。

最先输入的肯定是数,然后是运算符,因此,就判断:

第一个运算符入栈时,

肯定还不能运算(注意

因为不知道后面的情况。

(一定要切记你的程序里什么时候能运算,什么时候不能运算,要把不能运算的条件都记录下来,因为在读到'='时就准备要输出了,所以在读到等号后要让你的程序把式子都运算完,楼主就是在这WA了好久,当时没有形成严密清晰的思维…嗯,这个习惯不好

第二个运算符运算时,分情况讨论:

如果第二个运算符是*或/,

如果前面的运算符是*或/,则将前面的运算符进行运算

如果用栈的思想来描述就是,上一个运算符出栈(当前这个运算符还没进栈),上两个数出栈,然后进行运算,新得到的数入栈。

否则不进行运算(注意!)。

如果第二个运算符是+或-,

则将前面的运算符运算(栈的思想同上)。

第三个运算符及其以后的情况同第二个运算符

好,我们现在来数数不能运算的情况

首先,按运算符分类,0个运算符的时候,即第一个运算符读到的是'=',特判一下,直接输出第一个数就好。

1个运算符的时候,第二个运算符读到的是'=',即是读到'=',就把前一个运算符运算,然后输出。

2个运算符的时候,如果第二个是+或-,运算后只剩1个运算符,同第二种情况,

如果第二个是*或/,则读到'='时,需要进行两次运算,然后输出。

>=3个运算符时,同2个运算符的情况。

接下来我们来说为什么>=3个运算符的情况同第二个运算符的情况。

首先,如果你当前要入栈的运算符是+或-,则前面的式子的值就可以直接算出来了。

如果你当前入栈的是*或/,则前面的那个是+或-时不运算,前面那个是*或/时就可以运算,因此,最多,你遇到*或/后前面有个+或-,这时,运算符栈中有两个运算符。

也就是说,在你运算的过程中,新的运算符入栈后,栈中存有一个或两个运算符。

因此在+或-运算时,可能会有一次或者两次运算(两次的话,先算后面的乘除,再算前面的加减)。

在读到’=‘时也是同进行+或-的情况。

所以我的代码中(懒得用函数了,直接手写的),有两种运算,只进行一次的运算和进行到栈中只有一个运算符(当前读到的这个运算符入栈了)的运算。


遇到的错误:1,RE,貌似是数据中有空行,嗯,改了输入条件就好了,反正这块很迷,用%s应该就没事哈,不过我加了一个如果当前输入后的字符串的第一个字符还是空,好像并没有什么卵用,%s不会读入空格的啊,反正很迷,不管它了

2,就是我在读到’=‘时只进行了一次计算,然后有可能前面有两个运算符,所以就WA了半天。

3,T了几发,memset给T掉了,memset也不能随便用啊…


AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 1000060
char express[maxn];
char ope[10];
long long num[10];
int main()
{
	int t;
	scanf("%d%*c", &t);
//	cin >> t; getchar();
	while (t--)
	{
//		memset(express, 0, sizeof(express));
		memset(ope, 0, sizeof(ope));
		memset(num, 0, sizeof(num));
		scanf("%s", express);
		if (express[0] == '\0')
		{
			t++; continue;
		}
/*		char ch;
		int len = 0;
		while (1)
		{
			ch = getchar();
			if (ch == '\n')
				break;
			else
			if ((ch >= '0'&&ch <= '9') || ch == '+' || ch == '-' || ch == '*' || ch == '/')
			{
				express[len] = ch; len++;
			}
		}
		if (len == 0)
		{
			t++;
			continue;
		}
*/		
		int n = strlen(express);
		express[n++] = '='; express[n] = '\0';
		long long ans = 0;
		long long n_ope = 0, n_num = 0;
		for (int i = 0; i < n; i++)
		{
			if (express[i] >= '0'&&express[i] <= '9')
			{
				long long temp1, temp2;
				temp1 = num[n_num] * 10;
				temp2 = express[i] - '0';
				num[n_num] = temp1 + temp2;
			}
			else if (express[i] == '+' || express[i] == '-' || express[i] == '*' || express[i] == '/' || express[i] == '=')
			{
				n_num++; ope[n_ope++] = express[i];
				if (n_ope == 1)
				{
					if (ope[n_ope - 1] == '=')
					{
						ans = num[0]; break;
					}
				}
				else if (n_ope>1)
				{
					if (ope[n_ope - 1] == '+' || ope[n_ope - 1] == '-')
					{
						while (n_ope > 1)
						{
							switch (ope[n_ope - 2])
							{
							case'+':
								num[n_num - 2] = num[n_num - 2] + num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'-':
								num[n_num - 2] = num[n_num - 2] - num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'*':
								num[n_num - 2] = num[n_num - 2] * num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'/':
								if (num[n_num - 1] == 0)
								{
									printf("divisor is 0\n");
									return 0;
								}
								num[n_num - 2] = num[n_num - 2] / num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							default:
								break;
							}
						}
					}
					else if (ope[n_ope - 1] == '*' || ope[n_ope - 1] == '/')
					{
						if (ope[n_ope - 2] == '*')
						{
							num[n_num - 2] = num[n_num - 2] * num[n_num - 1];
							ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
							num[n_num - 1] = 0; n_num--;
						}
						else if (ope[n_ope - 2] == '/')
						{
							if (num[n_num - 1] == 0)
							{
								printf("divisor is 0\n");
								return 0;
							}
							num[n_num - 2] = num[n_num - 2] / num[n_num - 1];
							ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
							num[n_num - 1] = 0; n_num--;
						}
					}
					else if (ope[n_ope - 1] == '=')
					{
						while (n_ope > 1)
						{
							switch (ope[n_ope - 2])
							{
							case'+':
								num[n_num - 2] = num[n_num - 2] + num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'-':
								num[n_num - 2] = num[n_num - 2] - num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'*':
								num[n_num - 2] = num[n_num - 2] * num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							case'/':
								if (num[n_num - 1] == 0)
								{
									printf("divisor is 0\n");
									return 0;
								}
								num[n_num - 2] = num[n_num - 2] / num[n_num - 1];
								ope[n_ope - 2] = ope[n_ope - 1]; ope[n_ope - 1] = '\0'; n_ope--;
								num[n_num - 1] = 0; n_num--;
								break;
							default:
								break;
							}
						}
						ans = num[0];
					}
				}
			}
		}
		cout << ans << endl;
	}
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值