8.用C/C++实现一个科学计算器

您所在的位置:网站首页 开方计算器app下载 8.用C/C++实现一个科学计算器

8.用C/C++实现一个科学计算器

2023-12-30 03:38| 来源: 网络整理| 查看: 265

目录

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_H enum MAXSIZE { STACK_INIT_SIZE=20,//定义初始最大容量 STACKINCREMENT=10,//栈满的时候,动态增加容量,每次增加10个元素空间 MAXBUFFER=10,//最大缓冲区 MAX_EXP_LEN=100//表达式最长为100 }; template 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 template Calculator::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 Calculator::~Calculator() { delete []s.base; } template void Calculator::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 bool Calculator::Pop(ElemType &e) { if(s.top==s.base) return false;//空栈 e=*(--(s.top)); return true; } //清空栈,不改变物理空间 template void Calculator::clearStack() { s.top=s.base; } //计算栈的当前容量(存储的数据量或者元素个数) template int Calculator::StackLen() { return s.top-s.base; } template int Calculator::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]=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 bool Calculator::Infix2Postfix(char Infix[],char Postfix[]) { Calculator s; int i=0,j=0; char e; printf("中缀表达式为:"); while (Infix[j]!='\0') { while(Infix[j]>='0' && Infix[j]


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3