秋实大哥搞算数
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;
}