顺序栈使用——表达式求值

顺序栈使用——表达式求值


码文不易,如果帮助到您,希望您可以帮我刷一下点击量,与您无害,与我有益谢谢 支持原创

  欢迎大家阅读我的博客,如果有错误请指正,有问题请提问,我会尽我全力改正错误回答问题。在次谢谢大家。下面开始正式内容

  顺序栈部分在之前已经在另一篇文章中提及,本篇中就不再提及,如有需要请阅读<顺序栈的各种基本运算>


实验环境


  • 语言c/c++
  • 编译器devc++5.11/5.40


实验内容与要求


问题描述:
  设一个算术表达式中包含圆括号、+、-、*、/、正整数,编写一个程序完成对表达式的求值运算。


目录


码文不易,如果帮助到您,希望您可以帮我刷一下点击量,与您无害,与我有益谢谢 支持原创


实验解析

思路方法


  可以使用两个工作栈:

  1. 一个栈OPTR存放运算符;
  2. 另一个栈OPND存放操作数;

用算符优先关系来判断相邻两个符号之间的优先关系。


定义说明


Stack num_stack 运算数栈
Stack opr_stack 操作符栈
double calculate(char *, Stack* ,Stack*);//核心运算部分 
double get_result(double ,Stack* ,Stack*);//进行一步运算获取结果 
double accumulate(Stack* ,Stack* );// 

  定义常用常量,类型别称


函数说明



流程图

Created with Raphaël 2.1.2 初始化 读取完毕? 获取运算结果 返回结果,程序结束 读取数据进栈,乘除直接运算 遇到"()"? 运算"()"内数据 "()"前有"*/"? 运算一步乘除 yes no yes no yes no

运算函数

进行一步运算
double get_result(double right,Stack* num_stack,Stack* opr_stack){
    double left=OutStack(*num_stack);//获取运算数
    char oper=OutStack(*opr_stack);//获取操作
    switch(oper){//根据运算符返回结果
        case '+':
            return left+right;
        case '-':
            return left+right;
        case '*':
            return left*right;
        case '/':
            return left/right;
    }
}

  进行一步运算,返回结果。调用时注意栈是否为空,没有做安全防护


进行一级运算
double accumulate(Stack* num_stack,Stack* opr_stack){
    double acc = OutStack(*num_stack);
    while(TopStack(*opr_stack)!='('&&EmptyStack(*num_stack)!=1){

        acc= get_result(acc,num_stack, opr_stack);
    }
    if(EmptyStack(*num_stack)!=1){
        OutStack(*opr_stack);
        //处理括号前为乘除的情况 
        if(TopStack(*opr_stack)==(int)'/'||TopStack(*opr_stack)==(int)'*'){
            acc= get_result(acc,num_stack, opr_stack);
        }else if(TopStack(*opr_stack)==(int)'-')
            acc= -acc;
    }       
    return acc;
}

   运算同一级


