中缀表达式求值值问题

很多新手对于C的表达式求值(如i++ + ++i)这一问题感到十分的疑惑,不能很好地理解,今日小轩献丑,准备为新手们解释一下,如有不通之处,请各位同道指出。
首先,贴上裘老的解释:http://bbs.csdn.net/topics/
其次,是小轩认为要掌握这个问题需要的一些基础知识:
1.变量的访问种类与副作用的产生
在程序设计中经常用到“数”这一概念,在程序设计语言中,“数”被抽象为“量”,在C语言中,“量”分为“变量”和“常量”两种。其中与变量相关的内容较多,主要为访问类型和属性两大类(本文解释表达式求值问题,此问题与变量的属性无过多牵连,所以会在另外一篇文章中向大家介绍变量的属性)。C语言中访问类型有两种:透明引用和真引用;透明引用指不产生副作用的访问,而真引用与之恰好相反,指产生副作用的访问。
那么,什么是副作用呢?副作用指编译器系统对一个变量实行的数值改变的过程,简单来说,就是改变一个变量的数值。
第一个基础知识介绍完了,现在举个例子说明一下:
printf(&%d&,a+1);这里编译器对变量a的访问属于透明引用,没有修改变量a的值(即没有产生副作用)
if(++a) a=0;7 这里的对变量a的两个访问都属于真引用,都修改了变量a的值(即都产生了副作用)
2.序列点的定义,作用及其存在位置
序列点,也称顺序点,对于编译器系统而言,它是一个瞬间,一个在此序列点之前的全部的副作用都必须要实现的瞬间,也就是说,编译器系统处理到存在序列点的地方时,前面的所有副作用都已产生(即被真引用的变量都已改变它的数值),序列点存在的意义是为了保证编译工作的有序性和有效性。
有序性:多个不同的序列点的存在使源程序中处于不同序列点之间并被多次真引用的变量的副作用的产生有序化。
有效性:序列点的存在可以使编译器各模块之间相互通信,序列点就是他们的通信方式,可以保证编译器各模块工作的有效性。
那么,都什么地方存在序列点呢?C FAQs中明确写道:
1.完整表达式(表达式语句或不为任何其他表达式的子表达式的表达式)的尾部,即“;”处
2.“||”、“&&”、“?:”或逗号操作符处
3.函数调用处(参数求值完毕,函数被实际调用之前)
关于序列点的基础知识就这么多,现在让我们看几个例子:
a=1;本例中有一个序列点,位于结束符处,有一个副作用,在唯一的序列点之前有效。
a=1,b=2,c=3;本例中有三个序列点,分别位于两个逗号操作符处和结束符处,变量a的副作用在第一个序列点之前有效,变量b的副作用在第二个序列点之前,第一个序列点之后有效,变量c的副作用在第二个序列点之后,第三个序列点之前有效。
if(a==1 && ++b&0)本例中有两个序列点,分别位于&&&&处和语句结束符处(由于if语句的特殊性,没有结束符,但if内的表达式是一个完整表达式,所以也存在序列点),变量a被透明引用,没有产生副作用,即第一个序列点之前没有副作用产生,变量b被真引用,在第一个序列点之后,第二个序列点之前实现其副作用。
printf(&%d&,a);本例中有两个序列点,分别位于函数调用处和结束符处(函数中的“,”是分隔符,用来分割参数,不是逗号操作符),两个序列点之前及其相对应的序列点之后均没有副作用
a=0xffffffff,a++,c=malloc(a),*c=1;& & & & & & & & 本例中有五个序列点,分别位于三个逗号操作符处、函数调用处和结束符处,变量a的第一个副作用在第一个序列点之前有效,第二个副作用在第一个序列点之后,第二个序列点之前有效,变量c的第一个副作用在第二个序列点之后,第三个序列点(第三个序列点是函数表达式内的那个)之前有效,第三个序列点与第四个序列点之间没有副作用,变量c的第二个副作用在地四个序列点之后,第五个序列点之前有效。
3.对于前缀运算和后缀运算的解释
前缀运算,主要包括前缀自增运算(++i)和前缀自减运算(--i),相对应的,后缀运算主要包括后缀自增运算(i++)和后缀自减运算(i--)。
前缀运算与后缀运算的差别主要在于其副作用实现依据的序列点的不同。
前缀运算的副作用在本句结束符处的序列点之前有效,而后缀运算的副作用在本句结束符处的序列点之后有效。
a++;本例中有一个副作用和一个序列点,其中副作用由后缀运算产生,所以在本句结束之前,变量a的值都不改变,在本句结束之后,变量a的值改变。
--a;本例中有一个副作用和一个序列点,其中副作用由前缀运算产生,所以在本句结束之前,变量a的值就已经改变。
4.C语言一个重要的规则
ANSI/ISO C标准中有这样的描述:在上一个和下一个序列点之间,一个对象所保存的值至多只能被表达式的求值修改一次,而且只有在确定将要保存的值的时候才能访问前一个值。
我做具体解释如下:
在上一个和下一个序列点之间指的就是相邻的两个序列点,一个对象所保存的值至多只能被表达式求值修改一次指的是一个变量的值只能修改一次,只有在确定将要保存的值的时候才能访问前一个值指的是将要用来计算表达式计算的每个变量的值都应该是确定的;整合化简后,可以改述为:在两个相邻的序列点之间,对于同一个变量只能进行一次真引用。
现举例如下:
a=1,b=2,a=b;本例中有三个序列点和副作用,且相邻序列点之间对同一变量进行真引用的次数没有超过一次,所以本表达式合法。
a=a+1;本例中有一个序列点和一个副作用,变量a在寻列点之间出现两次,但对变量a的真引用的次数只有一次,没有违反我们刚才的规则,所以本表达式同样合法。
a[b=2]=++b;本例中有一个序列点和两个副作用,变量b的第一个副作用对变量b就行了一次真引用,就变量b的值修改为2,变量b的第二个副作用源自于前缀自增表达式,两个副作用都在同两个序列点之间,所以编译器不知道是先进行第一个副作用还是先进行第二个副作用了,所以就有了四种结果(a[2]=2、a[2]=3、a[3]=2、a[3]=3)了,这是我们不希望看到的,所以本表达式不合法。
a[b=2]=b--;本例中有两个序列点和两个副作用,但是变量b的第二个副租用源自于后缀运算,这个副作用在本句结束符处的序列点之后有效,所以本句还可以解释为a[2]=2,b=1;这样的表达式符合我们的规则,所以本表达式合法。
注:我这里指的表达式不合法不是说表达式不能通过编译器的编译,指的是可以通过编译但结果未知(就像a[b=2]=++b这个例子一样有四种解释方案,结果自然未知),我们习惯上统称此类问题为UB问题(未定义问题)。未定义问题主要是因为C语言标准没有明确规定遇到这种问题时编译器应如何处理,所以,对于未定义问题不同编译器给出的结果可能不同,可能相同,例如char
c=&asdf&;在VC6.0和LCC-WIN32的结果就是不同的。
下面回到主题,我们终于可以看看i++ + ++i了!在本例中,只有一个序列点(未写出全句),但在这个序列点之前访问了两次变量i,其中有一次访问为真引用,这样就使表达式产生了二义性(后面的i自加后,前面的i是自加前的i还是自加后的i?),所以这个表达式就成为了未定义问题。
ok,写到这里,这篇文章就差不多该结稿了,我希望新手们将本文多读几遍,就算不能全部理解,也要能记下多少就记多少,以后多练练,就回了;至于老手们,看后如果找到了什么不恰当的地方,还请指出,我一定会努力修改,使本文日臻完美的。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:98次
排名:千里之外数据结构课程设计-用栈来实现表达式求值
数据结构课程设计-用栈来实现表达式求值
, 围观2522次
1、需求分析
设计一个程序,演示用算符优先法对算术表达式求值的过程。利用算符优先关系,实现对算术四则混合运算表达式的求值。
(1)输入的形式:表达式,例如2*(3+4)
包含的运算符只能有’+’ 、’-’ 、’*’ 、’/’ 、’(‘、 ‘)’;
(2)输出的形式:运算结果,例如2*(3+4)=14;
(3)程序所能达到的功能:对表达式求值并输出
2、系统设计
1、栈的抽象数据类型定义:
ADT Stack{
数据对象:D={ai|ai∈ElemSet,i=1,2,…,n,n≥0}
数据关系:R1={&ai-1,ai&|ai-1,ai∈D,i=2,…,n}
约定an端为栈顶,ai端为栈底
基本操作:
Push(&S,e)
初始条件:栈S已存在
操作结果:插入元素e为新的栈顶元素
Pop(&S,&e)
初始条件:栈S已存在且非空
操作结果:删除S的栈顶元素,并用e返回其值
}ADT Stack
3、各个模块的主要功能:
*Push(SC *s,char c):把字符压栈
*Push(SF *s,float f):把数值压栈
*Pop(SC *s):把字符退栈
*Pop(SF *s):把数值退栈
Operate(a,theta,b):根据theta对a和b进行’+’ 、’-’ 、’*’ 、’/’ 、’^'操作
In(Test,*TestOp):若Test为运算符则返回true,否则返回false
ReturnOpOrd(op,*TestOp):若Test为运算符,则返回此运算符在数组中的下标
precede(Aop,Bop):根据运算符优先级表返回Aop与Bop之间的优先级
EvaluateExpression(*MyExpression):用算符优先法对算术表达式求值
完整的程序代码如下:
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
#include"math.h"
#define true 1
#define false 0
#define OPSETSIZE 8
typedef int S
unsigned char Prior[8][8] =
{ // 运算符优先级表
// '+' '-' '*' '/' '(' ')' '#' '^'
/*'+'*/'&','&','&','&','&','&','&','&',
/*'-'*/'&','&','&','&','&','&','&','&',
/*'*'*/'&','&','&','&','&','&','&','&',
/*'/'*/'&','&','&','&','&','&','&','&',
/*'('*/'&','&','&','&','&','=',' ','&',
/*')'*/'&','&','&','&',' ','&','&','&',
/*'#'*/'&','&','&','&','&',' ','=','&',
/*'^'*/'&','&','&','&','&','&','&','&'
typedef struct StackChar
struct StackChar *
//StackChar类型的结点SC
typedef struct StackFloat
struct StackFloat *
//StackFloat类型的结点SF
SC *Push(SC *s,char c)
//SC类型的指针Push,返回p
SC *p=(SC*)malloc(sizeof(SC));
p-&next=s;
SF *Push(SF *s,float f)
//SF类型的指针Push,返回p
SF *p=(SF*)malloc(sizeof(SF));
p-&next=s;
SC *Pop(SC *s)
//SC类型的指针Pop
SF *Pop(SF *s)
//SF类型的指针Pop
float Operate(float a,unsigned char theta, float b)
//计算函数Operate
switch(theta)
case '+': return a+b;
case '-': return a-b;
case '*': return a*b;
case '/': return a/b;
case '^': return pow(a,b);
default : return 0;
char OPSET[OPSETSIZE]={'+','-','*','/','(',')','#','^'};
Status In(char Test,char *TestOp)
for (int i=0; i& OPSETSIZE; i++)
if(Test == TestOp[i])
Status ReturnOpOrd(char op,char *TestOp)
for(int i=0; i& OPSETSIZE; i++)
if (op == TestOp[i])
char precede(char Aop, char Bop)
return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];
float EvaluateExpression(char* MyExpression)
// 算术表达式求值的算符优先算法
// 设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合
SC *OPTR=NULL;
// 运算符栈,字符元素
SF *OPND=NULL;
// 运算数栈,实数元素
char TempData[20];
float Data,a,b;
char theta,*c,Dr[]={'#','\0'};
OPTR=Push(OPTR,'#');
c=strcat(MyExpression,Dr);
strcpy(TempData,"\0");//字符串拷贝函数
while (*c!= '#' || OPTR-&c!='#')
if (!In(*c, OPSET))
strcat(TempData,Dr);
//字符串连接函数
if (In(*c, OPSET))
Data=atof(TempData);
//字符串转换函数(double)
OPND=Push(OPND, Data);
strcpy(TempData,"\0");
// 不是运算符则进栈
switch (precede(OPTR-&c, *c))
case '&': // 栈顶元素优先级低
OPTR=Push(OPTR, *c);
case '=': // 脱括号并接收下一字符
OPTR=Pop(OPTR);
case '&': // 退栈并将运算结果入栈
theta=OPTR-&c;OPTR=Pop(OPTR);
b=OPND-&f;OPND=Pop(OPND);
a=OPND-&f;OPND=Pop(OPND);
OPND=Push(OPND, Operate(a, theta, b));
} //switch
return OPND-&f;
} //EvaluateExpression
int main(void)
char s[128];
puts("请输入表达式:");
puts("该表达式的值为:");
printf("%s\b=%g\n",s,EvaluateExpression(s));
system("pause");
测试结果如下:
您可能还会对这些文章感兴趣!1.编写代码对算术表达式求值的经典方法由 Donald Knuth 描述于 1962 年。Knuth 将此概括为三个步骤:
对中缀表达式进行语法分析
中缀表达式到后缀表达式的转换
对后缀表达式求值
注意到我们谈到的这个经典算法有些简化:算术表达式只包含操作数、二元操作符和一种括号。此外,对于每个操作数和操作符,只用单个字符表示,使语法分析直观。
算术表达式中最常见的表示法形式有&中缀、前缀和&后缀表示法。中缀表示法是书写表达式的常见方式,而前缀和后缀表示法主要用于计算机科学领域。
中缀表示法&
中缀表示法是算术表达式的常规表示法。称它为&中缀表示法是因为每个操作符都位于其操作数的中间,这种表示法只适用于操作符恰好对应两个操作数的时候(在操作符是二元操作符如加、减、乘、除以及取模的情况下)。对以中缀表示法书写的表达式进行语法分析时,需要用括号和优先规则排除多义性。
Syntax: operand1 operator operand2
Example: (A+B)*C-D/(E+F)
前缀表示法&
前缀表示法中,操作符写在操作数的前面。这种表示法经常用于计算机科学,特别是编译器设计方面这种表示法也称&波兰表示法。
: operator operand1 operand2
Example : -*+ABC/D+EF
后缀表示法&
在后缀表示法中,操作符位于操作数后面。后缀表示法也称&逆波兰表示法(reverse Polish notation,RPN),因其使表达式求值变得轻松,所以被普遍使用。
: operand1 operand2 operator
Example : AB+C*DEF+/-
前缀和后缀表示法有三项公共特征:
操作数的顺序与等价的中缀表达式中操作数的顺序一致
不需要括号
操作符的优先级不相关
要把表达式从中缀表达式的形式转换成用后缀表示法表示的等价表达式,必须了解操作符的优先级和结合性。&优先级或者说操作符的强度决定求值顺序;优先级高的操作符比优先级低的操作符先求值。 如果所有操作符优先级一样,那么求值顺序就取决于它们的&结合性。操作符的结合性定义了相同优先级操作符组合的顺序(从右至左或从左至右)。
Left associativity
: A+B+C = (A+B)+C
Right associativity : A^B^C = A^(B^C)
转换过程包括用下面的算法读入中缀表达式的操作数、操作符和括号:
初始化一个空堆栈,将结果字符串变量置空。
从左到右读入中缀表达式,每次一个字符。
如果字符是操作数,将它添加到结果字符串。
如果字符是个操作符,弹出(pop)操作符,直至遇见开括号(opening parenthesis)、优先级较低的操作符或者同一优先级的右结合符号。把这个操作符压入(push)堆栈。
如果字符是个开括号,把它压入堆栈。
如果字符是个闭括号(closing parenthesis),在遇见开括号前,弹出所有操作符,然后把它们添加到结果字符串。
如果到达输入字符串的末尾,弹出所有操作符并添加到结果字符串。
对后缀表达式求值比直接对中缀表达式求值简单。在后缀表达式中,不需要括号,而且操作符的优先级也不再起作用了。您可以用如下算法对后缀表达式求值:
初始化一个空堆栈
从左到右读入后缀表达式
如果字符是一个操作数,把它压入堆栈。
如果字符是个操作符,弹出两个操作数,执行恰当操作,然后把结果压入堆栈。如果您不能够弹出两个操作数,后缀表达式的语法就不正确。
到后缀表达式末尾,从堆栈中弹出结果。若后缀表达式格式正确,那么堆栈应该为空。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:6580次
排名:千里之外
原创:13篇
(1)(1)(5)(7)(5)(1)EXCEL数学表达式如4 (2*3)求值的2种解决方案
  首先说明什么叫表达式,所谓表达式就是我们通常手写的算式,比如(1+2*3-3)/1,大家都知道在excel中计算这个表达式的值只需要在任意单元格输入=(1+2*3-3)/1即可,我这里要讲的问题是例如在A列中已经填写了文本(1+2*3-3)/1,现在要在B列中通过A列的算式直接得到A1的值,这个问题就归结为对表达式求值。如下图,A列是表达式,B列是结果,表达式求值的实现步骤:1、选中B3单元格,按下CTRL+F3,会弹出自定义名称对话框,在对话框中名称栏和引用位置栏按下图填写,点击添加按钮 确定,返回工作表2、在B3填写公式=evl,回车,即可看到B3会根据A3的表达式计算出结果。然后往下复制公式即可扩展****************上述方法适用于少量使用,且计算位置相对固定的情况,若多处需要计算表达式且位置散乱,就需要用vba自定义函数步骤:1、工具-选项-安全性-宏安全性-低(2010版到 选项-信任中心设置-宏设置-设置宏安全性为),关闭excel重开2、alt+F11打开vba编辑器,插入-模块,在右边空白处粘贴以下代码Function evl(s As String)evl = Evaluate(s)If s = '' Then evl = 0End Function然后返回到工作表,例如要计算A1中表达式的值 则在任意单元格 只需要输入=evl(A1)即可evl(rng),rng即为单元格参数,此公式即可计算引用单元格表达式的值
