双栈实现计算器


需求描述:使用一个双向栈实现一个简易计算器,可以计算加减乘除,带小括号(),如 3+2*(3-4)+2=

基本实现方法:双向栈的top端存运算数字,base端存运算符。读取数学运算式,若遇到数字,直接压栈;若遇到运算符,比较运算优先级。若后面的运算符优先级大于前一个运算符(即栈头运算符),运算符压栈,否则,数字出栈进行计算,再把计算结果压栈,后面继续读取字符计算,直到遇到=字符运算结束。


特别声明,下文提供的源码在VC6.0上验证通过。


///

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

// 定义双向栈大小
#define DSTACK_SIZE 40

// 定义双向栈数据结构
typedef struct dStack_s
{
 int data[DSTACK_SIZE];
 unsigned top;          // 指向数据侧栈顶
 unsigned base;         // 指向运算符侧栈顶
}dStack_t;

// 函数声明
int expr(const char *);    // 计算函数

void stackInit(dStack_t **);     // 初始化函数
void operate(dStack_t *);        // 计算函数
int  IsOpr(char);                // 判断输入字符是否运算符
char Precede(char, char);        // 判断运算符的优先级
void PushNum(dStack_t *, int);   // 数字压栈
int  PopNum(dStack_t *);         // 数字出栈
int  GetTopNum(dStack_t *);      // 取数据侧栈顶数字
void PushOpr(dStack_t *, char);  // 运算符压栈
char PopOpr(dStack_t *);         // 运算符出栈
char GetTopOpr(dStack_t *);      // 取运算符侧栈顶运算符


void main(void)
{
 char *equation = NULL;
 char ch = 0;
 int i = 0;
 
 equation = (char *)malloc(DSTACK_SIZE * sizeof(char));
 if (NULL == equation)
 {
  printf("main:Insufficient Memory!\n");
  exit(0);
 }
 memset(equation, 0, DSTACK_SIZE * sizeof(char));

 printf("Input Formula: Exp. 3+2*(3-4)+2=\n");
 ch = getchar();
 for (i = 0; ch != '\n'; i++)
 {
  if (' ' == ch)   // 过滤掉等式中的空格,其他非法字符在后面检查
  {
   continue;
  }
  *(equation + i) = ch;
  ch = getchar();
 }
 *(equation + i) = '\0';
 
 printf("%d\n", expr(equation));
 free(equation);
}

/* 利用双向栈算法的计算函数 */
int expr(const char *equation)
{
 char ch = 0;
 int digit = 0;
 int flag = 0;        // 用于标识负号
 int finalKey = 0;    // 存放最后运算结果
 dStack_t *pdStack = NULL;

 if (NULL == equation)
 {
  printf("expr:Insufficient Memory!\n");
  exit(0);
 }

 stackInit(&pdStack);
 PushOpr(pdStack, '=');

 ch = *(equation++);
 if ('-' == ch)       // 特殊情况1:首字符为'-',视为负号
 {
  ch = *(equation++);
  flag = 1;
 }
 while (ch != '=' || GetTopOpr(pdStack) != '=')  // 读入字符与运算符栈顶字符均为'='时结束运算
 {
  if (0 == IsOpr(ch))                  // 若输入为数字,可输入多位数
  {
   digit = ch - '0';
   ch = *(equation++);
   while (0 == IsOpr(ch))
   {
    digit = 10 * digit + ch - '0';
    ch = *(equation++);
   }
   if (1 == flag)
   {
    digit = -digit;
    flag = 0;
   }
   PushNum(pdStack, digit);
  }  
  else if (1 == IsOpr(ch))
  {
   if (('-' == ch) && ('(' == *(equation - 2))) // 特殊情况2:若字符'-'紧接'('之后,视前者为负号
   {
    ch = *(equation++);
    flag = 1;
   }
   else
   {
    switch (Precede(GetTopOpr(pdStack), ch))  // 比较栈顶运算符和输入运算符的优先级
    {
    case '<':
     {
      PushOpr(pdStack, ch);
      ch = *(equation++);
      break;
     }
    case '=':
     {
      PopOpr(pdStack);
      ch = *(equation++);
      break;
     }
    case '>':
     {
      operate(pdStack);
      break;
     }
    default:
     {
      printf("Anomaly Result!\n");
      exit(0);
     }
    }
   }
  }
  else
  {
   printf("Illegal input!\n");
   exit(0);
  }
 }
 finalKey = GetTopNum(pdStack);
 free(pdStack);
 return finalKey;
}

/* 四则运算函数 */
void operate(dStack_t *stack)
{
 int key = 0;
 int topDigit = 0;
 int hypDigit = 0;
 if (NULL == stack)
 {
  printf("operate:Insufficient Memory!\n");
  exit(0);
 }

 topDigit = PopNum(stack);
 hypDigit = PopNum(stack);
 switch (PopOpr(stack))
 {
 case '+':
  {
   key = hypDigit + topDigit;
   break;
  }
 case '-':
  {
   key = hypDigit - topDigit;
   break;
  }
 case '*':
  {
   key = hypDigit * topDigit;
   break;
  }
 case '/':
  {
   if (0 == topDigit)
   {
    printf("Divisor cannot be zero!\n");
    exit(0);
   }
   key = hypDigit / topDigit;
   break;
  }
 default:
  {
   printf("Illegal Operator!\n");
   exit(0);
  }
 }
 PushNum(stack, key);
}

