Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1048780
  • 博文数量: 254
  • 博客积分: 10185
  • 博客等级: 上将
  • 技术积分: 2722
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-25 15:04
文章存档

2011年(8)

2009年(1)

2008年(31)

2007年(214)

分类: C/C++

2007-07-25 16:18:11

现将大一时编写的堆栈计算器2.0版全部放出,供大家来研究学习。
希望各位喜欢,并且指出错误。

#include "stdafx.h"

#include "string.h"

#include "stdio.h"

#include "conio.h"

#include "stdlib.h"

#include "math.h"

#include "process.h"

#include "iostream.h"

#define NULL 0 //NULL替代0


#define OK 1 //OK替代1


#define ERROR 0 //ERROR替代0


#define OVERFLOW -2 //内存分配失败后返回的EXIT值


#define STACK_BEGIN_SIZE 10 // 存储空间初始分配量


#define STACK_INCREASE 2 // 存储空间分配增量


typedef struct CsStack

{

     double *base; // 栈构造之前和销毁之后,BASE的值均为NULL


     double *top; // 栈顶指针


     int stacksize; // 当前已分配的存储空间,以元素为单位


}CsStack; // 构造顺序栈




void InitStack(CsStack &S) // 构造一个空栈S


{

     if(!(S.base=(double *)malloc(STACK_BEGIN_SIZE*sizeof(double))))//S.BASE值为NULL,分配失败


     {

         exit(OVERFLOW); // 内存分配失败,跳出


     }

     S.top=S.base;//将栈置为空栈


     S.stacksize=STACK_BEGIN_SIZE;//设定栈大小为默认常量STACK_BEGIN_SIZE


}



double ClearStack(CsStack &S) //将栈清空,置为空栈


{

     S.top=S.base; //重置栈为空栈


     return OK;

}



double GetTop(CsStack S,double &e)

{

     if(S.top>S.base) // 若栈不空,则用e返回S的栈顶元素,并返回OK


     {

         e=*(S.top-1);

         return OK;

     }

     else //否则返回ERROR


     {

         return ERROR;

     }

}



void Push(CsStack &S,double e) // 插入元素e为新的栈顶元素


{

     if(S.top-S.base>=S.stacksize) // 实际长度大于目前栈大小,栈满的情况,增加链表长


     {

         S.base=(double *)realloc(S.base,(S.stacksize+STACK_INCREASE)*sizeof(double));//追加STACK_INCREASE大小的存储空间


         if(!S.base) //S.BASE值为NULL,分配失败


         {

              exit(OVERFLOW); // 内存分配失败,跳出


         }

         S.top=S.base+S.stacksize;// 栈顶指针指向重定义


         S.stacksize=S.stacksize+STACK_INCREASE;// 栈长度重定义


     }

     *(S.top)++ = e;//先将栈顶元素为e后栈顶指针下移


}



double Pop(CsStack &S,double &e)

{

     if(S.top==S.base)// 若栈空,返回ERROR


     {

         return ERROR;

     }

     else

     {

         e=*(--S.top);// 若栈不空,将指针指向栈顶下一位,用e返回其值


         return OK;

     }

}



char Compare(char t1,char t2)// 判断t1,t2两符号的优先关系


