后缀表达式(仅含乘与加)的计算(含C代码),栈
问题描述
给定一个只含加法和乘法的后缀表达式,请计算出它的值。表达式长度<=1000,各结果不超过int范围。
输入第一行包含一个整数T,代表一共有T组测试样例。
每组测试样例占1行,每相邻两项之间由一个空格隔开,最后一项后只有换行符,没有空格。输入保证合理。输出对于每组样例,输出一行(不包含引号)“Case t: ans”,其中t代表样例编号,由1开始,ans是运算的结果。样例输入
2 1 2 + 3 * 4 + 1 1 + 1 1 + *
样例输出
Case 1: 13 Case 2: 4
总论:后缀表达式(仅含乘与加)的计算:首先把问题模块化,可以分解成以下问题:数据的读取,数据的甄别,数据的计算。对于后缀表达式的计算,其思想为从式子中读取字符,遇到数字则压入数字栈,遇到运算符则从栈中取出两个数字计算,再把计算结果压入栈,直到遍历所有字符。
具体实现:首先开辟一个顺序栈,包括数组,栈顶指示top,其次编写入栈,出栈的函数。之后需要判断读入的字符是数字还是运算符(决定入栈还是从栈中取数),编写一个判断数字函数。然后就是计算了,计算函数包含三个参数,两个运算数,一个运算符,分别是数值型和字符型数据。到这里,大体的框架完成了一半,下面是一些具体问题。
具体问题及其处理:
问题1:整体的运算框架问题?
答:读入数据组数,用一个for循环处理多组数据,之后读入字符串,这里用gets函数。计算出长度,再用一个for循环遍历每一个字符,以便运算。
问题2:空格的处理问题?
答:关于空格的处理,这里用了一个if判断和continue语句,一旦是空格则返回++,读取下一个字符。
问题3:如何解决非各位数字的读取问题?
答:这里采用了一个while循环,利用is_number函数判断,连续读入数字字符,也就是说对后缀表达式遍历的进程不仅取决于上层for循环,此处的while循环也会加速遍历进程,这就需要注意上层for循环中的循环变量随while循环次数而增加,这就需要重新开辟一个变量代替for中的循环变量进行++。
问题4:如何解决计算问题?
答:for循环对后缀字符串的遍历内层是一个is_number的判断,问题三是关于数字的问题,此处是关于运算符的问题,如何根据读取的运算符进行运算。注意到,这里的运算符都是双目运算符,也就是意味着需要从数据栈中取出两个数字进行运算,利用计算函数进行计算,注意,一定要把运算结果压入栈中!
问题5:top的初始化问题
注意到,处理完一组数据后,top此时应该为-1,但是为了保险起见,最好还是在第二个for循环之前对top重新初始化。
下边是具体的代码实现。
#include <stdio.h>
#include <string.h>
int stack[1000];
int top = -1;
char read_string[1000];
int is_number(char c)
{
return c >= '0' && c <= '9';
}
void push_stack(int k)
{
stack[++top]=k;
}
int pop_stack()
{
if(top < 0)
{
printf("error");
}
else
{
return stack[top--];
}
}
int calc(int a,int b,char c)
{
if(c=='+')return a+b;
if(c=='*')return a*b;
}
int main()
{
int i,j,k,n,slen,t;
scanf("%d ",&n);
for(i = 1;i <= n;i++)
{
top = -1;
gets(read_string);
slen = strlen(read_string);
for(t = 0;t < slen;t++)
{
if (read_string[t] == ' ') continue;
if(is_number(read_string[t]))
{
j = t;
k = 0;
while(j < slen&&is_number(read_string[j]))
{
k = k*10+(read_string[j]-'0');
j++;
}
t = j-1;
push_stack(k);
}
else
{
int b = pop_stack();
int a = pop_stack();
push_stack(calc(a,b,read_string[t]));
}
}
printf("Case %d: %d\n", i, pop_stack());
}
}

浙公网安备 33010602011771号