/* 双向栈初始化函数 */
void stackInit(dStack_t **stack)
{
 *stack = (dStack_t *)malloc(sizeof(dStack_t));
 if ((NULL == *stack) || (NULL == stack))
 {
  printf("stackInit:Insufficient Memory!\n");
  exit(0);
 }

 memset((*stack)->data, 0, DSTACK_SIZE * sizeof(int));
 (*stack)->top  = -1;
 (*stack)->base = DSTACK_SIZE;
}

/* 数字压栈 */
void PushNum(dStack_t *stack, int digit)
{
 if (NULL == stack)
 {
  printf("PushNum:Insufficient Memory!\n");
  exit(0);
 }
 if (stack->top + 1 == stack->base)  // 判断是否栈满
 {
  printf("PushNum:Stack is full!\n");
  exit(0);
 }

 (stack->top)++;
 (stack->data)[stack->top] = digit;
}

/* 运算符压栈 */
void PushOpr(dStack_t *stack, char ch)
{
 int opr = (int)ch;
 if (NULL == stack)
 {
  printf("PushOpr:Insufficient Memory!\n");
  exit(0);
 }
 if (stack->top + 1 == stack->base)  // 判断是否栈满
 {
  printf("PushOpr:Stack is full!\n");
  exit(0);
 }

 (stack->base)--; 
 (stack->data)[stack->base] = opr;
}

/* 数字出栈 */
int PopNum(dStack_t *stack)
{
 int digit = 0;
 if (NULL == stack)
 {
  printf("PopNum:Insufficient Memory!\n");
  exit(0);
 }
 if (-1 == stack->top)     // 判断栈数据侧是否空
 {
  printf("PopNum:Stack is empty!\n");
  exit(0);
 }
 
 digit = (stack->data)[stack->top];
 (stack->data)[stack->top] = 0;    // 栈内存清零,可删除此行代码
 (stack->top)--;
 return digit;
}

/* 运算符出栈 */
char PopOpr(dStack_t *stack)
{
 char opr = 0;
 if (NULL == stack)
 {
  printf("PopOpr:Insufficient Memory!\n");
  exit(0);
 }
 if (DSTACK_SIZE == stack->base)  // 判断栈运算符侧是否空
 {
  printf("PopOpr:Stack is empty!\n");
  exit(0);
 }
 
 opr = (char)(stack->data)[stack->base];
 (stack->data)[stack->base] = 0;  // 栈内存清零,可删除
 (stack->base)++;
 return opr;
}

/* 取数据侧栈顶数字 */
int GetTopNum(dStack_t *stack)
{
 if (NULL == stack)
 {
  printf("GetTopNum:Insufficient Memory!\n");
  exit(0);
 }
 if (-1 == stack->top)            // 判断栈运算符侧是否空
 {
  printf("PopOpr:Stack is empty!\n");
  return 0;
 }

 return (stack->data)[stack->top];
}

/* 取运算符侧栈顶运算符 */
char GetTopOpr(dStack_t *stack)
{
 if (NULL == stack)
 {
  printf("GetTopOpr:Insufficient Memory!\n");
  exit(0);
 }
 if (DSTACK_SIZE == stack->base)  // 判断栈运算符侧是否空
 {
  printf("GetTopOpr:Stack is empty!\n");
  return 0;
 }

 return ((char)(stack->data)[stack->base]);
}

/* 判断输入字符是否运算符:运算符返回1,数字返回0,其他字符返回-1 */
int IsOpr(char ch)
{
 if ('+' == ch || '-' == ch || '*' == ch || '/' == ch
  || '(' == ch || ')' == ch || '=' == ch)
 {
  return 1;
 }
 else if (ch >= '0' && ch <='9')
 {
  return 0;
 }
 else
 {
  return -1;
 }
}

/* 判断运算符的优先级 */
char Precede(char aOpr, char bOpr)
{
 switch(aOpr)
 {
 case '+':
 case '-':
  {
   if ('*' == bOpr || '/' == bOpr || '(' == bOpr)
   {
    return '<';
   }
   else
   {
    return '>';
   }
  }           // 使用return返回,故不加break语句
 case '*':
 case '/':
  {
   if ('(' == bOpr)
   {
    return '<';
   }
   else
   {
    return '>';
   }
  }
 case '(':
  {
   if(')' == bOpr)
   {
    return '=';
   }
   else
   {
    return '<';
   }
  }
 case ')':            // 不会出现这种情况
  {
   return '>';
  }
 case '=':
  {
   if ('=' == bOpr)
   {
    return '=';
   }
   else
   {
    return '<';
   }
  }
 default:
  {
   exit(0);
  }
 } 
}



  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值