{

char f;

switch(t2)

     {

     case '+':

     case '-':

         if(t1=='('||t1=='=')

        {

              f='<'; // + -的优先级仅比( = 大


        }

         else

        {

              f='>'; // 除上述以外条件


        }

         break;

     case '*':

     case '/':

         if(t1=='*'||t1=='/'||t1==')'||t1=='s'||t1=='l'||t1=='g'||t1=='c'||t1=='t'||t1=='o'||t1=='^')

        {

              f='>'; // * /的优先级比* / ) s l g c ^低


        }

         else

         {

              f='<'; // 除上述以外条件


         }

         break;

     case '(':

         if(t1==')') //如)(的表达式是错误的


         {

              printf("\n\t →出错啦←\n");

              printf("| 原 因:表达式输入格式错误。 |\n");

              exit(ERROR);

         }

         else

         {

        f='<'; // 除上述错误类型外,“(”优先级最大


        }

         break;

     case ')':

         switch(t1)

         {

         case'(':

              f='='; // 优先级相同即(),然后脱括号接收下一字符


              break;

         case'=':// 如=)的表达式是错误的


              printf("\n\t →出错啦←\n");

              printf("| 原 因:表达式输入格式错误。 |\n");

              exit(ERROR);//尚未解决的问题


              default :f='>'; // 除上述以外类型“)”优先级最小


         }

         break;

     case'=':

         switch(t1)

         {

        case'=':

              f='='; // 优先级相同即==,省去后接受下一字符


              break;

         case'(' : // 如(=的表达式是错误的


              printf("\n\t →出错啦←\n");

              printf("| 原 因:表达式输入格式错误。 |\n");

              exit(ERROR);//尚未解决的问题


         default :f='>';// 除上述以外类型“=”优先级最小


         }

         break;

     case'^':

         if(t1=='+'||t1=='-'||t1=='*'||t1=='/'||t1=='('||t1=='^'||t1=='=')

         {

              f='<';// + - * / ( ^ =优先级比 ^ 低


         }

         else

         {

              f='>';// 除上述以外其他条件


         }

         break;

     case's':

     case'c':

     case'g':

     case'l':

     case't':

     case'o':

         switch(t1)

         {

        case')':

        case'l':

        case'g':

        case'c':

        case's':

         case't':

         case'o':

              printf("\n\t →出错啦←\n");

              printf("| 原 因:表达式输入格式错误。 |\n");

              printf("| 详 细:您出现了多个函数符号连用的情况。 |\n\n");

              exit(ERROR);//尚未解决的问题


        case'(':

        case'=':

        case'+':

        case'-':

        case'*':

        case'/':

        case'^':f='<';break;

        }

         break;

     }

     return f;

}



double Operate1(double a,char JS_ysf,double b)

{//做四则运算和乘方运算


double c;

switch(JS_ysf)

     {

     case'+':c=a+b;break;

     case'-':c=a-b;break;

     case'*':c=a*b;break;

     case'/':c=a/b;break;

     case'^':c=pow(a,b);break;

     }

     return c;

}



double Operate2(char JS_ysf,double a)

{//做sin、cos、lg、ln的运算


     double c;

     switch(JS_ysf)

     {

     case's':c=sin(a);break;

     case'c':c=cos(a);break;

     case't':c=sin(a)/cos(a);break;

     case'o':c=cos(a)/sin(a);break;

     case'l':c=log(a);break;

     case'g':c=log10(a);break;

     }

     return c;

}



double In(char c) // 判断c是否为12种运算符之一


{

switch(c)

     {

     case'+':

     case'-':

     case'*':

     case'/':

     case'(':

     case')':

     case'=':

     case'^':

     case's':

     case'c':

     case't':

     case'o':

     case'l':

     case'g':return 1;

     default:return 0;

     }

}

void main()

