表达式求值

[问题描述]

一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。假设操作数是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,如:#(7+15)*(23-28/4)#。引入表达式起始、结束符是为了方便。编程利用“算符优先法”求算术表达式的值。

[基本要求]

(1) 从键盘读入一个合法的算术表达式,输出正确的结果。

(2) 显示输入序列和栈的变化过程。

[选作内容]

(1) 扩充运算符集合。

(2) 引入变量操作数。

(3) 操作数类型扩充到实数。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h> #define TRUE 1
#define FALSE 0
#define Stack_Size 50 char ops[7]={'+','-','*','/','(',')','#'}; /*运算符数组*/ int cmp[7][7]={{2,2,1,1,1,2,2}, /*用来进行比较运算符优先级的矩阵,3代表'=',2代表'>',1代表'<',0代表不可比*/
{2,2,1,1,1,2,2},
{2,2,2,2,1,2,2},
{2,2,2,2,1,2,2},
{1,1,1,1,1,3,0},
{2,2,2,2,0,2,2},
{1,1,1,1,1,0,3}}; typedef struct
{
char elem[Stack_Size];
int top;
}SeqStack; /*运算符栈的定义*/ typedef struct
{
int elem[Stack_Size];
int top;
}nSeqStack; /* 运算数栈的定义*/ void InitStack(SeqStack *S) /*初始化运算符栈*/
{
S->top =-1;
} void InitStackn(nSeqStack *S) /*初始化运算数栈*/
{
S->top =-1;
} int IsEmpty(SeqStack *S) /*判断栈S为空栈时返回值为真,反之为假*/
{
return(S->top==-1?TRUE:FALSE);
} int IsEmptyn(nSeqStack *S) /*判断栈S为空栈时返回值为真,反之为假*/
{
return(S->top==-1?TRUE:FALSE);
} /*判栈满*/
int IsFull(SeqStack *S) /*判断栈S为满栈时返回值为真,反之为假*/
{
return(S->top==Stack_Size-1?TRUE:FALSE);
} int IsFulln(nSeqStack *S) /*判断栈S为满栈时返回值为真,反之为假*/
{
return(S->top==Stack_Size-1?TRUE:FALSE);
} int Push(SeqStack *S, char x) /*运算符栈入栈函数*/
{
if (S->top==Stack_Size-1)
{
printf("Stack is full!\n");
return FALSE;
}
else
{
S->top++;
S->elem[S->top]=x;
return TRUE;
}
} int Pushn(nSeqStack *S, int x) /*运算数栈入栈函数*/
{
if (S->top==Stack_Size-1)
{
printf("Stack is full!\n");
return FALSE;
}
else
{
S->top++;
S->elem[S->top]=x;
return TRUE;
}
} int Pop(SeqStack *S, char *x) /*运算符栈出栈函数*/
{
if (S->top==-1)
{
printf("运算符栈空!\n");
return FALSE;
}
else
{
*x=S->elem[S->top];
S->top--;
return TRUE;
}
} int Popn(nSeqStack *S, int *x) /*运算数栈出栈函数*/
{
if (S->top==-1)
{
printf("运算符栈空!\n");
return FALSE;
}
else
{
*x=S->elem[S->top];
S->top--;
return TRUE;
}
} char GetTop(SeqStack *S) /*运算符栈取栈顶元素函数*/
{
if (S->top ==-1)
{
printf("运算符栈为空!\n");
return FALSE;
}
else
{
return (S->elem[S->top]);
}
} int GetTopn(nSeqStack *S) /*运算数栈取栈顶元素函数*/
{
if (S->top ==-1)
{
printf("运算符栈为空!\n");
return FALSE;
}
else
{
return (S->elem[S->top]);
}
} int Isoperator(char ch) /*判断输入字符是否为运算符函数,是返回TRUE,不是返回FALSE*/
{
int i;
for (i=0;i<7;i++)
{
if(ch==ops[i])
return TRUE;
}
return FALSE;
} /*
int isvariable(char ch)
{ if (ch>='a'&&ch<='z')
return true;
else
return false;
}*/ char Compare(char ch1, char ch2) /*比较运算符优先级函数*/
{
int i,m,n;
char pri;
int priority;
for(i=0;i<7;i++) /*找到相比较的两个运算符在比较矩阵里的相对位置*/
{
if(ch1==ops[i])
m=i;
if (ch2==ops[i])
n=i;
} priority = cmp[m][n];
switch(priority)
{
case 1:
pri='<';
break;
case 2:
pri='>';
break;
case 3:
pri='=';
break;
case 0:
pri='$';
printf("表达式错误!\n");
break;
}
return pri;
} int Execute(int a, char op, int b) /*运算函数*/
{
int result;
switch(op)
{
case '+':
result=a+b;
break;
case '-':
result=a-b;
break;
case '*':
result=a*b;
break;
case '/':
result=a/b;
break;
}
return result;
} int ExpEvaluation()
/*读入一个简单算术表达式并计算其值。optr和operand分别为运算符栈和运算数栈,OPS为运算符集合*/
{
int a,b,v,temp;
char ch,op;
char *str;
int i=0; SeqStack optr;
nSeqStack operand; InitStack(&optr);
InitStackn(&operand);
Push(&optr,'#');
printf("请输入表达式(以#结束):\n"); /*表达式输入*/
str =(char *)malloc(50*sizeof(char));
gets(str); ch=str[i];
i++;
while(ch!='#'||GetTop(&optr)!='#')
{
if(!Isoperator(ch))
{
temp=ch-'0'; /*将字符转换为十进制数*/
ch=str[i];
i++;
while(!Isoperator(ch))
{
temp=temp*10 + ch-'0'; /*将逐个读入运算数的各位转化为十进制数*/
ch=str[i];
i++;
}
Pushn(&operand,temp);
}
else
{
switch(Compare(GetTop(&optr),ch))
{
case '<':
Push(&optr,ch);
ch=str[i];
i++;
break;
case '=':
Pop(&optr,&op);
ch=str[i];
i++;
break;
case '>':
Pop(&optr,&op);
Popn(&operand,&b);
Popn(&operand,&a);
v=Execute(a,op,b); /* 对a和b进行op运算 */
Pushn(&operand,v);
break;
}
}
}
v=GetTopn(&operand);
return v;
} void main() /*主函数*/
{
int result;
result=ExpEvaluation();
printf("\n表达式结果是%d\n",result);
}