计算
double calculate(char *s, Stack* num_stack,Stack* opr_stack){
    int i= 0; 
    int j = 0;// 小数位数
    int length = strlen(s);
    int flag =0 ; //判断 -1不运算取负数  0不运算 1进行一次运算 
    double tempnumber=0;//数字缓存
    double spot=-0;//小数部分 
    while(i<length){

        //数字
        if(isdigit(s[i])){
            tempnumber =  (s[i]-'0');//字符转数字 
            while(i<length&&isdigit(s[i+1])){//多位数转换 
                tempnumber =tempnumber*10 +(s[++i]-'0');
            }
            if(s[i+1]=='.'){//小数部分 
                i++;
                spot=-0;
                while(i<length&&isdigit(s[i+1])){
                    j++; 
                    spot =spot*10 +(s[++i]-'0');
                }

                for(;j>0;j--){//转换小数部分 
                    spot /=10;
                }
                tempnumber += spot;//合成一个数 
            }

            //运算数入栈 
            if(flag==-1){
                flag = 0;
                PushStack(*num_stack,-tempnumber);
            }else if(flag == 0){//不进行运算
                PushStack(*num_stack,tempnumber);
            }else if(flag == 1){//进行一次运算
                flag =0;
                PushStack(*num_stack,   get_result(tempnumber,num_stack,opr_stack));
            }

            //如果当前字符是运算符.
        }else{
            switch(s[i]){
                case '+'://如果是加号.
                    PushStack(*opr_stack,'+');
                    break;
                case '-'://如果是减号.
                    flag = -1;
                    PushStack(*opr_stack,'-');
                    break;

                //乘除法优先级高所以直接就运算掉 
                case '*'://如果是乘号.
                    flag=1;
                    PushStack(*opr_stack,'*');
                    break;
                case '/'://如果是除号.
                    flag=1;
                    PushStack(*opr_stack,'/');
                    break;

                //但是如果乘除后是括号就不能运算 
                case '('://如果是左括号.
                    flag = 0;
                    PushStack(*opr_stack,   '(');
                    break;
                case ')'://如果是右括号.这时获取这一级的结果,这时需要考虑括号前如果是乘除也需要运算掉。 
                    //计算当前的栈内元素值.
                    PushStack(*num_stack,   accumulate(num_stack,opr_stack));
                    break;
                default:break;
            }
        }
        i++;
    } 
    return accumulate(num_stack,opr_stack);
}

   运算同一级


主函数


int main(){
    Stack num_stack;
    Stack opr_stack;
    InitList_stack(num_stack);
    InitList_stack(opr_stack);
    char s[100] = {0};
    gets(s);    
    printf("结果是:%f",calculate(s,&num_stack,&opr_stack));
    return 0;
}


结果展示


表达式求值测试结果截图


附录

相关资料

  1. 顺序栈的各种基本运算


源代码

码文不易,如果帮助到您,希望您可以帮我刷一下点击量,与您无害,与我有益谢谢 支持原创


Stack.h

#include<stdio.h>   //EOF,NULL
#include<malloc.h>  //malloc()
#include<process.h>  //exit()

#define  OK  1
#define  ERROR  0
#define  TRUE  1
#define  FALSE  0

typedef  int  Status;
typedef  double    SElemType;
#define STACK_INIT_SIZE  100   //栈存储空间的初始分配量
#define STACKINCREMENT  10   //存储空间分配增量
typedef struct{
   SElemType  *base;             //存储数据元素的数组
   SElemType  *top;              //栈顶指针
   int stacksize;                   //当前分配的栈空间大小
                                 //(以sizeof(SElemType)为单位)
}Stack;


Status InitList_stack (Stack &s) {
    s.base = (SElemType*)malloc( STACK_INIT_SIZE*sizeof(SElemType));
    if (!s.base )   exit(0);
s.stacksize = STACK_INIT_SIZE;
s.top = s.base;

 return OK;
}// InitList_stack
Status EmptyStack (Stack s) 
{ if(s.base == s.top)  return TRUE;
  else return FALSE;
}//
Status PushStack(Stack &s , SElemType e ){
if(s.stacksize<(s.top-s.base) )return ERROR;
if(s.stacksize==(s.top-s.base) )
s.base = (SElemType*)malloc(( s.stacksize+STACKINCREMENT)*sizeof(SElemType));

        *(s.top) = e;
        s.top++;

    return OK;

}
Status GetLength(Stack s){
    return s.top-s.base;
}
Status DisplayStack(Stack &s){

    while(s.base != s.top){

        printf("%c ",*--(s.top));

    }
    printf("\n");
}
SElemType OutStack(Stack &s ){
 SElemType  e;
    if(s.top != s.base)

 e= *(--s.top);

    return e;
}
SElemType TopStack(Stack &s ){
 SElemType  e;
    if(s.top != s.base)

 e= *(s.top-1);

    return e;
}
Status DestroyStack ( Stack s) 
{      if (!s.base)  return ERROR; 
      free (s.base);    
      s.base = NULL;
      s.top = NULL;
      s.stacksize= 0;
      return OK;
}// DestroyList_Sq 

