您的位置:首页 > 编程语言 > C语言/C++

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

2017-11-30 13:06 603 查看

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

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

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

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

实验环境

语言c/c++

编译器devc++5.11/5.40

实验内容与要求

问题描述:

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

目录

顺序栈使用——表达式求值
实验环境

实验内容与要求

目录

实验解析
思路方法

定义说明

函数说明
流程图

运算函数
进行一步运算

进行一级运算

计算

主函数

结果展示

附录
相关资料

源代码
Stack.h

main.cpp

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

实验解析

思路方法

  可以使用两个工作栈:

一个栈OPTR存放运算符;

另一个栈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初始化读取完毕?获取运算结果返回结果,程序结束读取数据进栈,乘除直接运算遇到"()"?运算"()"内数据"()"前有"*/"?运算一步乘除yesnoyesnoyesno

运算函数

进行一步运算

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
10755
_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;
}


结果展示



附录

相关资料

顺序栈的各种基本运算

源代码

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

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; }


码文不易,如果帮助到您,希望您可以帮我刷一下点击量,与您无害,与我有益谢谢 支持原创
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息