c/c++ 表达式求值
表达式求值
[问题描述]
一个算术表达式是由操作数(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++ 表达式求值的更多相关文章
- 表达式求值(noip2015等价表达式)
题目大意 给一个含字母a的表达式,求n个选项中表达式跟一开始那个等价的有哪些 做法 模拟一个多项式显然难以实现那么我们高兴的找一些素数代入表达式,再随便找一个素数做模表达式求值优先级表 - ( ) + ...
- 用Python3实现表达式求值
一.题目描述 请用 python3 编写一个计算器的控制台程序,支持加减乘除.乘方.括号.小数点,运算符优先级为括号>乘方>乘除>加减,同级别运算按照从左向右的顺序计算. 二.输入描 ...
- 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值
一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...
- nyoj305_表达式求值
表达式求值 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求值,比如,它知道函数min ...
- 利用栈实现算术表达式求值(Java语言描述)
利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...
- 数据结构--栈的应用(表达式求值 nyoj 35)
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=35 题目: 表达式求值 时间限制:3000 ms | 内存限制:65535 KB描述 AC ...
- NOIP2013普及组 T2 表达式求值
OJ地址:洛谷P1981 CODEVS 3292 正常写法是用栈 #include<iostream> #include<algorithm> #include<cmat ...
- HNU 12817 Shipura(表达式求值)
题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12817 解题报告:定义两种运算符号,一种是>>,就 ...
- NOIP201302表达式求值
NOIP201302表达式求值 题目描述 Description 给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值. 输入描述 Input Description 输入仅有一行,为需要你计 ...
- OpenJudge计算概论-简单算术表达式求值
/*===================================== 简单算术表达式求值 总时间限制: 1000ms 内存限制: 65536kB 描述 2位正整数的简单算术运算(只考虑整数运 ...
随机推荐
- RxJava操作符(08-条件和布尔操作)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51671826 本文出自:[openXu的博客] 目录: All Amb Contains D ...
- Volley的基本使用
Volley的基本使用 导入jar包 导入成功 源码 GET请求下载地址:http://download.csdn.net/detail/q4878802/9053969 POST请求下载地址:htt ...
- Android高级控件(六)——自定义ListView高仿一个QQ可拖拽列表的实现
Android高级控件(六)--自定义ListView高仿一个QQ可拖拽列表的实现 我们做一些好友列表或者商品列表的时候,居多的需求可能就是需要列表拖拽了,而我们选择了ListView,也是因为使用L ...
- Servlet之异常处理
当一个 Servlet 抛出一个异常时,Web 容器在使用了exception-type 元素的 web.xml 中搜索与抛出异常类型相匹配的配置. 前提是必须在 web.xml 中使用 error- ...
- spark idea 的配置问题
不知道下面的错误是为什么? Error:scalac: missing or invalid dependency detected while loading class file 'RDD.cla ...
- EBS 客户表结构
客户表/联系人/PARTY关联 HZ_PARTIES 客户账户表 HZ_CUST_ACCOUNTS SELECT hp.party_number --客户注册标识 , hp.party_name ...
- 【Unity Shaders】Lighting Models —— 光照模型之Lit Sphere
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- Android 官方命令深入分析之android
作者:宋志辉 android命令是一个非常重要的开发工具,它可以: 创建.删除和查看Android Virtual Devices(AVDs). 创建和更新android项目. 更新你的android ...
- CentOS配置
1.在Vmware中安装好虚拟机. 2.客户机(即虚拟机中的centos)网络连接使用仅主机模式Host-only 3.在主机中网络配置上,配置IP地址 1.使用PieTTY远程连接该虚拟机 2.使用 ...
- 一台电脑上同启动两个Tomcat的方式,windows/Linux配置。
安装两个jdk,一个JDK路径在:C:\ProgramFiles (x86)\Java\jdk1.7.0_25,另外一个JDK的路径在E:\UCMSServer\j2sdk 在环境变量里并设置J ...