下一篇:没有了
与本文的相关文章推荐利用递归下降分析解决表达式求值问题之noj35
利用递归下降分析解决表达式求值问题之noj35
感谢scuxc的指出错误,在这向大家道歉,其中的预处理是不需要的。以(1*2)为例的左推导:
term-&factor
factor-&(exp)
-&(term*facctor)
-&(factor*factor)
-&(1*factor)
所以是不需要预处理的。但是预处理部分涉及到一些变量的声明,并没有删除。但是这些并不影响程序的运行正性
题目链接:
这道题应该是数据结构的经题目。记得大二时的数据结构课程报告其中一篇就是表达式求值。今天在看编译原理时看到自顶向下分析之递归下降分析时看到了一个例程-----简单整型算术的递归下降程序计算器。我立马想到了这道题。
先写一下表达式文法:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& exp -& exp addop& term | term
&&&&&&&&&&&&&&&&& &addop -& + | -
&&&&&&&&&&&&&&&&& &term -& term mulop factor | factor
&&&&&&&&&&&&&&&&&& mulop -& * &| &/
&&&&&&&&&&&&&&&&&& factor -& (exp) | number
在求解表达式值时,如果直接用表达式文法写代码,,那么首先应该调用exp,而这将导致一个无限循环,因为exp和term都最终转换为factor,这样将无法区分exp和term,因此会有exp无限调用自己。因此要使用EBNF,将·exp表示为term{addop term),将term表示为factor{mulop facotor}。这样根据EBNF就可以写一个较为简单的程序。注意这个EBNF中在乘法和除法的子表达式中是不需要用括号的,例如不包括这种情况(1*2),所以我们要对表达式做一个预处理,将括号内只有乘除运算的括号去除。利用括号匹配来确定两个括号的管辖范围,然后在管辖范围内查找是否包含加减运算。如果不包含,则去除这两个括号。然后就是求值。贴下code:
[cpp] #include&&stdio.h&&&#include&&stdlib.h&&&#include&&string.h&&&#include&&math.h&&&#include&&ctype.h&&&int&len,&&&const&int&MAX&=&1000&+&10;&&char&&&char&str[MAX];&&int&stack[MAX];&&bool&flag[MAX];&&double&exp();&&double&factor();&&char&getChar();&&double&term();&&void&error()&&{&&&&&&fprintf(stderr,&"Error");&&&&&&exit(1);&&}&&&&void&match(char&expectedToken)&&{&&&&&&if&(token&==&expectedToken)&&&&&&{&&&&&&&&&&token&=&getChar();&&&&&&}&&&&&&else&&&&&&{&&&&&&&&&&error();&&&&&&}&&}&&/*预处理*/&&void&init()&&{&&&&&&int&i,&top&=&0,&j;&&&&&&pos&=&0;&&&&&&memset(flag,&0,&sizeof(flag));&&&&&&len&=&strlen(str);&&&&&&bool&used&=&false;&&&&&&for&(i=0;&i&&i++)&&&&&&{&&&&&&&&&&if&(str[i]&==&'(')&&&&&&&&&&{&&&&&&&&&&&&&&stack[top++]&=&i;&&&&&&&&&&}&&&&&&&&&&else&if&(str[i]&==&')')&&&&&&&&&&{&&&&&&&&&&&&&&for&(j=stack[top-1]+1;&j&i;&j++)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&if&(!flag[j]&&(str[j]&==&'+'&||&str[j]&==&'-'))&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&//puts("hahha");&&&&&&&&&&&&&&&&&&&&&&used&=&true;&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&if&((str[j]&==&'('&||&str[j]&==&')')&&&&!flag[j])&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&continue;&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&flag[j]&=&true;&&&&&&&&&&&&&&}&&&&&&&&&&&&&&if&(used)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&//puts("hahha");&&&&&&&&&&&&&&&&&&flag[stack[top-1]]&=&flag[i]&=&true;&&&&&&&&&&&&&&}&&&&&&&&&&&&&&used&=&false;&&&&&&&&&&&&&&top--;&&&&&&&&&&}&&&&&&}&&&&&&int&tmp&=&0;&&&&&&char&str1[MAX];&&&&&&for&(i=0;&i&&i++)&&&&&&{&&&&&&&&&&//printf("%d\n",&flag[i]);&&&&&&&&&&if&((str[i]&==&'('&||&str[i]&==&')')&&&!flag[i])&&&&&&&&&&{&&&&&&&&&&&&&&continue;&&&&&&&&&&}&&&&&&&&&&else&&&&&&&&&&{&&&&&&&&&&&&&&str1[tmp++]&=&str[i];&&&&&&&&&&}&&&&&&}&&&&&&str1[tmp]&=&0;&&&&&&memset(str,&0,&sizeof(str));&&&&&&strcpy(str,&str1);&&&&&&len&=&&&}&&&&&&&&double&getnum()&&{&&&&&&bool&dot&=&false;&&&&&&pos--;&&&&&&double&tmp1&=&0,&tmp2&=&1;&&&&&&while&(true)&&&&&&{&&&&&&&&&&if&(isdigit(str[pos])&&&&!dot)&&&&&&&&&&{&&&&&&&&&&&&&&tmp1&=&tmp1&*&10&+&(str[pos]&-&'0');&&&&&&&&&&}&&&&&&&&&&else&if&(isdigit(str[pos])&&&&dot)&&&&&&&&&&{&&&&&&&&&&&&&&tmp2&=&tmp2&*&0.1;&&&&&&&&&&&&&&tmp1&=&tmp1&&+&tmp2&*&(str[pos]&-&'0');&&&&&&&&&&}&&&&&&&&&&else&if&(str[pos]&==&'.')&&&&&&&&&&{&&&&&&&&&&&&&&dot&=&true;&&&&&&&&&&}&&&&&&&&&&else&&&&&&&&&&{&&&&&&&&&&&&&&break;&&&&&&&&&&}&&&&&&&&&&pos++;&&&&&&}&&&&&&return&tmp1;&&}&&void&solve()&&{&&&&&&double&&&&&&&init();&&&&&&//puts(str);&&&&&&token&=&getChar();&&&&&&result&=&exp();&&&&&&if&(token&==&'=')&&&&&&{&&&&&&&&&&printf("%.2lf\n",&result);&&&&&&}&&&&&&else&&&&&&{&&&&&&&&&&error();&&&&&&}&&}&&&&int&main()&&{&&&&&&int&t;&&&&&&scanf("%d",&&t);&&&&&&while&(t--)&&&&&&{&&&&&&&&&&scanf("%s",&str);&&&&&&&&&&solve();&&&&&&}&&}&&&&double&exp()&&{&&&&&&double&temp&=&term();&&&&&&while&(token&==&'+'&||&token&==&'-')&&&&&&{&&&&&&&&&&switch&(token)&&&&&&&&&&{&&&&&&&&&&&&&&case&'+':&&&&&&&&&&&&&&&&&&match('+');&&&&&&&&&&&&&&&&&&temp&+=&term();&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&&&case&'-':&&&&&&&&&&&&&&&&&&match('-');&&&&&&&&&&&&&&&&&&temp&-=&term();&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&}&&&&&&}&&&&&&return&&&}&&double&term()&&{&&&&&&double&temp&=&factor();&&&&&&while&(token&==&'*'&||&token&==&'/')&&&&&&{&&&&&&&&&&switch&(token)&&&&&&&&&&{&&&&&&&&&&&&&&case&'*':&&&&&&&&&&&&&&&&&&match('*');&&&&&&&&&&&&&&&&&&temp&*=&factor();&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&&&case&'/':&&&&&&&&&&&&&&&&&&match('/');&&&&&&&&&&&&&&&&&&temp&/=&factor();&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&}&&&&&&}&&&&&&return&&&}&&&&double&factor()&&{&&&&&&double&&&&&&&if&(token&==&'(')&&&&&&{&&&&&&&&&&match('(');&&&&&&&&&&temp&=&exp();&&&&&&&&&&match(')');&&&&&&}&&&&&&else&if&(isdigit(token))&&&&&&{&&&&&&&&&&temp&=&getnum();&&&&&&&&&&token&=&getChar();&&&&&&}&&&&&&else&&&&&&{&&&&&&&&&&error();&&&&&&}&&&&&&return&&&}&&char&getChar()&&{&&&&&&if&(pos&len)&&&&&&{&&&&&&&&&&return&str[pos++];&&&&&&}&&&&&&else&&&&&&{&&&&&&&&&&error();&&&&&&}&&}&&
欢迎纠正指错
发表评论:
馆藏&20932
TA的最新馆藏

我要回帖

更多关于 表达式求值 的文章

 

随机推荐