下面这个是在网上找的:

用 C++ 实现的加、减、乘、除表达式计算

前些日子面试一个开发工作,考官出了这么一笔试题目,要我写出实现过程, 思量半天,终于
用 C++ 完成,现将代码贴出,与诸同道共分享。 // 头文件 Calc.h
#ifndef __CALC_H__
#define __CALC_H__
#include <stack>
#define ascii_int(x) (x >= 0x30 && x <= 0x39) ? (x - 0x30) : (x)
const int GREATER = 1;
const int EQUAL = 0;
const int LESS = -1;
class Calculate {
public:
int evaluteExpr(char *exp);
private:
int getLevel(char ch);
bool isOperator(char ch);
int compareOpteratorLevel(char inputChar, char optrStackTop);
int calc(int num1, int num2, char op);
void evaluate(char ch);
private:
std::stack<int> _opnd_stack;
std::stack<char> _optr_stack;
static char _optr[];
static int _level[];
};
#endif // 头文件的实现代码 Calc.cxx
#include "Calc.h"
char Calculate::_optr[] = {'#', '(', '+', '-', '*', '/', ')'};
int Calculate::_level[] = { 0, 1, 2, 2, 3, 3, 4 };
// Get current operator level for calculating
int Calculate::getLevel(char ch) {
for (int i = 0; *(_optr+i) != '\0'; ++i)
if (*(_optr+i) == ch)
return *(_level+i);
}
// Calculate the operands
int Calculate::calc(int num1, int num2, char op) {
switch (op)
{
case '+':
return num1 + num2;
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
return num1 / num2;
}
}
// judge inputing character is operator or not
bool Calculate::isOperator(char ch) {
for (char *p = _optr; *p != '\0'; ++p)
if (*p == ch)
return true;
return false;
}
// Compare level of input operator and the top operator of operator stack
int Calculate::compareOpteratorLevel(char inputChar, char optrStackTop) {
// if (inputChar == '(' && optrStackTop == ')')
// return EQUAL;
// else
if (inputChar == '(')
return GREATER;
if (inputChar == ')' && optrStackTop == '(')
return EQUAL;
else if (inputChar == ')')
return LESS;
if (inputChar == '#' && optrStackTop == '#')
return EQUAL;
// else if (inputChar == '#')
// return LESS;
return (getLevel(inputChar) > getLevel(optrStackTop)) ? GREATER : LESS;
}
// Evaluate value while inputing operators
void Calculate::evaluate(char ch) {
char op;
int num, result;
if (!isOperator(ch)) {
_opnd_stack.push(ascii_int(ch));
return ;
}
switch (compareOpteratorLevel(ch, _optr_stack.top()))
{
case GREATER :
_optr_stack.push(ch);
break;
case EQUAL :
_optr_stack.pop();
break;
case LESS :
num = _opnd_stack.top();
_opnd_stack.pop();
result = _opnd_stack.top();
_opnd_stack.pop();
op = _optr_stack.top();
_optr_stack.pop();
result = calc(result, num, op);
_opnd_stack.push(result);
evaluate(ch);
break;
}
}
// Evaluate user specified expression
int Calculate::evaluteExpr(char *exp) {
_optr_stack.push('#');
for (char *p =exp; *p != '\0'; ++p )
evaluate(*p);
int result = _opnd_stack.top();
_opnd_stack.pop();
return result;
} // 测试代码 calc_test.cxx
#include <iostream>
#include "Calc.h"
using namespace std;
int main(void) {
Calculate *calc = new Calculate();
cout << "1+3*(4+7) = "
<< calc->evaluteExpr("1+3*(4+7)#")
<< endl;
cout << "((1+2)) = "
<< calc->evaluteExpr("((1+2))#")
<< endl;
cout << "3*8+9/7-5-9+(1-9)/4 = "
<< calc->evaluteExpr("3*8+9/7-5-9+(1-9)/4#")
<< endl;
cout << "(6-7)*(5+9) = "
<< calc->evaluteExpr("(6-7)*(5+9)#")
<< endl;
cout << "0*8+0/6-9+(7-1) = "
<< calc->evaluteExpr("0*8+0/6-9+(7-1)#")
<< endl;
delete calc;
} 用 MinGW/G++ 3.4.5 编译如下:
g++ -o test.exe Calc.cxx Calc_test.cxx 作为一个演示算法够了, 但代码还是有一些缺点:
(1) 只能处理一位数的加、减、乘、除表达式计算(可带括号)

