题解 | #表达式求值#
表达式求值
http://www.nowcoder.com/practice/9566499a2e1546c0a257e885dfdbf30d
抄的大佬的答案。
总体思路就是将表达式化为若干项的和。
即将带正号的加数本身入栈。
将带负号的加数的相反数入栈。
将带乘号的元素与乘号后的元素求积后入栈。
将带乘号的元素与除号后的元素求商后入栈。
再将栈中所有的元素求和。
此中用数组模拟栈,缺点是要控制索引。
也可以用入栈出栈相关函数代替。
但是再调试时出现未知错误使元素无法写入栈中,故而用数组模拟。
值得关注的是初始计算操作的设定、负号的处理和括号的处理。
初始计算操作设为“加”。
因为第一个元素有可能是负数,故而在子函数开始的第一步就判断是否有负号。
如果有负号,则将操作负设置为“减”,后边将相反数入栈。
如果是乘号,只影响其后面的元素,让该元素与前面元素相乘。
括号的处理则是迭代一个函数,越过括号之后再进行一个新的循环,将括号里的内容计算完毕后将其最终值入栈,入栈的位置是stack[i],其中i为加号的个数。
迭代也在循环之中,因此与单片机中断十分相似。
在被迭代的函数中,虽然开辟了两个相同名称的储存空间,但不会占用同一块内存。所以无需担心数据被覆盖。
i是控制字符串的指针的重要标志,因此无论多少次迭代,i始终只能单向变化。
因此i赋初值只能在子函数之外,否则每迭代一次i都将从初值位置开始,会将指针指向错误的位置并使循环无法结束。
注意求每次子函数求和时的索引要另辟新变量,不要重复用指针的标志i,也会导致指针指向错误位置。
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
int i=0;
int trans(char *s)//取加数
{
int stack[100];
int len;
int top=-1;
char flag='+';
int val;
int asb;
len=strlen(s);
while(i<=len)
{
int num=0;
if(*(s+i)=='-')//第一位是负数的情况
{
flag='-';
i++;
}
if(*(s+i)=='(')
{
i++;
num=trans(s);
}
while((*(s+i)-'0'>=0)&&(*(s+i)-'0'<=9))
{
num=num*10+(*(s+i)-'0');//将字符型转换为整型,算超过一位的数字需要多次
i++;
// count++;
}
switch(flag)
{
case'+':
{
stack[++top]=num;
// stack_push(stack,num);
break;
}
case'-':
{
//stack_push(stack,(-1)*num);
stack[++top]=(-1)*num;
break;
}
case'*':
{
// asb=stack_pop(stack);//第一步flag默认为‘+’,因此不必担心取空
//stack_push(stack,asb*num);
stack[top] *= num;
break;
}
case'/':
{
//asb=stack_pop(stack);
//stack_push(stack,asb/num);
stack[top] /= num;
break;
}
}
flag=*(s+i);//取下一个符号
if (*(s+i) == ')')
{
i++;
break;
}
i++;
}
int sum=0;
for(int j=0;j<=top;j++)
{
sum=sum+stack[j];
}
return sum;
}
int main()
{
int award;
//int count=0;
char *s;
s=(int*)malloc(sizeof(int));
scanf("%s\n",s);
award=trans(s);
printf("%d",award);
}