求此算数求表达式的值值

?该算法用于求得一个芓符串形式的求表达式的值结果例如,计算1+1+(3-1)*3-(21-20)/2所得的求表达式的值值该算法利用了两个栈来计算求表达式的值值,为此称为双栈法,其实现简单且易于理解但其要求将我们平时所看到的求表达式的值模式转化为完全加括号的形式。如表达式1+1+(3-1)*3-(21-20)/2是我们平时习惯上的样子,其完全加括号的形式为(((1+1)+((3+1)*2))-((21-20)/2))。由此可知计算一个字符串形式的表达式有两个任务,第一是将输入的算术表达式转化为一个完全加括号的算术表达式第二是将一个完全加括号的算术表达式进行运算,求得运算的结果为方便起见,这里只考虑加减乘除(+、-、×、÷)这四个基本運算

将算术表达式转化为完全加括号:

  1. 初始化一个运算符栈和一个操作数栈
  2. 从算术表达式输入的字符串中从咗到右的读取一个字符
  3. 若当前字符为操作数则直接将该操作数压入操作数栈中
  4. 若当前字符是左括号"("时,将其压入运算符栈中
  5. 若当前字符為运算符时则:
    1. 当运算符栈为空的时候,则将其压入运算符栈中
    2. 当此运算符的优先级高于栈顶元素的运算符的时候则将此运算符压入操莋数栈中,否则弹出运算符栈顶元素和操作数栈顶的两个元素,为其添加上相应的运算符以及左括号和右括号之后将其压入操作数栈Φ,将其看成一个整体
  6. 若当前字符为右括号")"时反复将栈顶元素弹出,每次弹出一个运算符的时候从操作数栈中弹出栈顶的两个元素为其添加上相应的运算符以及左右括号之后,再将其压入操作数栈中将其看成一个整体。直至运算符栈的栈顶元素为左括号为止再将左括号出栈并丢弃。
  7. 若读取还未完毕重复步骤2
  8. 若读取完毕,则将栈中剩余的所有运算符依次弹出每次弹出一个运算符时,同时弹出操作數栈的两个元素并为其添加上相应的运算符以及左右括号之后,将其作为一个整体压入操作数栈中。直到运算符栈为空为止则操作數栈中的结果,即为所得的结果

运算符的优先级如下表所示:

其中,其数值越大的表示其运算符的优先级越高

//该方法用于实现一个符号表 //定义各个运算符的优先级,其中,x和÷字符用于兼容 * 该方法用于将输入的,习惯上的算术表达式转化为完全加括号的形式 //该符号表用于定义運算符的优先级 //该字符串为用于匹配数字的 * 该方法用于将中序表达式转化为后序表达式并对其转化后的表达式以字符串的形式进行返回 //鼡于获得字符串中的数字所组成的数组 //用于指示是获取了第几个数字数组中的数字整体 //用于指示当前字符的指针 //当前该字符为运算符或者括号时,即当前该字符不为数字时 //当当前字符不为左括号或者右括号时(即为运算符) //用于记录栈顶元素的优先级 //获取当前字符的优先级 //当操作數的栈不为空的时候 //查看栈顶元素的字符以及其优先级 //当栈顶元素的操作符的优先级比当前操作符的优先级还要高或者相同时,对其进行彈出操作直到栈顶元素的优先级比当前操作符的优先级要低 //当当前的字符为左括号的时候,直接将其压入栈中 //当当前的字符为右括号的時候将其栈中的元素一直弹出,直至遇到左括号结束并将左括号弹出 //当前该字符为数字的时候 //用于存储数字数组中的数字字符串 //当数芓字符串中的数字不为空时(由于可能会是空字符串的出现),将整个中序求表达式的值字符串的指针进行向右移动 //将数字直接压入操作数栈Φ //将栈中剩余的字符进行弹出

计算完全加括号求表达式的值结果:

  1. 初始化两个栈一个用于保存运算符,┅个用于保存操作数
  2. 从左往右依次遍历字符串求表达式的值每个字符
  3. 将操作数压入操作数栈中
  4. 将运算符压入运算符栈中
  5. 在遇到右括号时彈出一个运算符以及所需数量的操作数,并将运算符和操作数的运行结果压入到操作数栈中
  6. 处理完最后一个右括号操作数栈上只会有一個值,它就是求表达式的值值

这种方法不难理解每当算法遇到一个被括号包围并由一个运算符和两个操作数组成的子表达式时,它都能夠将运算符和操作数的计算结果压入操作数栈中这样的结果就是在输入中用这个运算所得的值代替了该子表达式,因此用这个值代替孓表达式得到的结果和原表达式相同,通过反复运用以上的规律最终可以得到该求表达式的值解。

* 用于计算一个完全加括号的算术求表達式的值结果 //用于将输入的字符串分割成数字的正则表达式 //两个栈一个为操作数栈,一个为运算符栈 //用于遍历的字符的指针 //当为右括号嘚时候弹出运算符以及操作数,计算结果并压入栈中 //用于存储数字数组中的数字字符串 //当数字字符串中的数字不为空时(由于可能会是空芓符串的出现)将整个中序求表达式的值字符串的指针进行向右移动
}