码文不易,如果帮助到您,希望您可以帮我刷一下点击量,与您无害,与我有益谢谢 支持原创

main.cpp

#include "Stack.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

//函数声明 
double calculate(char *, Stack* ,Stack*);
double get_result(double ,Stack* ,Stack*);
double accumulate(Stack* ,Stack* );

//运算
double calculate(char *s, Stack* num_stack,Stack* opr_stack){
    int i= 0; 
    int j = 0;// 小数位数
    int length = strlen(s);
    int flag =0 ; //判断
    double tempnumber=0;//数字缓存
    double spot=-0;//小数部分 
    while(i<length){
        if(isdigit(s[i])){//数字
            tempnumber =  (s[i]-'0');
            while(i<length&&isdigit(s[i+1])){
                tempnumber =tempnumber*10 +(s[++i]-'0');
            }
            if(s[i+1]=='.'){
                i++;
                spot=-0;
                while(i<length&&isdigit(s[i+1])){
                    j++; 
                    spot =spot*10 +(s[++i]-'0');
                }

                for(;j>0;j--){
                    spot /=10;
                }
                tempnumber += spot;
            }
            if(flag==-1){
                flag = 0;
                PushStack(*num_stack,-tempnumber);
            }else if(flag == 0){//不进行运算
                PushStack(*num_stack,tempnumber);
            }else if(flag == 1){//进行一次运算
                flag =0;
                PushStack(*num_stack,   get_result(tempnumber,num_stack,opr_stack));
            }
        }else{//如果当前字符是运算符.
            switch(s[i]){
                case '+'://如果是加号.
                    PushStack(*opr_stack,'+');
                    break;
                case '-'://如果是减号.
                    flag = -1;
                    PushStack(*opr_stack,'-');
                    break;
                case '*'://如果是乘号.
                    flag=1;
                    PushStack(*opr_stack,'*');
                    break;
                case '/'://如果是除号.
                    flag=1;
                    PushStack(*opr_stack,'/');
                    break;
                case '('://如果是左括号.
                    flag = 0;
                    PushStack(*opr_stack,   '(');
                    break;
                case ')'://如果是右括号.
                    //计算当前的栈内元素值.
                    PushStack(*num_stack,   accumulate(num_stack,opr_stack));
                    break;
                default:break;
            }
        }
        i++;
    } 
    return accumulate(num_stack,opr_stack);
}
double accumulate(Stack* num_stack,Stack* opr_stack){
    double acc = OutStack(*num_stack);
    while(TopStack(*opr_stack)!='('&&EmptyStack(*num_stack)!=1){
        acc= get_result(acc,num_stack, opr_stack);
    }
    if(EmptyStack(*num_stack)!=1){
        OutStack(*opr_stack);
        if(TopStack(*opr_stack)==(int)'/'||TopStack(*opr_stack)==(int)'*'){
            acc= get_result(acc,num_stack, opr_stack);
        }else if(TopStack(*opr_stack)==(int)'-')
            acc= -acc;
    }       
    return acc;
}

double get_result(double right,Stack* num_stack,Stack* opr_stack){
    double left=OutStack(*num_stack);
    char oper=OutStack(*opr_stack);
    switch(oper){
        case '+':
            return left+right;
        case '-':
            return left+right;
        case '*':
            return left*right;
        case '/':
            return left/right;
    }
}

int main(){
    Stack num_stack;
    Stack opr_stack;
    InitList_stack(num_stack);
    InitList_stack(opr_stack);
    char s[100] = {0};
    gets(s);    
    printf("结果是:%f",calculate(s,&num_stack,&opr_stack));
    return 0;
}

码文不易,如果帮助到您,希望您可以帮我刷一下点击量,与您无害,与我有益谢谢 支持原创

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值