用栈实现的模拟计算器程序

来源:互联网 发布:iphone用电脑网络上网 编辑:程序博客网 时间:2024/06/04 19:45
#include<stdio.h>
#include<math.h>
#include <stdlib.h>
#include<string.h>
//运算符栈数组长度
#define STACK_OPERATOR_LENGTH 100
//操作数栈数组长度
#define STACK_DATE_LENGTH 100
//定义运算符栈
typedef struct OPStack
{
//定义运算符数组
char opStack[STACK_OPERATOR_LENGTH];
//栈顶
int top;
}OPStack,*pOPStack;
//定义运算数栈
typedef struct DATAStack
{
//定义操作数数组;
double stack[STACK_DATE_LENGTH];
int top;
}DATAStack,*pDATAStack;


//初始化运算符栈
void InitpOPStack(pOPStack &OPStack)
{
//为运算符栈分配空间
if(!(OPStack = ( pOPStack)malloc( sizeof(OPStack ))))
{
printf("分配内存空间失败!\n");
exit(-1);
}
OPStack->top=-1;
}


//初始化运算数栈
void InitpDATAStack(pDATAStack &pDStack)
{
//为运算数栈分配空间
if(!(pDStack = ( pDATAStack)malloc(sizeof(DATAStack))))
{
printf("分配内存空间失败!\n");
exit(-1);
}
pDStack->top=-1;
}


//运算符进栈
void PushOPStack(pOPStack &pOPStack, char ch)
{
pOPStack->opStack[++(pOPStack->top)]=ch;
}


//运算符出栈
void PopOPStack(pOPStack &pOStack, char &ch)
{
 ch = pOStack->opStack[pOStack->top];
 pOStack->top--;
}


//运算数进栈
void PushDATAStack(pDATAStack &pDStack, double d)
{
 ++(pDStack->top);
 pDStack->stack[pDStack->top] = d;
}


//运算数出栈
void PopDATAStack(pDATAStack &pDStack, double &d)
{
 d = pDStack->stack[pDStack->top];
 pDStack->top--; 
}


//清空运算符栈
void ClearpOPStack(pOPStack &pOStack)
{
 pOStack->top = -1;
}


//清空运算数栈
void ClearpDATAStack(pDATAStack &pDStack)
{
 pDStack->top = -1;
}


//获取运算符栈顶元素
char GetToppOPStack(pOPStack &pOStack)
{
 return pOStack->opStack[pOStack->top];
}


 //获取运算数栈顶元素
double GetToppDATAStack(pDATAStack &pDStack)
{
 return pDStack->stack[pDStack->top];
}


//区分 运算符 和 运算数 的函数,是运算符时返回true,否则返回false
bool IsOP(char &ch)
{ //判断是否为符号
 if ( (ch == '+') || (ch == '-') || (ch == '*') || (ch == '/') || (ch == '=') || (ch == 'A') || (ch == 'S') || (ch == 'a') || (ch == 's') || (ch == '(') || (ch == ')') )
  return true;
 else
  return false;
}


//参考《数据结构》(C语言版)第53页 3.2.5表达式求值 表 3.1
char Precede(char op1, char op2)
{
 char tab[9][10];  //定义字符串的二维数组来存放运算符优先级的关系
 strcpy( tab[0], ">><<<><<>" );
 strcpy( tab[1], ">><<<><<>" );
 strcpy( tab[2], ">>>><><<>" );
 strcpy( tab[3], ">>>><><<>" );
 strcpy( tab[4], "<<<<<=<<E" );
 strcpy( tab[5], ">>>>E>>>>" );
 strcpy( tab[6], ">>>><>>>>" );
 strcpy( tab[7], ">>>><>>>>" );
 strcpy( tab[8], "<<<<<E<<=" );
 char op[10];  //定义一维字符串数组来按优先级从低到高存放运算符
 strcpy(op, "+-*/()AS=");
 int i, j;


 for( i = 0; i < 9; i++)
  if( op[i] == op1)
   break;
 for( j = 0; j < 9; j++)
  if( op[j] == op2)
   break;
 return tab[i][j];  //返回比较结果
}
void exit_E()
{
  printf("\n |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|\n");
  printf("\n | ***欢迎您的下次使用!谢谢!!!***   | \n\n");  //退出使用
  printf(" |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|\n\n");
}


  //对出栈的运算符和运算数进行计算
double Operate(double a, char theta, double b)
{
 double s;
 switch(theta)
 {
 case '+':
  s = a + b;
  break;
 case '-':
  s = a - b;
  break;
 case '*':
  s = a * b;
  break;
 case '/':
  if ( b != 0 )  //判断除数是否为0,若为0,退出程序
  {
   s = a/b;
   break;
  }
  else
  {
   printf("\n  #### 除数为0,非法运算。程序终止! ####\n");
   exit_E();  //打印结束菜单
   exit(-1);
  }
 case 'A':
  s = fabs(b);  //调用FABS()函数
  break;
 case 'S':
  if( b >= 0)   //判断被开方数是否为0,若为0,退出程序
  {
   s = sqrt(b);  //调用SQRT()函数
   break;
  }
  else
  {
   printf("\n  #### 求负数的平方根是非法运算。程序终止! ####\n");
   exit_E();  //打印结束菜单
   exit(-1);
  }
 }
 return s;
}
//通过ChangeChar函数来把a、s的小写字母改为大写的
char ChangeChar(char &c)
{
 if( c == 'a' )
  c = 'A';
 else if( c == 's' )
  c = 'S';
 return c;
}


