目录

1.需求分析

2.主要难点——逆波兰算法

2.1 中缀表达式转换为后缀表达式

2.2 后缀表达式的计算

3.编程实现

3.1  C/C++版本

3.2  Qt版本

4.参考资料


1.需求分析

编程实现一个科学计算器(类似于Windows自带的计算器),要求能够实现加减乘除混合运算,并且能够识别括号,优先级正确。

下面是本博客的Qt版本的计算器效果图

2.主要难点——逆波兰算法

2.1 中缀表达式转换为后缀表达式

我们日常所用的数学表达式(如5+3)都是中缀表达式,中缀表达式是人容易理解的表达式。后缀表达式又叫做逆波兰表达式,对计算机来说,计算中缀表达式是很困难的,但是计算后缀表达式却非常容易,所以我们先把中缀表达式转化成后缀表达式来计算。下面的动态图和算法流程图可以很好的演示整个转换的过程:

图1   中缀表达式转后缀表达式的动态图

图2   中缀表达式转后缀表达式的流程图

2.2 后缀表达式的计算

后缀表达式的计算是比较简单的,基本思路就是遇到操作符就将操作数出栈并根据操作符进行计算,并将结果进栈,如果没有遇到操作符,就直接将操作数进栈。下图是具体的流程图,注意下面的代码使用'\0'作为表达式的终止符号(本人偷懒使用了别人的流程图)

图3   后缀表达式的计算---动态图

图4   后缀表达式的计算----流程图

3.编程实现

3.1  C/C++版本

在编程的时候,刚开始准备使用C语言,编程的过程中发现,在中缀转后缀表达式的时候需要一个存放字符型元素的栈,而后缀表达式的计算中又需要一个存放double型元素的栈,这样一来,就需要分别编写两个栈,很麻烦。下面的代码是直接用C++的类模板来实现的,程序比C语言简单很多,当然纯粹用C语言肯定也是没有任何问题的。

实际编程中还需要考虑正负号,因为‘+’和‘-’有时候不表示加减,为了解决这个问题,可以将负数-a看成是0-a,把正数+a看成0+a,这样一来,正负号的问题也解决了。

(1)类的声明    calculator.h

