数据结构专题实验四 — 栈的应用(C++实现)

一、实验概述

实验内容:利用表达式求值思想,完成简易计算器的开发。
实验要求:

  1. 要求用C++实现表达式求值。
  2. 设计计算器图形界面。
  3. 考虑带小括号情况。
  4. 考虑整数、小数及多位数的计算。
  5. 考虑多种容错,如+与-不能连着等错误。

二、代码结构

在这里插入图片描述

	stack是存放数字的栈,opstack是存放运算符的栈。

在这里插入图片描述

三、函数讲解

int isEmpety(stack s)

	判断栈是否为空,EmptyTOS的值为-1。
int isEmpety(stack s){
    return s->top == EmptyTOS;
}

stack createStack()

	创建一个存放数字的栈。MaxSize的值为100,即这个栈最多能容纳100个
数字。
stack createStack(){
    stack s;
    s = (Stack*)malloc(sizeof(Stack));
    if(s == NULL)
      printf("out of space!");

    s->operand = (double*)malloc(sizeof(double)*MaxSize);
    if(s->operand == NULL)
      printf("out of space!");

    makeEmpety(s);
    s->size = MaxSize;
    return s;
}

void makeEmpety(stack s)

	使栈为空。本质上就是改变栈顶的位置,若栈里原先有数据,再次存放就
会覆盖。
void makeEmpety(stack s){
    s->top = EmptyTOS;
}

void push(double x,stack s)

	将数字放入栈。先判断这个栈是否为满,若满,则不放入;反之,放入。
void push(double x , stack s){
    if(isFull(s))//top在判断时自增
      printf("Full stack!");
    else
      s->operand[s->top] = x;
}

void pop(stack s)

	弹出栈顶的元素。即改变栈顶位置,继续入栈就会覆盖。
void pop(stack s){
    if(isEmpety(s))
      printf("Empty stack!");
    else
      s->top--;//下次输入就覆盖掉
}

double top(stack s)

	获得栈顶的元素。
double top(stack s){
    if(!isEmpety(s))
      return s->operand[s->top];
    printf("Empty stack!!!");
    return 0;
}

int isFull(stack s)

	判断栈是否为满。
int isFull(stack s){
     return s->top++ == s->size;
}
	以上是关于栈的相关函数,这里我只列举了数字栈的函数,但其实符号栈
也是大同小异,各位朋友可以自行改写。以下则是讲解计算器功能逻辑的相关函
数。

double operate(double a,double b,char c)

	实现加减乘除计算操作的函数。
double operate(double a,double b,char c){
    double result;
    switch(c){
    case '+':
        result = a+b;
        break;
    case '-':
        result = b-a;
        break;
    case '*':
        result = a*b;
        break;
    case '/':
        if(a == 0){
            setCheck(-1);
        }
        else
        result = b/a;
        break;
    }
    return result;
}

char compare(char c1,char c2)

	比较一串表达式中运算符号的优先级。例如:乘除优先于加减,括号优先于
其他,同级别运算符左边优先于右边。

根据这张图能很好的看出各符号间的优先级

char compare(char c1,char c2){
        if(c1=='+'){
            switch(c2){
                case '+': return '>';break;
                case '-': return '>';break;
                case '*': return '<';break;
                case '/': return '<';break;
                case '(': return '<';break;
                case ')': return '>';break;
                case '#': return '>';break;
            }
        }
        else if(c1=='-'){
            switch(c2){
                case '+': return '>';break;
                case '-': return '>';break;
                case '*': return '<';break;
                case '/': return '<';break;
                case '(': return '<';break;
                case ')': return '>';break;
                case '#': return '>';break;
            }
        }
        else if(c1=='*'){
            switch(c2){
                case '+': return '>';break;
                case '-': return '>';break;
                case '*': return '>';break;
                case '/': return '>';break;
                case '(': return '<';break;
                case ')': return '>';break;
                case '#': return '>';break;
            }
        }
        else if(c1=='/'){
            switch(c2){
                case '+': return '>';break;
                case '-': return '>';break;
                case '*': return '>';break;
                case '/': return '>';break;
                case '(': return '<';break;
                case ')': return '>';break;
                case '#': return '>';break;
            }
        }
        else if(c1=='('){
            switch(c2){
                case '+': return '<';break;
                case '-': return '<';break;
                case '*': return '<';break;
                case '/': return '<';break;
                case '(': return '<';break;
                case ')': return '=';break;
                case '#': return '!';break;
            }
        }
        else if(c1==')'){
                switch(c2){
                    case '+': return '>';break;
                    case '-': return '>';break;
                    case '*': return '>';break;
                    case '/': return '>';break;
                    case '(': return '!';break;
                    case ')': return '>';break;
                    case '#': return '>';break;
                }
            }
            else if(c1=='#'){
                switch(c2){
                    case '+': return '<';break;
                    case '-': return '<';break;
                    case '*': return '<';break;
                    case '/': return '<';break;
                    case '(': return '<';break;
                    case ')': return '!';break;
                    case '#': return '=';break;
                }
         }
}

bool input(char a)

	判断输入的是否是运算符。
bool input(char a){
    if(a =='+' || a =='-' || a =='*' || a =='/' || a =='(' || a ==')' || a =='#')
        return true;
    else
        return false;
}

double evaluate(QString qs,stack s,opstack ops)

	对输入的表达式进行计算。
	首先将表达式转换为字符串,对每个字符依次进行判断,若是数字,则入
数字栈;若是运算符,则入符号栈。temp作为临时变量,代表当前字符。然后
比较符号栈栈顶的符号与当前符号的运算优先级。若栈顶运算符先级更高,直接
计算,即从数字栈弹出栈顶的两个元素,再从符号栈中弹出栈顶元素,利用
operate()函数计算,将计算结果放入数字栈栈顶;若栈顶运算符优先级更低,
将当前temp代表的运算符入栈,继续向下读取字符串;若栈顶运算符优先级与
当前运算符相同,则弹出符号栈栈顶运算符。
double evaluate(QString qs,stack s,opstack ops){
    int pos = 0,n = qs.length();
    double in,a,b;
    QString num = "";
    char temp,c;

    while(pos < n){
        temp = qs.at(pos).toLatin1();
        if(input(temp)==false){
            num.append(temp);
            pos++;
        }
        else {
            if(num != ""){
                in = num.toDouble();
                num = "";
                push(in,s);
            }
                switch(compare(ops->operatoR[ops->top],temp)){
                    case '<':              
                        pos++;
                        push2(temp,ops);
                        break;
                    case '=':
                         pos++;
                         pop2(ops);
                        break;
                    case '>':
                        a = topAndPop(s);
                        b = topAndPop(s);
                        c = top2(ops);
                        pop2(ops);
                        push(operate(a,b,c),s);          
                    break;
          }
       }
     }
   return top(s);
}

四、结果演示

	简单的一个运算表达式。

在这里插入图片描述
一些容错。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我在github上做的开源。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值