洛谷题目如下:
所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。
本题中运算符仅包含 +-*/+-*/。保证对于 // 运算除数不为 0。特别地,其中 // 运算的结果需要向 0 取整(即与 C++ /
运算的规则一致)。
如:3*(5-2)+73*(5-2)+7 对应的后缀表达式为:3.5.2.-*7.+@3.5.2.-*7.+@。在该式中,@
为表达式的结束符号。.
为操作数的结束符号。
输入格式
输入一行一个字符串 s,表示后缀表达式。
输出格式
输出一个整数,表示表达式的值。
输入输出样例
输入 #1复制
3.5.2.-*7.+@
输出 #1复制
16
输入 #2复制
10.28.30./*7.-@
输出 #2复制
-7
说明/提示
数据保证,1≤∣s∣≤50,答案和计算过程中的每一个值的绝对值不超过 10(9)。
本题练习的是栈这一数据结构,操作起来还是有点不太顺手(第一道栈的AC题),而且我if条件写的有些复杂,不是很简短,但是思路还是比较流畅(鬼知道调试了多长时间)
我先将输入的字符串放到字符数组s【】中,然后再细分成了两组,一组是栈,用来存放数字部分,另一组是普通字符数组用来存放运算符,从头开始遍历,因为题目要求严格按照顺序来适用运算符
//存放数字的栈
typedef struct
{
int* top;
int* base;
int stacksize;
} STACKNUM;
//存放运算符的数组
char sign[50]="0";
然后我把先读数,再读符号这一流程称为”一轮“,而一串字符就是由好几轮”小运算“构成的
//说明一轮结束
if((s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/')&&
(s[i+1]!='+'|| s[i + 1] != '-'|| s[i + 1] != '*'|| s[i + 1] != '/'))
{
start=site-start;
now = run(&num, sign,site,start);
start =0;
}
一个运算符要用两个数,所以出栈时要移动两个位置的top指针,然后出栈操作完成后进行运算,用now保存一个小结果重新放入栈中
int run(STACKNUM* num, char* sign, int site,int start)
{
int now;
(*num).top--;
now = *((*num).top);
for (int i = start; i < site; i++)
{
if (sign[i] == '+')
{
((*num).top)--;
now = *((*num).top) + now;
*((*num).top)=now;
}
if (sign[i] == '-')
{
((*num).top)--;
now = *((*num).top) - now;
*((*num).top)=now;
}
if (sign[i]=='*')
{
((*num).top)--;
now = *((*num).top) * now;
*((*num).top)=now;
}
if (sign[i] == '/')
{
((*num).top)--;
now = *((*num).top) / now;
*((*num).top)=now;
}
}
(*num).top++;
return now;
}
(最后要清楚top指针的位置!一定要保证在栈顶!)
完整代码:
#include<stdio.h>
#include<stdlib.h>
//存放数字的栈
typedef struct
{
int* top;
int* base;
int stacksize;
} STACKNUM;
char c[100]="0";
void initnum(STACKNUM* num)
{
(*num).base = (int*)malloc(50*sizeof(int));
(*num).top = (*num).base;
(*num).stacksize = 50;
}
void pushnum(STACKNUM*num,int n)
{
if ((*num).top - (*num).base == (*num).stacksize)
exit(1);
*((*num).top) = n;
(*num).top++;
}
int run(STACKNUM* num, char* sign, int site,int start)
{
int now;
(*num).top--;
now = *((*num).top);
for (int i = start; i < site; i++)
{
if (sign[i] == '+')
{
((*num).top)--;
now = *((*num).top) + now;
*((*num).top)=now;
}
if (sign[i] == '-')
{
((*num).top)--;
now = *((*num).top) - now;
*((*num).top)=now;
}
if (sign[i]=='*')
{
((*num).top)--;
now = *((*num).top) * now;
*((*num).top)=now;
}
if (sign[i] == '/')
{
((*num).top)--;
now = *((*num).top) / now;
*((*num).top)=now;
}
}
(*num).top++;
return now;
}
int main()
{
char s[50]="0";
scanf("%s", s);
int n,now=0;
int site = 0,start=0,w=0;
STACKNUM num;
//存放运算符的数组
char sign[50]="0";
initnum(&num);
for (int i = start; s[i] != '@'; i++)
{
if (s[i]!='.'&&!(s[i] == '+'|| s[i] == '-'|| s[i] == '*'|| s[i] == '/'|| s[i] == '@'))
{
c[i] = s[i];
w++;
}
else if (s[i] == '+'|| s[i] == '-'|| s[i] == '*'|| s[i] == '/'|| s[i] == '@')
{
sign[site] = s[i];
site++;
start++;
}
else if(s[i]=='.')
{
c[i]='\0';
n = atoi(&c[i-w]);
w=0;
pushnum(&num, n);
}
//说明一轮结束
if((s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/')&&
(s[i+1]!='+'|| s[i + 1] != '-'|| s[i + 1] != '*'|| s[i + 1] != '/'))
{
start=site-start;
now = run(&num, sign,site,start);
start =0;
}
}
printf("%d\n",now);
return 0;
}
感觉这次写的思路比较麻烦,暂时想不出更简便的算法,而且修修改改了许多地方可读性比较差
得之后加以优化一下。