#ifndef CALCULATOR_H
#define CALCULATOR_Henum MAXSIZE
{STACK_INIT_SIZE=20,//定义初始最大容量STACKINCREMENT=10,//栈满的时候,动态增加容量,每次增加10个元素空间MAXBUFFER=10,//最大缓冲区MAX_EXP_LEN=100//表达式最长为100
};template<typename ElemType>
class Calculator
{
public:struct sqStack{ElemType *base;//指向栈顶ElemType *top;int stackSize;//当前栈的最大容量};Calculator();~Calculator();void Push(ElemType e);bool Pop(ElemType &e);void clearStack();int StackLen();int Calculation(char Postfix[]);//后缀表达式的计算bool Infix2Postfix(char Infix[],char Postfix[]);//中缀表达式变为后缀表达式private:sqStack s;};#endif // CALCULATOR_H

(2)类的实现  calculator.cpp

#include "calculator.h"
#include <stdio.h>template<typename ElemType>
Calculator<ElemType>::Calculator()
{s.base=new ElemType[STACK_INIT_SIZE];//栈底指向申请空间的首地址if(s.base==NULL)//申请失败exit(0);s.top=s.base;//top总是指向有效元素的下一个空间(栈顶),top中没有数据s.stackSize=STACK_INIT_SIZE;
}//销毁栈,将内存空间释放
template<typename ElemType>
Calculator<ElemType>::~Calculator()
{delete []s.base;
}template<typename ElemType>
void Calculator<ElemType>::Push(ElemType e)
{if(s.top-s.base>=s.stackSize){s.base=(ElemType *)realloc(s.base,(s.stackSize+STACKINCREMENT)*sizeof(ElemType));//        realloc是申请一个新的空间,并将旧的内容拷贝到新的空间,还会释放以前的空间if(s.base==NULL)exit(0);s.top=s.base+s.stackSize;//因为重新分配了空间,所以重新设置栈顶s.stackSize=s.stackSize+STACKINCREMENT;//当前栈的最大容量变大了}*(s.top)=e;s.top++;
}template<typename ElemType>
bool Calculator<ElemType>::Pop(ElemType &e)
{if(s.top==s.base)return false;//空栈e=*(--(s.top));return true;
}//清空栈,不改变物理空间
template<typename ElemType>
void Calculator<ElemType>::clearStack()
{s.top=s.base;
}//计算栈的当前容量(存储的数据量或者元素个数)
template<typename ElemType>
int Calculator<ElemType>::StackLen()
{return s.top-s.base;
}template<typename ElemType>
int Calculator<ElemType>::Calculation(char Postfix[])
{int i=0,j;char c;char str[MAXBUFFER];double a=0,b=0;for(j=0;Postfix[j]!='\0';j++){//        c=Postfix[j];while ((Postfix[j]>=48)&&(Postfix[j]<=57)||Postfix[j]=='.') //输入的是数字{str[i]=Postfix[j];
//            printf("str[%d]=%c\n",i,c);i++;str[i]='\0';if(i>=10){printf("出错,输入的数据长度过大!\n");return -1;}//            scanf("%c",&c);j++;if((Postfix[j]==' ')){//                str[i]='\0';
//                printf("str[%d]=%c\n",i,Postfix[j]);a=atof(str);
//                printf("%f \n",a);Push(a);i=0;}}switch (Postfix[j]){case '+':Pop(a);if(!Pop(b))//防止这是符号位(单目运算符){Push(a);break;}Pop(b);
//            printf("%f+%f=%f\n",b,a,b+a);Push(b+a);break;case '-':Pop(a);if(!Pop(b))//{Push(-a);break;}
//            printf("%f-%f=%f\n",b,a,b-a);Push(b-a);break;case '*':Pop(a);Pop(b);
//            printf("%f*%f=%f\n",b,a,b*a);Push(b*a);break;case '/':Pop(a);if(a==0){printf("除数不能为零 !\n");return -1;}Pop(b);Push(b/a);break;default:break;}}Pop(a);return a;}template<typename ElemType>
bool Calculator<ElemType>::Infix2Postfix(char Infix[],char Postfix[])
{Calculator<char> s;int i=0,j=0;char e;printf("中缀表达式为:");while (Infix[j]!='\0'){while(Infix[j]>='0' && Infix[j]<='9'){printf("%c",Infix[j]);Postfix[i++]=Infix[j];j++;if(Infix[j]<'0' || Infix[j]>'9'){Postfix[i++]=' ';printf(" ");}}switch (Infix[j]){case ')':s.Pop(e);while ('('!=e){printf("%c ",e);Postfix[i++]=e;Postfix[i++]=' ';s.Pop(e);}break;case '+':case '-':if(0==s.StackLen())s.Push(Infix[j]);else{do{s.Pop(e);if('('==e){s.Push(e);}else{printf("%c ",e);Postfix[i++]=e;Postfix[i++]=' ';}}while (s.StackLen() && '('!=e);s.Push(Infix[j]);}break;case '*':case '/':case '(':s.Push(Infix[j]);break;case '\0':break;default:printf("\n输入格式错误!\n");return -1;}if('\0'==Infix[j])break;j++;}while (s.StackLen()){s.Pop(e);printf("%c ",e);Postfix[i++]=e;Postfix[i++]=' ';}Postfix[i]='\0';printf("\n");return true;
}

(3)测试程序 main.cpp

#include <iostream>
#include "calculator.cpp"
#include <stdio.h>
using namespace std;int main()
{Calculator<double> cal;char Infix[MAX_EXP_LEN],Postfix[MAX_EXP_LEN];gets(Infix);double sum;cal.Infix2Postfix(Infix,Postfix);sum=cal.Calculation(Postfix);printf("最终计算结果为:%f\n\n",sum);return 0;
}

(4)测试结果

下面计算8+(6-3)*(-5)+10/2:

3.2  Qt版本

Qt实现的科学计算器有较友好的界面,效果图在本文的开头。

Qt的编程比较复杂一些,在这个程序里面不仅添加了界面,而且还增加了清除数据,后退一个数字等功能,用了四个文件来编写程序,基本思路跟上面的C++类似,由于程序太长,这里就不放代码了。我已经将完整的源代码上传,有需要的小伙伴可以前去下载(点击进入下载界面),没有积分的小伙伴可以私聊我。

4.参考资料

[1] 流程图来自https://blog.csdn.net/hackerain/article/details/7682891?locationNum=15

[2]中缀表达式转后缀表达式的动态图来自https://www.cnblogs.com/lulipro/p/7450886.html

8.用C/C++实现一个科学计算器———(超级详细完整,包含C/C++版本和Qt版本)相关推荐

  1. 共享一个科学计算器(js版本)

    效果图: 代码如下,可将代码存为html.用浏览器直接运行,或者点击'运行代码'按钮直接运行 <HTML><HEAD><TITLE>科学计算器</TITLE& ...

  2. java作业:用GUI实现一个科学计算器的设计

    问题描述 代码实现 import javax.swing.*; import java.awt.*;public class MyCalc extends JFrame {private void i ...

  3. 用计算机算出手机号码,手机计算器开根号怎么按(万能科学计算器在线使用方法)...

    在日常生活中,因为手机的方便些,也越来越成为我们生活中不可或缺的一部分了.因此,大家对手机也并不陌生,那么你的手机里有自带的计算器功能吗?你知道手机里自动的计算器功能如何正常使用吗?你知道手机自带的计 ...

  4. html+css+js实现科学计算器

    代码地址如下: http://www.demodashi.com/demo/13751.html 项目描述 纯html+css+js实现一个科学计算器,支持平方开方指数对数等基本函数,支持键盘输入,有 ...

  5. 关于计算机flash的毕业论文,用flash制作科学计算器

    1.引言 进入21世纪,计算机网络发展越来越迅猛.随着计算机的大量使用,计算工具和科学技术飞速迅猛发展,以及其在线网络资源共享和数据通信技术的运用,为人们带来了很多便利,计算机网络正在改变着人们的工作 ...

  6. 用Python语言写个科学计算器

    自学Python语言一个月,还是小白,发一个科学计算器的代码,希望大家批评指正,共勉嘛. calculator.py from tkinter import * from functools impo ...

  7. 基于51单片机的科学计算器

    科学计算器 1.任务 设计制作一个科学计算器.  2. 要求 (1)按数字 0-9 时应发出蜂鸣器声音,数越大,频率越高. (20 分) (2) 完成任意两位数(范围 0-99)的加减乘除运算,结果只 ...

  8. Android Studio小作业:科学计算器

    背景 上一章,我们完成基于Xamarin.Android的简单计算器 今天突发奇想,做一个科学计算器 支持标准四则运算.括号.小数点.三角函数.log.ln.倒数.阶乘.幂.算数平方根.百分数 开发环 ...

  9. 华丽科学计算机,华丽科学计算器 正式登陆首派Astore

    2011-8-2 11:43 [天极网手机频道]计算器是日常工作生活中一个重要的工具,华丽科学计算器 RealCalc Scientific Calculator是一款实用性超强的科学计算器应用程序, ...

  10. 科学计算机怎么编程玩,如何通过可编程科学计算器在另一个设备中运行本机MFP语言编写的...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 MFP语言的一个重要功能就是通过call ... endcall语句实现对并行计算的支持.MFP语言实现多线互不干扰并行计算的基本原理是采用沙盒机制.每一 ...

最新文章

  1. 操作系统--内存管理方式
  2. 可逆素数编程c语言,巧用C语言求四位的可逆素数
  3. Windows下Mysql 的安装和卸载
  4. 【ZOJ - 3211】Dream City (01背包类问题,贪心背包)
  5. Linux中 C++ main函数参数argc和argv含义及用法
  6. PyQt5笔记(03) -- 消息框
  7. css为什么要用浮动_CSS问题和解决
  8. Jupyter Lab——如何添加没有出现的kernel
  9. python最短路径例子_[python]dijkstra 算法的 加权的最短路径 案例
  10. python还能活多久_啥?python以后没活路?
  11. WPS文字常用排版快捷键
  12. uni-app引入阿里图标【单色】
  13. 阿里成立“平头哥”半导体公司,明年推神经网络芯片
  14. hdu1069 最长下降子列
  15. 分布式的坑(队列、缓存、分库分表、事务)
  16. python培训班深圳-深圳python人工智能培训班
  17. 一起学OCP:oracle-082题库及解析(21-40)
  18. w7计算机防火墙无法更改,w7防火墙无法更改该怎么办
  19. Arduino Ethernet构建简易服务器
  20. 查看SCI期刊引用格式步骤记录

热门文章

  1. oracle教程课件,Oracle入门教程(PPT课件)
  2. PopClip for Mac 增强型复制粘贴工具
  3. windows10系统超全面优化攻略
  4. 【论文笔记】ARBITRAR: User-Guided API Misuse Detection
  5. Python四舍五入问题详解
  6. 单片机延时C语言程序
  7. 加了阿里云CDN出现504
  8. 用计算时间差计算出天数
  9. [ XJTUSE ]JAVA语言基础知识——7.11 JTree、TreeModel实现树
  10. 小女子菜鸟一枚,因本科毕业设计第一次接触安卓开发……图片上传问题求教