编号:学号:课程设计教学院课程名称题目专业班级姓名同组人员指导教师2013 年 6 月22 日(完成时间)目录一.概述 (2)二.总体方案设计 (4)三.详细设计 (6)四.程序的调试与运行结果说明 (14)五.课程设计总结 (14)六.附录 (16)参考文献 (3233)(“目录”要求必须自动生成)一概述(宋体,三号,加粗,居中)1.课程设计的目的(小标题,宋体,四号,加粗,左对齐顶格)(1).理解和掌握该课程中的有关基本概念,程序设计思想和方法。
(2).培养综合运用所学知识独立完成课题的能力。
(3).培养勇于探索、严谨推理、实事求是、有错必改,用实践来检验理论,全方位考虑问题等科学技术人员应具有的素质。
(4).掌握从资料文献、科学实验中获得知识的能力,提高学生从别人经验中找到解决问题的新途径的悟性,初步培养工程意识和创新能力。
2.课程设计的要求算术表达式求值程序实现以下功能:(1)构造一个空栈S,初始条件:栈S已存在(2)用P返回S的栈顶元素(3)插入元素ch为新的栈顶元素(4)删除S的栈顶元素(5)判断字符是否是运算符,运算符即返回1(6)判断运算符优先权,返回优先权高的(7)输入表达式(8)返回表达式的最终结果。
二总体方案设计a)需求分析该程序能实现算术四则运算表达式的求值,显示运算过程。
输入的形式:表达式,例如5*(3+7)#。
包含的运算符只能有'+'、 '-'、'*'、 '/'、 ' (' ') ';程序所能达到的功能:对表达式求值并输出。
b)总体设计本程序使用的是编程工具是Visual c++ 6.0,实现了运算器的功能和仿真界面(大体界面如下图所示)。
在基本要求的基础上,运算数可以是实数类型,同时增加了乘方运算的功能;可以实现对负数的运算,例如用户输入表达式6*(-0.25),则程序会在负号的前面自动加上一个0。
1)算符包括加(+)、减(-)、乘(*)、除(/)、乘方(^);另一个称作OPND,用以寄存操作数和运算结果,操作数可以是float型的浮点数。
算法的基本思想是:2)首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素;依次读入表达式中的每个字符,若是操作数(浮点数)则进OPND栈,若是运算符(+、—、*、/、^)则和OPTR栈的栈顶运算符比较优先权后作相应操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为“#”)。
3)编写一个原型为void strtofloat(char str[ ],int n,int i),把一个数字串转换为一个实型数,并压入运算数栈中。
(整个程序的源代码见附录,并有具体解释)c)数据结构与模块说明1)主要采用DLL封装和前台MFC界面使用到Layout菜单中的Align功能对各个按钮进行对其,使界面更加整洁。
拖出的控件有上面的一个Edit控件用于显示数字,Button控件用于处理鼠标的消息。
2)建立的变量,控件的命名,对应的消息处理函数对应表ID CAPTION Message HandlerIDD_CALC_DIALOG 计算器N/AIDC_NUM0 0 OnNum0IDC_NUM1 1 OnNum1IDC_NUM2 2 OnNum2IDC_NUM3 3 OnNum3IDC_NUM4 4 OnNum4IDC_NUM5 5 OnNum5IDC_NUM6 6 OnNum6IDC_NUM7 7 OnNum7IDC_NUM8 8 OnNum8IDC_NUM9 9 OnNum9IDC_PT .OnPtIDC_DIV / OnDivIDC_MUL * OnMulIDC_MIN - OnMinIDC_ADD + OnAddIDC_CLEAR Clear OnClearIDC_EQU = OnEquIDC_RESULT N/A N/AOnCal(double num) double poz; //保存小数点的位置,初始化为1,表示poz-1个小数点。
double m_Dis; //Edit控件上需要显示的数字BOOL point_flag; //小数点表示位,判定是否是小数,是小数为1,不是小数为0。
double numfirst; //保存计算过程中的前一个数字,double numsecond;//保存计算过程中的第二个数字char op;//记录当前的计算符号,可以为’+’,’-’,’*’,’/’,’=’,’c’,’n’变量初始化:poz=1;m_Dis = 0.0;numfirst=0;numsecond=0;op=0;三详细设计1:数据结构与模块说明:设定栈的抽象数据类型定义:ADT Stack{数据对象:D={ai|ai属于CharSet,i=1,2,……n,n>=0} 数据关系:R1={<ai-1,ai>|ai-1,ai属于D,i=2,……,n} 基本操作:InitStack(&S)操作结果:构造一个空栈。
GetTop(S,&e)初始条件:栈S已存在。
操作结果:若栈S不空,则以e返回栈顶元素。
Push(&S,e)初始条件:栈S已存在。
操作结果:在栈S的栈顶插入新的栈顶元素e。
Pop(&S,e)初始条件:栈S已存在。
操作结果:删除S的栈顶元素,并以e 返回其值。
}ADT Stack2、栈的类型struct SqStackTR struct SqStackND{ {float *base; //栈底指针char *base; //栈底指针float *top; //栈顶指针char *top; //栈顶指针int stacksize; //栈的长度int stacksize; //栈的长度}OPND; //定义运算数栈}OPTR; //定义运算符栈3、模块说明按照运算器界面Button的类型,本程序分为三个模块:运算数和运算符事件响应函数模块、“=”事件响应函数模块、“清除”事件响应函数模块。
(1)运算数和运算符事件响应函数完成的主要功能是向Edit1->Text中输入运算数和运算符,这些Button分别是标有“1”、“2”、“3”,“4”,“5”,“6”,“7”,“8”,“9”,“0”,“.”,“+”,“-”,“*”,“/”,“(”,“)”,“^”的Button。
函数的另外一个任务是把这些字符存入一个事先定义好的全局变量字符型数组s中。
举一例说明(其它类同):void __fastcall TForm1::Button17Click(TObject *Sender){Edit1->Text=Edit1->Text+'('; // 向Edit1->Text中输入运算符“(”s[m++]='('; //把字符“(”存入数组s,m是全局变量}(2)、“=”事件响应函数完成的功能是计算Edit1->Text中表达式的值,并将结果送入文本框Edit2->Text中。
这是整个源程序的主体部分。
这部分的伪码算法如下:void __fastcall TForm1::Button12Click(TObject *Sender){把“#”送入数组s,“#”就成了数组中的最后一个元素;初始化字符栈,并把“#”压入字符栈中;逐个读出字符数组s中的元素;while(s[m]!=’#’&&GetTopTR(&OPTR)!='#'){if(读出的不是一个数字){直到读入下一个字符是一个字符,就把刚才读入数字串用一个函数名字为strtofloat 的函数转化成一个实型数,并把它压入数字栈中;如果下一个字符是“-”,就作标记tack=0,说明用户没有输入负数}else{判断用户是否输入了负数,如果是,就把0压入数字栈中。
例如用户输入了(-2.5),程序就把它转化成(0-2.5)进行运算。
switch(Precede(GetTopTR(&OPTR),s[m])) //Precede比较两个运算符的优先级{case '<': PushTR(&OPTR,s[m]); //把s[m]压入符号栈中m++; //找到下一个符号break;case '=': PopTR(&OPTR);m++;break;case '>': theta=PopTR(&OPTR); //运算符出栈,并赋给thetanum_2=PopND(&OPND); //运算数出栈,并赋给num_2num_1=PopND(&OPND); //运算数出栈,并赋给num_2zancun=Operate(num_1,theta,num_2); //运算结果赋给zancunPushND(&OPND,zancun);break; //把运算结果压入栈中} //switch语句结束} // else语句结束} //while语句结束把栈顶元素取出并使之显示在文本框Edit2->Text中;} //“=”事件响应函数结束(3)、“清除”事件响应函数比较简单,作用是把文本框Edit1->Text和文本框Edit2->Text清空,并准备进行下一个算术表达式的运算。
void __fastcall TForm1::Button20Click(TObject *Sender){Edit1->Clear( ); //清空文本框Edit1->TextEdit2->Clear( ); //清空文本框Edit2->Textm=1; //为新的表达式的输入作好准备}(所完成的具体功能及用到的算法(详细分析)。
程序流程图:主要部分的详细流程图)开始输入表达式特殊情况处理将数与运算符分开找到最内层一堆括号将括号内表达式用指针带出将括号内表达式用指针带出进行只有加减乘除运算表达式求值用表达式值替换掉括号及括号间表达式取当前表达式首指针进行只有加减乘除运算表达式求值得出结果否是循环我所负责的部分算术符优先级的判定。
部分代码如下char Precede(char x,char y)//运算符优先级判断{int i,j;int from[5][5]={{0,0,-1,-1,1},{0,0,-1,-1,1},{1,1,0,0,1},{1,1,0,0,1},{-1,-1,-1,-1,0}};//定义一个二维数组存放算术符号的优先级switch(x){case '+':i=0;break;case '-':i=1;break;case '*':i=2;break;case '/':i=3;break;case '#':i=4;break;}switch(y){case '+':j=0;break;case '-':j=1;break;case '*':j=2;break;case '/':j=3;break;case '#':j=4;break;}if(from[i][j]==1)//说明运算符i的优先级比j的优先级高return '>';if(from[i][j]==-1)return '<';elsereturn '=';}程序中用switch将运算符转化为对应的数字,即:+ ——,0,- ——1,*——2,/ ——4,#——5.再用一个二维数组存储优先级,亮两两比较当数组中的元素form[i][j]=0时表示i所对应的运算符的优先级大于j。