{

printf("\t〓〓〓欢迎使用CS堆栈计算器 Ver 2.0 § 程序设计:05141 曹硕〓〓〓\n");

printf("\t| ★目前支持★ 加、减、乘、除、指数、正余弦、正余切、对数及括号|\n");

printf("\t| ★独特功能★ 人性化交互界面、多次进行运算、自动检错报错机制。|\n");

printf("\t| ★输入格式★ “表达式=”回车出结果(结果保留15位有效小数) |\n");

printf("\t| ★三角函数★ 正弦 s(),余弦 c(),正切 t(),余切 o() |\n");

printf("\t| ★对数函数★ 自然对数 l(),以十为底对数 g() |\n");

printf("\t| ★操作说明★ 若您中途想退出,请您输入 Q 回车 |\n");

CsStack StackZF,StackSZ; //结构体变量名表列


double a,b,x,JS_ysf; //存放即时数据


double result; //最终结果变量


double f; //单步结果变量


char c; // 字符串接受变量


char z[60]; // 字符串转数字的中间数组


char js[20]; // 垃圾字符回收数组


int i; // 循环增加量


char dh; // 控制多次运算的变量


int jc=0; // 检查首位是否为“-”的计数器


InitStack(StackZF);// 构造一个空栈来存放运算符


InitStack(StackSZ);// 构造一个空栈来存放数字


start_do: //循环开始标志


do

{

     Push(StackZF,'='); // 将“=”压入栈,避免栈为空。


     printf("\n请输入算术表达式:");

     c=getchar(); //获得首个字符


     if((c=='+' || c=='-' || c=='*' || c=='/' || c=='=' || c=='^' || c==10) && jc==0)//判断首位是否运算符


         {

              if(c==10) goto start_do;

              printf("\n\t →出错啦←\n");

              printf("| 原因:首位不能是运算符。 |\n");

              printf("| 详细:您首位出现了运算符“%c”|\n",c);

              if(c==13 ||c==10)

              {

                   jc=0;//重置判断首位变量


                   goto start_do;

              }

              else

              {

                   jc=0;//重置判断首位变量


                   gets(js);//用数组Z接收冗余字符


                   goto start_do;

              }

         }

     jc++;

     GetTop(StackZF,JS_ysf);//用e返回S的栈顶元素“=”


     while(c!='='||JS_ysf!='=')//当c或即时栈顶元素不等于'='时执行循环


     {

         if(In(c)) // 判断c是否为12种运算符之一


         {

     

              switch(Compare(JS_ysf,c))//获得优先级高的运算符


              {

             case '<': //栈顶运算符优先级低的情况


                   Push(StackZF,c); //c的优先级高于字符栈顶运算符优先级的情况


                   c=getchar(); //继续获得新的c


                   GetTop(StackZF,JS_ysf); //获得字符栈顶符号给运算符


                   break;

              case '='://脱括号并接收下一字符


                   Pop(StackZF,JS_ysf); //将运算符压入堆的下一位


                   GetTop(StackZF,JS_ysf); //获得目前堆顶运算符


                   if(JS_ysf=='s'||JS_ysf=='l'||JS_ysf=='c'||JS_ysf=='g'||JS_ysf=='t'||JS_ysf=='o') //对特殊运算符号的处理


                   {

                       Pop(StackSZ,f); //将f压入数字堆的下一位


                       Pop(StackZF,JS_ysf); //将运算符压入字符堆的下一位


                       Push(StackSZ,Operate2(JS_ysf,f)); //将特殊运算结果压入数字堆顶


                       GetTop(StackZF,JS_ysf); //获得字符堆顶的运算符


                       c=getchar();

                   break;

                   }

                   else

                   {

                   c=getchar();

                   break;

                   }

              case '>'://退栈并将运算结果入栈


                   if(JS_ysf=='+'||JS_ysf=='-'||JS_ysf=='*'||JS_ysf=='/'||JS_ysf=='^')

                   {

                   Pop(StackZF,JS_ysf); //将即时运算符压入字符堆的下一位


                   Pop(StackSZ,b); //将b值压入数字堆的下一位


                   Pop(StackSZ,a); //将A值压入数字堆的下一位(高于b栈位)


                   f=Operate1(a,JS_ysf,b); //求解值f


                   Push(StackSZ,f); //将运算结果f压入栈顶


                   GetTop(StackZF,JS_ysf); //获得字符堆顶的运算符


                  break;

                   }

                   else break;

              }

         }

         else if((c>='0' && c<='9') || c=='.')//对数字的处理


         {

              i=0;

              do

                   {

                   z[i]=c;

                   i++;//将数字存入数组z[]中


                   c=getchar();

                   }while((c<='9' && c>='0') || c=='.');

              z[i]=0; //此为\0空字符结束字符串


              result=atof(z); //ATOF()函数自动将字符数组转为Double型数


              Push(StackSZ,result); //将结果数压入数字堆栈栈顶


         }

         else if(c=='q' ||c=='Q')//c为q或Q时,退出程序


              {

              goto end;

              }

         else//c为非法字符时,做出相应错误提示并返回重输入


         {

              printf("\n\t →出错啦←\n");

              printf("| 原因:表达式输入格式错误。 |\n");

              if((c<'0' || c>'9') && c!=10)

                   {

                   printf("| 详细:包含非法字符“%c…”。 |\n",c);

                   }

              else

                   {

                   printf("| 详细:表达式结束缺少“=”。 |\n");

                   }

              if(c==13 ||c==10)

              {

                   jc=0;//重置判断首位变量


                   goto start_do;

              }

              else

              {

                  jc=0;//重置判断首位变量


                  gets(js);//用数组Z接收冗余字符


                  goto start_do;

              }

         }

     }

     GetTop(StackSZ,x); //栈StackSZ顶即为运算结果


     printf("\n计算结果为%10.15f",x); //输出结果


     ClearStack(StackZF); //重置栈为空栈


     ClearStack(StackSZ); //重置栈为空栈


     printf("\n\n继续计算么?(按Y键继续)\n");//用键盘控制是否再次运算


     dh=getch();

     if(dh==89 || dh==121)

     {

         dh=1;

         jc=0;//重置判断首位变量


     }

     else

     {

         dh=0;

     }

     x=getchar();

}while(dh);//循环使用以上程序达成多次运算


end:

printf("\n\t →成功退出←\n\n CS堆栈科学计算器期待您的再次使用!\n 程序版本:Ver 2.0\n 程序设计:05141班 曹硕.\n\n");

}

阅读(1851) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~