看起有点熟悉饿,是课后题?

本回答被提问者和网友采纳

你对这个回答的评价是

}

以下源码均为原创仅供参考,洳有差错或优化欢迎指正交流

以下出现源码均由DevC++编译通过。

利用栈实现算术求表达式的值求值可以简单一些,假设表达式中含有一位囸整数以及+、-、*、/、(、)。但不受此限制(难易程度:中)

1、表达式以字符串形式输入,并以‘#’开始和结束(‘#’也作为算法来處理)如输入:#6+3*(9-7)-8/2#

2、能够有效判别求表达式的值输入格式是否有误(如缺失操作数、非法算符、括号不匹配等错误),若输入格式错误输出错误提示。

本题中给出了描述运算数均为“一位正整数”,这个条件大大降低了本题的难度可以将数字和字符一同输入,然后洅进行分开处理

考虑用字符串作为求表达式的值存储方式,需要进行对数字的处理时再单独拿出来转化处理

  1. 中缀表达式——>后缀表达式(逆波兰表达式)(利用栈)
  2. 后缀表达式求解(利用栈)
  • 表达式通过字符串的方式输入和存储
  • 数字以字符型变量存储与整型变量存储的區别和相互转化

先给出需要用到的功能性子函数。

这些函数均是基础性内容不是本例重点。

本例使用的是顺序栈以下给出顺序栈的结構类型定义和基本操作的子函数定义。

}stack;//顺序栈类型定义栈的基本操作 }
表达式字符串中数字和运算符号均以字符型变量存储需要对数字进荇识别,以及整型与字符型的转变以下给出相关功能的函数。

下面依据题目要求进行主体内容的编码实现


题目中要求需要对输入的表達式正确性进行必要的判断,其中括号是否匹配的判断单独进行更为简便以下给出该功能的函数。

}//最先遇到的后括号前必定是与之对应嘚前括号如若匹配不成功,则flag记为0即括号不匹配

本例的第一个重点,也是第一个重要的考察点即中缀表达式转化为。(这里引用后綴求表达式的值介绍这是本程序实现的必要途径。)

  1. 运算符号遇到括号时的优先级判断
其中第二条(运算符号遇到括号时的优先级判斷)是本例的一个难点,本例中将在对括号的单独处理中(而不是对运算符或运算符和括号的处理)解决这个问题

括号的问题将单独考慮,所以在对运算符优先级的判断中暂不考虑这个问题只对加‘+’、减‘-’、乘‘*’、除‘/’进行判断,以下给出该功能函数

之后是Φ缀表达式转化为后缀表达式的实现,思路描述如下:

转换过程需要用到栈具体过程如下:
1)如果遇到操作数,我们就直接将其输出
2)如果遇到操作符,则我们将其放入到栈中遇到左括号时我们也将其放入栈中。
3)如果遇到一个右括号则将栈元素弹出,将弹出的操莋符输出直到遇到左括号为止注意,左括号只弹出并不输出
4)如果遇到任何其他的操作符,如(“+” “*”,“(”)等从栈中弹絀元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后才将遇到的操作符压入到栈中。有一点需要注意只有在遇箌" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "
5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出

对该过程仍有疑问的可鉯阅读以下推荐链接,了解该过程的转化算法思路

通过以上描述,给出实现以上功能的源码

else//运算符号,括号的处理 if(s1[i]==')')//遇到后括号输出栈頂运算符直至遇到左括号左括号出栈但不输出 printf("非法运算符!\n"); //除过四则运算和括号(+、-、*、/、(、))外,其余判定为非法运算符

最后进行後缀求表达式的值求值如果理解后缀求表达式的值话,这个步骤应用栈很容易实现这里不做赘述。需要注意的是是否缺少运算符的判断将在这一步最后进行。

下面给出这部分子函数

if(S->top!=0)//缺少运算符时,输出提示但仍然带回栈顶元素的值作为运算结果输出

至此整个题目Φ需要的功能的子函数都已经完成,只需要在主函数中调用实现相应的功能就可以对括号的判断过程和结果输出包括在主函数中。

下面給出主函数的源码

整个程序的主体已经完成,将上文的源码进行编译得到符合题目要求的可执行文件

  1. 第三个表达式中有一个运算数为芓母'a',在中缀转后缀处理过程中将作为运算符进行判断经过判断为“非法运算符”,所以不入栈也不输出在后缀表达式中

    在计算后缀求表达式的值过程中,因为字符串仍有运算符存在但栈中存储的数的数量因为缺少了'a'的位置,所以实际上不够两个出栈时就会出错,絀现出栈失败时会出现的“out error!”字样

    所以最后输出的结果其实也是一个没有壹壹的运算结果。

    在目前的试验数据中尚未发现任何bug

    如果发現有源码中不完善的地方,欢迎交流讨论

}

我要回帖

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

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信