1.问题描述
对于给定的一个表达式,表达式中可以包括常数、算术运行符(包括:“+”、 “-”、“*”、“/”、“%”(求余运算)、“^”(乘幂运算)、“!”(阶乘运算))和括 号,编写一个简单计算器,实现表达式的计算。
基本要求:从键盘输入一个正确的表达式,将表达式转换为对应的后缀表达式,并计算后缀 表达式的值。对于表达式中的简单错误(如,除数不能为零、负数无法求阶乘等),能够给出提 示,并给出错误信息;表达式中可以包括单个字母表示的变量。
提高要求:完成基本要求的基础上,能够支持一部分不规范的表达式(如,3-3+-6),支持 科学计数法表示的数(如,19971400000000 表示为:1.99714E13),并具有图形用户界面的简单计算器
2.需求分析
软件的基本功能:由键盘输入中缀表达式,程序可以将输入的中缀表达式转换成对应的后缀表达式,并计算后缀表达式的值。对于在输入时发生的简单错误,程序可以给出提示。本程序支持含负数、小数、多位数等多种操作数的处理,可以计算含加、减、乘、除、求余、求幂等多种运算符的表达式,并能判断表达式括号是否匹配。
输入/输出形式:用户可以通过控制台,根据输入提示。
输入形式:
①正确的不含字母变量的中缀表达式;
②含有简单错误的中缀表达式。
输出形式:
①对于正确的中缀表达式,可以输出其转化后的后缀表达式及表达式的计算结果;
②对于含有简单错误的中缀表达式,程序将自动输出错误提示,并给出错误信息。
测试数据要求:用户可以输入一个符合要求的中缀表达式,也可以输入一个包含简单错误的表达式。表达式中可以包括各种类型的常数以及负数等,操作符包括(+、-、*、/、%、^)等,同时表达式还可以包括各种括号。
- 概要设计
(1)抽象数据类型:
根据题目的要求,考虑用栈类型比较适合。
本程序总共设计了三个栈C1、C2、C3。C1用于存储输入的中缀表达式,C2为栈用于转化过程中对数和操作符进行压栈,C3用于元素出栈后进行相关运算,并将最终结果进行重新压栈。在栈操作的过程中用top变量,对栈内的存储情况进行标记。如果top=0则表示栈为空。
(2)主程序流程:
图1:主程序流程图
(3)模块调用关系:
本程序中函数包括:main函 数,adorn函数,fun函数,PrintList函数,input函数,Change函数,systemmenu函数,easycalculate函数,easymenu函数
- Main函数
通过switch-case函数对系统界面进行初步的实现,用户可以通过输入1、2或其他数字选择进入系统的不同功能。同时使用system函数对命令指示行进行DOS操作,实现在实现新功能时清除缓存区。
- adorn函数
此函数为装饰函数,通过ASCLL码判断如果是数字则将ASCLL码-48转换为字符,强制在字符串的结尾加上\n,方便计算字符串内的个数 。进而解决了系统无法区分数字与运算符的问题
- Fun函数
此函数的作用为判断括号是否匹配 (1匹配,0不匹配)。设置了两个字符变量L\R
- PrintList函数
将表达式最后计算的结果输出,如果为结果大于1000或小于0.001,则以科学计数法输出
- Input函数
对用户从键盘输入的数据进行读取,保存在字符类型的数组中,以便后续使用
- Change函数
- 此函数功能为将中缀表达式转换为后缀表达式并进行计算 ,函数首先会调 用Fun函数已检测表达式括号是否匹配,若不匹配则返回主函数。从左至右扫描 中缀表达式,遇到运算符时,比较其与s1栈顶运算符的优先级遇到操作数时, 将其压入s2遇到括号时如果是左括号’(’,则直接压入s1如果是右括号’)’, 则依次弹出s1栈顶的运算符,并压入s2中,直到遇到左括号’('为止,将这个 左括号从s1中弹出丢弃(这时候消除了一对括号)将s1中剩余的运算符依次弹 出并压入s2中依次弹出s2中的元素并输出,并将输出结果逆序,即得到后缀表 达式。从左至右扫描,若为数字,依次压入栈遇到运算符,依次弹出s1,s2, 计算s2(+,-,*,/)s1的结果并压入栈。
- systemmenu函数
本函数用于打印当用户进入系统时的操作界面,以便用户对系统可实现的操作功能进行选择。
- easycalculate函数
对简单的二元计算式进行‘+’‘-’‘*’‘/’的运算
- easymenu函数
- 此函数是简单计算器的系统界面,在该函数使用中通过调用easycalculate函数,对简单的二元运算式进行运算
函数调用关系如下:
图2:函数调用关系
4.详细设计
(1)实现概要设计的数据类型:
根据题目的要求,考虑用栈类型比较适合。
本程序总共设计了三个栈C1、C2、C3。C1用于存储输入的中缀表达式,C2为栈用于转化过程中对数和操作符进行压栈,C3用于元素出栈后进行相关运算,并将最终结果进行重新压栈。在栈操作的过程中用top变量,对栈内的存储情况进行标记。如果top=0则表示栈为空。
(2)主程序以及其它模块的算法描述:
主函数具体代码:
int main()
{
while(1)
{
system("cls");
systemmenu();
int n;
cin>>n;
switch(n)
{
case 1: system("cls");
while(1)
{
cout<<"欢迎来到简单计算器功能"<<endl;
cout<<"本功能支持'+''-''*''/'四种运算符号";
cout<<"[且运算符号需为英文字符]"<<endl;
easymenu();
int flag;
cout<<"*************************"<<endl;
cout<<"是否继续简单计算器功能?"<<endl;
cout<<"1-YES"<<endl;
cout<<"2-NO"<<endl;
cout<<"*************************"<<endl;
cin>>flag;
if(flag==2)
{
break;
}
}
break;
case 2: system("cls");//实现启动器的DOS功能,清除显示器屏幕上的内容,使DOS提示符到屏幕左上角
while(1)
{
fflush(stdin);//清除缓冲区的值
int count=0;
int i;
int j;
int m;
int n;
int top=0;
int v=-1;
int u=0;
adorn('-',90);
cout<<"**请输入需要计算的中缀表达式,直接回车即可,注意本系统只识别英文符号**:" <<endl;
cout<<"如果想退出本界面,请输入‘#’号键"<<endl;
input();
if(*c1=='#')
{
break;
}
else
{
Change(c1);
}
}
default:system("cls");
cout<<"**************"<<endl;
cout<<"感谢您的使用!" <<endl;
cout<<"我们下次再会!"<<endl;
cout<<"**************"<<endl;
goto over;
}
}
over:
return 0;
}
这个函数主要调用了实现功能的各个函数,并且对本程序实现的功能进行选择。若用户输入“1”则进入简单计算器的界面,若用户输入“2”进入中缀表达式转后缀表达式的界面,若输入其他数字则退出该程序。在进入每个界面后程序会调用system("cls");函数对DOS进行操作,清空命令指示行中的缓存信息。
图3:主函数关系流程
(3)其它模块的算法描述
表达式转换函数,并计算后缀表达式的值
功能:将中缀表达式转换为后缀表达式,其中infix是输入的中缀表达式,
Char Change(char c1[])
{
fflush(stdin);