C++实现计算器功能(包括计算含未知量的式子),输出后缀表达式
大概描述
用c++语言在vc中实现部分数学计算功能。其中实现的数学计算功能包括加减乘除运算、开方计算、自然对数运算、以10为底的对数运算、幂计算、正弦余弦计算。
由用户输入要计算的表达式,然后判断表达式是否含有未知变量,若含有未知变量则调用可以处理未知量的计算函数,否则调用一般的计算函数。
把用户输入的表达式存进一个存放中缀表达式的字符数组,再定义一个存放后缀表达式的字符数组,通过调用中缀转后缀的函数,将转为后缀的字符存进后缀表达式的字符数组。
用存放后缀表达式的字符数组调用计算函数,遇到数字时,调用读取数据的函数,把数字字符转换为double型的数。最后将答案输出。
为方便,对于未知量的处理,人为地规定了未知量的顺序和名字,规定如下:未知量的定义最多有5个,其名字和顺序如下x、y、z、m、n。
同时,为方便,常见函数的名字一律采用一个字母代替,其中sin函数用s代替,cos函数用c代替,ln函数用l代替,log10函数用g代替。
实验目的
1 用c++语言在vc中实现部分数学计算功能。其中实现的数学计算功能包括加减乘除运算、开方计算、自然对数 运算、以10为底的对数运算、幂计算、正弦余弦计算。
2 通过用户输入表达式,实现字符串的处理:实现中缀表达式转化后缀表达式,实现后缀表达式的数字字符的处 理。
3 实现后缀表达式的计算。
实验设计
1、由用户输入中缀表达式,把表达式存进一个字符数组,再定义一个字符数组用于存放后缀表达式
2、写一个将中缀表达式转为后缀表达式的函数,利用栈来处理操作符和括号
3、写一个从后缀表达式获取数据的函数
4、写一个函数,判断用户输入的表达式是否含有未知量
5、写两个计算函数,一个用于计算不含未知量的表达式,一个用于计算含有未知量的表达式
6、规定未知量的名字和顺序(本程序只定义了5个未知量,其名字依次为x、y、z、m、n)
7、调用<cmath>中的常见函数;如调用其正弦余弦函数对数函数等
实验描述
- 在主函数测试计算器,提示用户相应的函数名字缩写定义,提示用户输入表达式,并且创建两个字符数组,分别用于存放中缀 表达式和后缀表达式,再用这两个数组去调用中缀转后缀的函数,继而调用后缀表达式的计算函数,具体看main()函数。
- 中缀表达式转后缀表达式函数:创建一个字符型的栈,用于存放操作符。将存放中缀表达式的字符数组作为实参来调用此函数。然后从i=0开始读取字符数组里的元素,若遇到数字或者未知量,则调用读取数据的函数;若遇到函数缩写名时,则先将后面的数存进后缀表达式的数组,再将函数缩写名存进后缀表达式的数组;若遇到‘(’,则将其进栈;若遇到‘)’,则将栈顶的操作符存进后缀表达式的字符数组,并且出栈,直到遇到‘(’,将‘(’出栈;若遇到二目操作符,则比较此操作符和栈顶操作符的优先级,若栈顶操作符的优先级高,则将栈顶操作符放进后缀表达式,并将其出栈,一直进行此操作,直到栈里的操作符优先级比此操作符的优先级低。具体看getpostfix()函数。
- 获取操作符优先级的函数:加减的优先级定义为1,乘除的优先级定义为2,幂计算的优先级定义为3。具体看getpri()函数。
- 判断字符是否是二目操作符函数,具体看is_opr()函数。
- 判断字符是否是函数缩写名,具体看is_char()函数。
- 判断字符是否是数字或者未知量函数,具体看is_num()函数。
- 从后缀表达式读取数据函数:在读取后缀表达式的字符时,遇到数字,则调用此函数。调用此函数时,除了要传后缀表达式的数组做参数外,还要传此时的i的引用来做参数。具体看read_number()函数。
- 判断表达式是否含有未知量函数,具体看is_xyzmn()函数。
- 计算不含未知量表达式的函数:创建一个double型的数组,用于存放后缀表达式里的数据和进行计算后的中间结果。遍历存放后缀表达式的字符数组,若遇到数字,则调用读取数据的函数,并且把读取到的数据放在double型的数组中;若遇到操作符或者函数缩写名,则进行相应计算。具体看getpanswer()函数。
- 计算含有未知量表达式的函数: 计算含有未知量表达式的函数实现和计算不含未知量表达式的函数实现差不多。只不过在遍历后缀表达式数组时,若遇到未知量,则将未知量的值直接存进double型数据数组,而不存未知量。具体看geteanswer()函数。
完整代码
/*************************************************************************> File Name: mycomputer.c> Author: surecheun> Mail: surecheun@163.com> Created Time: 2017年4月18日************************************************************************/#include<iostream>
#include<stack>
#include<string>
#include<vector>
#include <sstream>
#include<cmath>
#define max 100using namespace std;//对二目操作符进行优先级的量化转变
int getpri(char c) {switch (c) {case '+':return 1; break;case '-':return 1; break;//‘+’和‘-’的优先级为最低级1case '*':return 2; break;case '/':return 2; break;//‘*’‘/’的优先级为中级2case'^':return 3; break;//‘^’的优先级最高,为3default:return 0; break;}
}
//判断字符是否是二目操作符
int is_opr(char c)
{switch (c) {case '+':case '-':case '*':case '/':case'^':return 1; break;default:return 0; break;}
}
//判断字符是否是数字或者是未知量
int is_num(char c)
{switch (c){case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9':case'.':case'x':case'y':case'z':case'm':case'n':return 1; break;default:return 0; break;}
}
//判断字符是否代表特殊函数,为了程序简单,取特殊函数的某个字母代替该函数(此类函数均为单目运算)
int is_char(char c)
{switch (c){case's'://sin函数case'c'://cos函数case'q'://开方函数case'l'://ln函数case'g'://log10函数return 1; break;default:return 0; break;}
}//中缀表达式改写成后缀表达式
void getpostfix(char *in, char *post)
{stack<char> st;//创建一个字符类的栈,用于存放操作符st.push('@');//村一个@进栈底,方便于最后判断栈里的操作符是否已经全部出栈int i = 0;int j = 0;while (in[i] != '#')//‘#’为字符数组的最后一个元素{char ch = in[i];if (is_num(ch))//判断是否是数字后者未知量,若是则把其放进后缀字符数组{post[j++] = ch;i++;}else if (is_char(ch))//判断字符是否是常见(单目运算)函数的缩写,若是则将函数后面的数放进后缀字符数组,再将函数名缩写放进后缀数组{i++;char ch1 = in[i];while (is_num(ch1) == 1){post[j++] = ch1;i++;ch1 = in[i];}//把函数后面的数输进后缀字符数组post[j++] = ' ';//用空格分开数和函数名post[j++] = ch; //将函数名的缩写放进后缀表达式的数组 }else //若字符是二目操作符或者是括号,则做以下操作{post[j++] = ' ';//用空格隔开操作符前后的数,便于后续读取if (ch == '(')//如果字符是‘(’,则将字符进栈{st.push(ch);}else if (ch == ')') //若字符是‘)’,则将栈中的字符输进后缀表达式的字符数组,直至遇到‘(’ {ch = st.top();while (ch != '('){post[j++] = ch;st.pop();ch = st.top();}st.pop(); //将‘(’出栈}else//若字符是二目操作符‘则做以下操作{int thisPri = getpri(ch); //获取操作符的优先级char prevOpt = st.top(); //获取栈顶操作符int prevPri = getpri(prevOpt); //获取栈顶操作符的优先级while (thisPri <= prevPri)//比较两者的优先级,若栈顶操作符的优先级高,则将栈顶操作符放进后缀表达式,并将其出栈 {post[j++] = prevOpt;//将栈顶操作符放进后缀表达式st.pop(); //将其出栈prevOpt = st.top();//取栈中新栈顶的操作符prevPri = getpri(prevOpt);//同理获取栈中新栈顶的操作符的优先级}st.push(ch); //把新的操作符进栈}i++;}}char ch = st.top();while (ch != '@'){post[j++] = ch;st.pop();ch = st.top();}//当栈底元素不是’@‘时,将栈顶元素放进后缀表达时的字符数组post[j] = '\0';
}
//读取数据,将后缀表达式的字符数字转变为数
double read_number(char *dest, int *i)
{double x = 0;int num = 0;int j;while (dest[*i]<'0' || dest[*i]>'9') (*i)++;while (dest[*i] >= '0'&&dest[*i] <= '9'){x = x * 10 + (dest[*i] - '0');(*i)++;}if (dest[*i] == '.')//遇到小数点,则计算后面的数字个数,用于判断要把数字除以多少个10{(*i)++;while (dest[*i] >= '0'&&dest[*i] <= '9'){num++;x = x * 10 + (dest[*i] - '0');(*i)++;}}for (j = 0; j < num; j++)x = x / 10;return x;
}//计算没有未知数的表达式
double getpanswer(char *dest)
{double x[50];//创建一个数组,用于存放数据int len = 0;int i = 0;while (dest[i] != '\0')//当字符数组中的字符不是’/0‘时{if (dest[i] >= '0'&&dest[i] <= '9')//遇到数字时x[len++] = read_number(dest, &i);//调用读取数据函数,并且把i的地址传过去,这样i的值将会在函数调用后,也改变,从而使i跳到下一个类型的字符else if (is_char(dest[i]) || is_opr(dest[i]))//假设字符是二目操作符,或者是函数名缩写,则进行计算{switch (dest[i]){case '+'://加法x[len - 2] = x[len - 2] + x[len - 1];len--;i++;break;case '-'://加法x[len - 2] = x[len - 2] - x[len - 1];len--;i++;break;case '*'://乘法x[len - 2] = x[len - 2] * x[len - 1];len--;i++;break;case '/'://除法x[len - 2] = x[len - 2] / x[len - 1];len--;i++;break;case'^'://幂运算for (double i = 1; i < x[len - 1]; i++){double y = x[len - 2];x[len - 2] = x[len - 2] * y;}len--;i++;break;case's'://sin函数x[len - 1] = sin(x[len - 1]);i++;break;case'c'://cos函数x[len - 1] = cos(x[len - 1]);i++;break;case'q'://开方函数x[len - 1] = sqrt(x[len - 1]);i++;break;case'l'://ln函数x[len - 1] = log(x[len - 1]);i++;break;case'g'://log10函数x[len - 1] = log10(x[len - 1]);i++;break;}}else i++;}return x[len - 1];}
//计算含有未知量的表达式
double geteanswer(char *dest, double x1, double y1, double z1, double m1, double n1)
{double x[50];int len = 0;int i = 0;while (dest[i] != '\0'){if (dest[i] >= '0'&&dest[i] <= '9')x[len++] = read_number(dest, &i);else if (dest[i] == 'x' || dest[i] == 'y' || dest[i] == 'z' || dest[i] == 'm' || dest[i] == 'n')//如果遇到未知量,则将未知量的值直接存进数据数组,而不存未知量{if (dest[i] == 'x')x[len++] = x1;else if (dest[i] == 'y')x[len++] = y1;else if (dest[i] == 'z')x[len++] = z1;else if (dest[i] == 'm')x[len++] = m1;elsex[len++] = n1;i++;}else if (is_char(dest[i]) || is_opr(dest[i]))//遇到操作符或者函数名字缩写,则同不含有未知量的计算一样{switch (dest[i]){case '+':x[len - 2] = x[len - 2] + x[len - 1];len--;i++;break;case '-':x[len - 2] = x[len - 2] - x[len - 1];len--;i++;break;case '*':x[len - 2] = x[len - 2] * x[len - 1];len--;i++;break;case '/':x[len - 2] = x[len - 2] / x[len - 1];len--;i++;break;case'^':for (double i = 1; i < x[len - 1]; i++){double y = x[len - 2];x[len - 2] = x[len - 2] * y;}len--;i++;break;case's':x[len - 1] = sin(x[len - 1]);i++;break;case'c':x[len - 1] = cos(x[len - 1]);i++;break;case'q':x[len - 1] = sqrt(x[len - 1]);i++;break;case'l':x[len - 1] = log(x[len - 1]);i++;break;case'g':x[len - 1] = log10(x[len - 1]);i++;break;}}else i++;}return x[len - 1];
}int is_xyzmn(char *d, int j)//判断表达式是否含有未知量
{int p;for (int o = 0; o < j; o++){if (d[o] == 'x'){p = 1;break;}elsep = 0;}return p;
}int main() {cout << "sin请用s代替;cos请用c代替;sqrt请用q代替;ln用l代替;log10用g代替!" << endl;cout << "如果表达式含有未知数,请按下面的顺序定义变量名字:x,y,z,m,n.(最多只允许5个变量)" << endl;char infix[max];//创建一个字符数组,用于存放中缀表达式char postfix[max];//创建一个字符数组,用于存放后缀表达式int i = 0;char ch;while ((ch = getchar()) != '\n'){infix[i++] = ch;//把输入的字符放进中缀表达式的数组}infix[i++] = '#';//放进一个标志字符,便于判断中缀表达式是否已查完infix[i] = '\0';getpostfix(infix, postfix);//调用中缀转后缀函数cout << "输出后缀表达式:" << postfix << endl;double a;//用于存放答案if (is_xyzmn(infix, i))//判断表达式是否含有未知量,若含有,则输入未知量的取值,并且调用含有未知量表达式的计算函数{cout << "请按顺序输入未知数的取值,若未知数不够5个,请用0补齐:";double a1;double a2;double a3;double a4;double a5;cin >> a1;cin >> a2;cin >> a3;cin >> a4;cin >> a5;a = geteanswer(postfix, a1, a2, a3, a4, a5);//调用含有为质量的计算函数}if (!is_xyzmn(infix, i))//若表达式没有含未知量,则调用不含未知量的计算函数a = getpanswer(postfix);//调用不含为质量的计算函数cout << a << endl;//输出答案getchar();return 0;
}
欢迎指教!
转载于:https://www.cnblogs.com/surecheun/p/9648980.html
C++实现计算器功能(包括计算含未知量的式子),输出后缀表达式相关推荐
- 前、中、后缀表达式概述及转换+栈的计算器原理及代码分析(含完整源码)
目录: 1.前中后缀表达式的概述 2.中序表达式转前后缀表达式 3.运用栈的后缀表达式实现计算器原理步骤 4.代码实现和分析 1.前中后缀表达式的概述及相互转换 前缀表达式:运算符位于操作数之前. 中 ...
- java后缀表达式_表达式计算 java 后缀表达式
题目: 问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个表达式. 输出格式 输出这个表达式的值. 样例输入 1-2+3*(4-5) 样例 ...
- java实现多功能科学计算器(包括进制转换,三角函数,四则运算等)
多功能科学计算器(包括进制转换,三角函数,四则运算等) Basic Framework calculator.java package myCalculator; import java.awt.*; ...
- 用统计功能计算机计算js,js实现计算器功能
本文实例为大家分享了js实现计算器功能的具体代码,供大家参考,具体内容如下 知识点 eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码. 代码如下 js计算器 计算器 .h ...
- java poker_poker21 21点 Java 可实现基本功能,包括计算双方点数,显示输赢,计分 Games 游戏 247万源代码下载- www.pudn.com...
文件名称: poker21下载 收藏√ [ 5 4 3 2 1 ] 所属分类: Games 开发工具: Java 文件大小: 62 KB 上传时间: 2015-11-18 下载次数: 0 ...
- html编程计算,js html实现计算器功能
本文实例为大家分享了html实现计算器功能的具体代码,供大家参考,具体内容如下 代码: var numresult; var str; function onclicknum(nums) { str ...
- 用计算机怎么计算sh 3,Shell 实现简单计算器功能
Shell 实现简单计算器功能,脚本如下: [root@nfs scripts]# cat jisuan.sh #!/bin/bash print_usage(){ printf $"USA ...
- python编程计算器_Python设计实现的计算器功能完整实例
本文实例讲述了Python设计实现的计算器功能.分享给大家供大家参考,具体如下: 通过利用PYTHON 设计处理计算器的功能如: 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/ ...
- python课程设计计算器_Python设计实现的计算器功能完整实例
本文实例讲述了Python设计实现的计算器功能.分享给大家供大家参考,具体如下: 通过利用PYTHON 设计处理计算器的功能如: 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/ ...
- 使用jquery实现的计算器功能
晚上做了一个jQuery的项目,使用jQuery实现了一个简单的计算器功能,可以实现连加,连减,混合计算,括号内优先计算,代码如下: css部分: 1 <style> 2 .main{ 3 ...
最新文章
- ionic之自定义 ion-tabs 图标
- ImportError: DLL load failed: 找不到指定的模块
- xcode7,AFN不能使用的问题
- 查询用户分配角色TCODE
- 序列化与反序列化存储、updatepanel
- STM32Cube_FW_F1_V1.0.0固件库学习(四)外部中断 中
- ssma5.3_适用于Oracle的Microsoft SQL Server迁移助手(SSMA)v7.1
- 随手记_科研攻略_好的idea的产生
- serv-u启动管理控制台后提示脚本错误解决方案
- 不同平台安装python的方式一样吗_Python软件的正确安装方式
- 二维码解码器(zbar-0.10+ opencv-2.4.10+VS2010)完整实例含源代码
- 计蒜客 - T1212 仙岛求药 BFS+DFS剪枝
- 厉害了!第一款国产5G芯片,华为海思1020即将诞生!
- 如何教你真正的懂得色温?
- 面试——数据库常问问题
- 质数——夏洛克和他的女朋友
- zabbix随堂笔记
- iWO(联通3G详单及套餐使用情况查询工具)更新至v0.8
- 网易严选——迅速崛起的新消费品牌
- 影视网QQ群机器人接口对接 苹果CMS视频jiexi站
热门文章
- Java 基础类库:System、Runtime、Object、Math、日期、时间
- 通过url链接登录其他系统
- 同步与异步、异步与回调
- SSH2框架多数据源配置原理和方式
- onclick与addEventListener的区别
- xilinx spartan-3a iob
- python+requests+pytest_Python+Requests+Pytest 在window下的安装(附pip升级过程遇到的问题)...
- [RK3399][Android7.1] ADB功能怎么Debug
- fatal error: highgui.h: No such file or directory
- automake 安装及使用