//参考《数据结构》(C语言版)第53页 3.2.5表达式求值 算法3.4 Evaluateexpression_r()函数
void Evaluateexpression_r()  //计算函数:读入表达式,并计算结果
{
 pOPStack pOStack;  //声明运算符栈
 pDATAStack pDStack;   //声明运算数栈
 double result;  //存运算的结果
 char x, theta, c;  //c存放读取的字符,x、theta存放运算符栈的栈顶元素
 int flag, data;   //标识符,用来读入连续的数字
 double s;
 double getd;  //存放GetTop***的结果
 double a, b, cc;  //a,b存放数据栈出栈的栈顶元素, c存放运算结果
 flag = 0;  //初始化标识符,用来判断字符串中的连续数字
 data = 0;  //
 InitpOPStack(pOStack);  //初始化运算符栈


 InitpDATAStack(pDStack);  //初始化运算数栈
 
 PushOPStack(pOStack,'=');  //在运算符栈底放入'='   ←←问题在这里 
 
 printf(" &请输入表达式以'='结束:");
 c = getchar();  //读入字符
 ChangeChar(c);  //通过调用函数来实现把小写的a、s改为大写的A、S
 while( c != '=' || GetToppOPStack(pOStack) != '=')
 {
  if( !IsOP(c) )   //不是运算符进栈
  {
   s = c - '0';  //把字符转化为数字
   if ( flag == 1 )
   {
    PopDATAStack(pDStack, getd);
    s = getd*10 + s;
   }
   PushDATAStack(pDStack, s);
   flag = 1;
   c = getchar();
   ChangeChar(c);
  }
  else
  {
   flag = 0;
   switch( Precede(GetToppOPStack(pOStack), c) )  //输入元素和运算符栈顶元素比较
   {
   case '<':  //栈顶元素优先级低
    PushOPStack(pOStack, c);
    c = getchar();
    ChangeChar(c);
    break;
   case '=':  //托括号并接受下一个字符
    PopOPStack(pOStack, x);
    c = getchar();
    ChangeChar(c);
    break;
   case '>':  //退栈并将运算结果进栈
    PopOPStack(pOStack, theta);
    PopDATAStack(pDStack, b);//当运算符为ABS或SART函数时,只需出一个运算数栈
    if(theta=='+'||theta=='-'||theta=='*'||theta=='/')
    {
        PopDATAStack(pDStack, a);
        cc = Operate(a, theta, b);
    }
    else{
        cc = Operate(0, theta, b);
    }
    PushDATAStack(pDStack, cc);
    break;
   }//switch
  }//else
 }//while
 result = GetToppDATAStack(pDStack);  //运算结束时,运算数栈的栈底元素就是计算结果
 ClearpOPStack(pOStack);   //清空运算符栈
 ClearpDATAStack(pDStack);  //清空运算数栈
 printf(" ->计算结果为:%.2f\n\n", result);  //输出运算结果
}


void print_user()  //欢迎界面
{
 printf("\n   欢迎使用C语言版模拟计算器  \n\n");
 printf("************************************************************************\n");
 printf(" |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|\n");
 printf(" |  模拟计算器使用说明   |\n\n");
 printf(" | 本程序包括对'+'、'-'、'*'、'/'、'()'的运算 |\n");
 printf(" | 本程序中ABS()算用A()替代、SQRT()运算用S()代替 |\n");
 printf(" | 本程序中的一切字母均不区分大小写  |\n");
 printf("  正确的表达式如:1+A(7-8)+S(9*8)=  \n");
 printf(" | 输入'='表示表达式输入结束!!   |\n\n");
 printf(" |     欢迎使用!!!-->-->      |\n");
 printf(" |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|\n");
 printf("************************************************************************\n\n");
}


int main ( )//主函数
{
char in;
bool b;  //标识符,用来标识是否结束程序
b = true;  //初始化,不结束
print_user();  //打印欢迎界面
printf(" *请确认使用计算器Y/N:");
while(1)
{
 scanf("%c", &in);  //确认是否继续操作
 getchar();  //吃掉会车,避免干扰
 switch(in)
 {
 case 'Y':
 case 'y':
            {
            Evaluateexpression_r();  //进入计算函数:读入表达式,并计算结果
            break;
            }
          case 'N':
          case 'n':
            {
                exit_E();
                b = false;
                break;
            }
 //default:
 // printf(" **输入错误,请重新输入Y/N:");
 // break;
 }
 if(b==false)  //如果 b==false ,退出整个程序
  break;
 printf(" *您确定要继续使用计算机Y/N:");
 getchar();  //用getchar吃掉回车,避免对后续输入中in的干扰
}
return 0;
}
1 0
原创粉丝点击