c/c++ 表达式求值的更多相关文章

  1. 表达式求值(noip2015等价表达式)

    题目大意 给一个含字母a的表达式,求n个选项中表达式跟一开始那个等价的有哪些 做法 模拟一个多项式显然难以实现那么我们高兴的找一些素数代入表达式,再随便找一个素数做模表达式求值优先级表 - ( ) + ...

  2. 用Python3实现表达式求值

    一.题目描述 请用 python3 编写一个计算器的控制台程序,支持加减乘除.乘方.括号.小数点,运算符优先级为括号>乘方>乘除>加减,同级别运算按照从左向右的顺序计算. 二.输入描 ...

  3. 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

    一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...

  4. nyoj305_表达式求值

    表达式求值 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求值,比如,它知道函数min ...

  5. 利用栈实现算术表达式求值(Java语言描述)

    利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...

  6. 数据结构--栈的应用(表达式求值 nyoj 35)

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=35 题目: 表达式求值 时间限制:3000 ms | 内存限制:65535 KB描述 AC ...

  7. NOIP2013普及组 T2 表达式求值

    OJ地址:洛谷P1981 CODEVS 3292 正常写法是用栈 #include<iostream> #include<algorithm> #include<cmat ...

  8. HNU 12817 Shipura(表达式求值)

    题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12817 解题报告:定义两种运算符号,一种是>>,就 ...

  9. NOIP201302表达式求值

    NOIP201302表达式求值 题目描述 Description 给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值. 输入描述 Input Description 输入仅有一行,为需要你计 ...

  10. OpenJudge计算概论-简单算术表达式求值

    /*===================================== 简单算术表达式求值 总时间限制: 1000ms 内存限制: 65536kB 描述 2位正整数的简单算术运算(只考虑整数运 ...

随机推荐

  1. 协议系列之TCP/IP协议

    根据前面介绍的几种协议,将IP协议.TCP协议.UDP协议组合起来,于是便有了TCP/IP协议.现在很多的应用的通信都是建立在TCP/IP协议的基础上,运用非常广泛,很有必要对其学习一下. 打个不太恰 ...

  2. Struts1基础、使用Struts实现登录、使用Struts HTML标签简化开发

    Struts 1基础 为什么重拾Struts 1 曾经是最主流的MVC框架 市场份额依然很大 很多遗留系统中依旧使用 维护和升级都需要熟悉Struts 1 与Struts 2相比 编码.配置繁琐 侵入 ...

  3. 指令汇B新闻客户端开发(五) ShareSdk的使用

    ShareSdk是一个分享按钮的开源框架,我们首先可以去mob的官网下载这个控件.mob官网,然后找到sdk下载那一栏, 下载下来之后点击这个.jar文件就会有一个弹窗,填写自己的应用包名和要哪些分享 ...

  4. 安卓自定义View实现钟表

    转载请注明出处:http://blog.csdn.net/baiyuliang2013/article/details/45535227 之前实现过html5版的钟表,html5也有一个画板属性Can ...

  5. 18 Ui美化 剪切动画clip

    输入0 - 10000 让图片根据数值显示部分图片 在工程文件的res/drawable/新建clip文件 <?xml version="1.0" encoding=&quo ...

  6. VMware虚拟化解决方案】如何选择虚拟化产品

    http://wangchunhai.blog.51cto.com/225186/1425557/ 拟化.云计算.大数据.智慧城市,是近期以及将来一段时间的热点.现在虚拟化产品很多,做虚拟化的公司也很 ...

  7. 1021. Deepest Root (25) -并查集判树 -BFS求深度

    题目如下: A graph which is connected and acyclic can be considered a tree. The height of the tree depend ...

  8. J2EE学习从菜鸟变大鸟之五 JDBC(Java Data Base Connectivity)

    JDBC刚开始学习这个的时候看到了,以为是ODBC呢,很是相似啊,总的来说还是基本上一类的东东,但是还有一些细微的区别,下面和大家一起分享学习. JDBC(Java Data Base Connect ...

  9. mysql DISTINCT 的实现与优化

    DISTINCT实际上和GROUP BY的操作非常相似,只不过是在GROUP BY之后的每组中只取出一条记录而已.所以,DISTINCT的实现和GROUP BY的实现也基本差不多,没有太大的区别.同样 ...

  10. C++对象模型(三):Program Transformation Semantics (程序转换语义学)

    本文是Inside The C++ Object Model Chapter 2 部分的读书笔记.是讨论编译器调用拷贝构造函数时的策略(如何优化以提高效率),侯捷称之为"程序转化的语义学&q ...