C语言课程设计.简易计算器.报告

xxxx大学信息科学与工程学院

课程设计报告

班        级:       通信工程一班               

姓名 (学号):         xxx                                 

实验项目名称:        简易计算器                          

实验室(中心):信息科学与工程学院信息技术实验室 

指 导 教 师 :          xxx                      

实验完成时间:  2012  年  6  月  19  日

目录

一:课程设计题目............................................................................ 3

二:功能描述.................................................................................... 3

三:概要设计.................................................................................... 4

四:详细设计.................................................................................... 5

五:测试结果及存在的问题.............................................................. 9

六:课程设计心得体会................................................................... 12

七:附录......................................................................................... 12


一、题目:

                      简易计算器设计

二、功能描述:

           此简易计算器根据算符优先算法原则可以计算由“+-*/,(,)”

组成的任意算术表达式的值。其中此程序中包含对负数和字符数据转

换功能。

如:-9+((2+3*9/8-5/(-3);

三、概要设计:

根据算符优先算法设计将函数功能模块分布如下:

       利用结构体数组中脚码的变换达到符号和数据进栈和出栈的目的。

C语言课程设计.简易计算器.报告

四、详细设计:

各功能模块的实现过程如下:

   1:栈的应用:

通过运用结构体数组中top值的改变来达到数据进栈和出栈的目的,而栈的初始化只需将top的初始值赋为-1即可                                              

                                                         

    

                                                                                

 

 2:表达式负数的处理(Translate函数完成):

C语言课程设计.简易计算器.报告

算法说明 :

函数中,先扫描数组,若s[0]=-’,则将数组的所有元素向后   移一位且首位赋值为‘0’,若数组首位之后含有形如(-5)则将负号及其以后的元素全向后移一位且负号位置赋值为‘0’,然后返回新的数组;

3:表达式正误的判断(Can函数完成):

    

     函数说明函数中将错误归为几类:括号的完整性、运算符后的数据类型、除号后的数据不能为0、小数点及运算符不能多个在一起、右括号后的数据必须为运算符或结束标志;函数通过ps记录对这些错误的判断,并返回结果;

4:进栈和出栈:

 

说明 :

运算符和数据的进栈是通过给结构体数组赋值并增加top的值来记录栈的栈顶元素的位置以便取用;出栈是使top的减1后的那个数组中的数据作为新栈的栈顶元素,并返回栈顶元素.即实质上是通过改变数组的位置来达到进栈出栈;

                                                  

                                                                 

  

 

 5:字符串数据转换成浮点型数据(Getdouble函数完成):

    

函数说明 :

             从字符数组的运算符开始扫描,直到遇到下一个运算符结束,然后将这两个运算符间的字符记录在数组S中,再用库函数atof将字符数据转换成浮点型数据并返回数据和数组a中新的元素的起点(即扫描到的第二个运算符)

   6:算符优先级的比较:

    

函数说明 :   

        此函数是记录运算符栈的栈顶元素在运算符集合中的位置与读入运算符在运算符集合中的位置,将这两个值作为运算符优先级表数组的脚码,然后返回这个元素所代表的字符;

                                                       

   7:算符优先算法求表达式的值的核心算法:

        说明:此函数中使用两个工作栈,一个是OPTR,用以寄存运算符;另一个是OPND,用以寄存浮点型数据。基本思想是:首先置数栈为空栈,表达式的起始符号为‘#’算符栈的栈底元素;然后依次读入表达式中的每一个字符,若为数则进OPND数栈,若为运算符则和OPTR算符栈的栈顶运算符比较优先级后,如果栈顶算符优先级低,则此算符进栈并返回新的栈顶算符;如果栈顶算符优先级高,则取算符栈栈顶算符theta并删除此算符,同时去数栈的最上面的两个数ab并删除这两个数,作a theta b运算并将结果进数栈;如果两个算符优先级相同,则删除算符栈顶算符并返回新的栈顶算符。直到整个表达式求值完毕(OPTR的栈顶算符和当前读入的字符均为‘#’时求值完毕)

     

程序框图如下:

 

五、测试结果及存在的问题:

  1:系统运行效果:

输入界面:

     

正确的计算:

        

再计算界面

错误报告:

                              

修正再计算:

                                           

     

2:存在的不足及预期的解决办法:

不足之处:

1计算器的操作界面不是很美观;

2而且程序循环使用不能在指定的位置退出;

3目前只能用于计算+-*/四则运算;

                                     

   预期的解决办法 :                                   

            1查询资料学习了解操作界面的制作方法及需要的技巧;                    

            2查询相关资料了解学习有关处理字符数组赋值的相关问题

              (即处理字符数组赋值只取到预定的位置)

            3学习了解相关的库函数的功能以增加计算器的计算功能

              (如计算器的次方、开方、π、等的运算) .                                   

                                           

六、课程设计心得体会:

心得体会:

            我对编程是有很浓厚兴趣的。在编程的过程中,我深深地体会到力不从心有些知识没能深入地理解和掌握以及VC++的许多功能没能探索和了解使我编程时有好多的思想运用不上(如设计一个美观的操作界面)。另外,我也感受到了数据结构的重要性,有了结构才能将好的思想付诸实践。同时经过查询资料了解到栈由多种运用方法,其中包括栈的顺序存储结构和链式存储结构,栈是计算表达式的经典应用。数据结构中的许多结构都是很经典思想,只有把编程语言和数据结构都熟练掌握的情况下,才能做出一些很好的作品。在编程过程中,虽然有时候是很发闷的,尤其是程序无错但结果不对,但是在完成一个完整的程序时所带来的喜悦是其它事情所不能替代的。我很喜欢编程,即使我的知识和能力有限,但我相信经过努力,一切皆有可能。

七、附录:

  程序源代码如下:

#include

#include

#include

//算符优先级表

char First[7][7]=

{

            //'+','-','*','/','(',')','#'

   /*'+'*/ '>','>','<','<','<','>','>',

   /*'-'*/ '>','>','<','<','<','>','>',

   /*'*'*/ '>','>','>','>','<','>','>',

   /*'/'*/ '>','>','>','>','<','>','>',

   /*'('*/ '<','<','<','<','<','=',' ',

   /*')'*/ '>','>','>','>',' ','>','>',

   /*'#'*/ '<','<','<','<','<',' ','='

};

//运算符数组

char OP[7]={'+','-','*','/','(',')','#'};

//数据结构体

typedef struct

{

       double data[50];

       int top;

}OPND_Stack;

//运算符结构体

typedef struct

{

       char data[50];

       int top;

}OPTR_Stack;

//初始化运算符栈函数

void InitStack_R(OPTR_Stack *a)

{

       a->top=-1;

}

//初始化数据站函数

void InitStack_D(OPND_Stack *a)

{

       a->top=-1;

}

//运算符进栈函数

void Push_R(OPTR_Stack *a,char b)

{

       a->top++;

       a->data[a->top]=b;

}

//数据进栈函数

void Push_D(OPND_Stack *a,double b)

{

       a->top++;

       a->data[a->top]=b;

}

//取运算符栈顶符函数

void GetTop_R(OPTR_Stack *a,char *b)

{

       *b=a->data[a->top];

}

//取数据栈顶数函数

void GetTop_D(OPND_Stack *a,double *b)

{

       *b=a->data[a->top];

}

//判断数据是否为运算符函数

int In(char a,char *s)

{

       for(int i=0;i<7;i++)

              if(a==s[i])

                     return 1;

       return 0;

}

//算符优先级判断函数

char Precede(char a,char b)

{

       int m,n;

       for(int i=0;i<7;i++)

       {

              if(a==OP[i])

                     m=i;

              if(b==OP[i])

                     n=i;

       }

       return First[m][n];

}

//删除运算符栈顶元素,并取新栈的栈顶元素

void Pop_R(OPTR_Stack *a,char *b)

{

       a->top--;

       *b=a->data[a->top];

}

//取数据站的栈顶元素,并从栈中删除此元素

void Pop_D(OPND_Stack *a,double *b)

{

       *b=a->data[a->top];

       a->top--;

}

//二元运算函数

double Operate(double a,char theta,double b)

{

       switch(theta)

       {

       case'+':return a+b;

       case'-':return a-b;

       case'*':return a*b;

       case'/':return a/b;

       default:return 0;

       }

}

//将字符串转换成浮点型数据

double Getdouble(char *a,int *b)

{

       double x;char s[50];

       int m=0,n;

       n=strlen(a);

       for(int i=*b;i

              if(In(a[i],OP)==1)

              {

                     m=i;break;

              }

       for(i=*b;i

              s[i-*b]=a[i];

       strcat(s,"\0");

       x=atof(s);

       *b=m;

       return x;

}

//算符优先算法求值核心函数

double EvaluateExpression(char *s)

{

       OPND_Stack OPND;

       OPTR_Stack OPTR;

       char ch,theta;

       double x,a,b;

       int k=0;

       strcat(s,"#");

       InitStack_R(&OPTR);Push_R(&OPTR,'#');

       InitStack_D(&OPND);

       GetTop_R(&OPTR,&ch);

       while(s[k]!='#'||ch!='#')

       {

              if(In(s[k],OP)==0)

              {

                     x=Getdouble(s,&k);

                     Push_D(&OPND,x);

              }

              else

              {

                     switch(Precede(ch,s[k]))

                     {

                     case'<':Push_R(&OPTR,s[k]);

                                k++;

                                   break;

                     case'=':Pop_R(&OPTR,&ch);

                               k++;

                               break;

                     case'>':GetTop_R(&OPTR,&theta);Pop_R(&OPTR,&ch);

                                Pop_D(&OPND,&b);Pop_D(&OPND,&a);

                                   Push_D(&OPND,Operate(a,theta,b));

                                   break;

                     }

              }

              GetTop_R(&OPTR,&ch);

       }

       GetTop_D(&OPND,&x);

       return x;

       InitStack_R(&OPTR);Push_R(&OPTR,'#');

       InitStack_D(&OPND);

}

//判断表达式是否输入正确.

int Can(char a[],int n)         

{

       int p=0,s=0,t=0;

       for(int i=0;i

       {

              if(a[i]=='('||a[i]==')')

                     p++;

              if((a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/')&&((a[i+1]<'0'&&a[i+1]!='(')||a[i+1]>'9'))

                     s++;

              if(a[i]=='/'&&a[i+1]=='0')

                     s++;

              if((a[i]=='('&&(a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/'))||(a[i]==')'&&a[i+1]=='('))

                     s++;

              if(a[i]==')'&&a[i+1]!='\0'&&(a[i+1]!='+'&&a[i+1]!='-'&&a[i+1]!='*'&&a[i+1]!='/'))

                     s++;

              if(a[i]=='.'&&a[i+1]=='.')

                     s++;

       }

       if(p%2==0&&s==0)

              return 0;

       return 1;

}

//负数转换函数

void Translate(char *s)

{

       char b[80];int k,t;

       if(s[0]=='-')

       {

              b[0]='0';

              b[1]='\0';

              strcat(b,s);

              strcpy(s,b);

       }

       t=strlen(s);

       k=t;

       for(int i=0;i

       {

              if(s[i]=='('&&s[i+1]=='-')

              {

                 k=i+1;

              for(int j=t;j>=k;j--)

                 s[j]=s[j-1];

              s[k]='0';

              s[t+1]='\0';

              }

         t=strlen(s);

         k=t;

       }

}

//主函数

void main()

{

       system("color B0");

       char a[80];int m;char b[80];

       printf("============简易计算器============\n");

       printf("[四则运算.:-1+(2+3)*9/(-2)-6].\n请输入一个表达式:\n");

       while(1)

       {

              gets(a);

              strcpy(b,a);

              Translate(a);

              while(1)

              {

                     int  p;

                     m=strlen(a);

                     p=Can(a,m);

                     if(p==0) break;

                     system("color F4");

                     printf("输入错误.请从新输入表达式:\n");

                     gets(a);

                     strcpy(b,a);

                     Translate(a);

              }

              system("color B0");

              printf("=*=*=*=*=*=*表达式结果=*=*=*=*=*=*\n");

              printf("该表达式的结果为:\n%s=%-10.3lf\n",b,EvaluateExpression(a));

              printf("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*\n");

              printf("继续使用[四则运算.:-1+(2+3)*9/(-2)-6].<关闭退出>.\n请再输入一个表达式:\n");

       }

}

相关推荐