最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

中缀表达式转为后缀表达式并求值

来源:动视网 责编:小OO 时间:2025-10-06 04:32:56
文档

中缀表达式转为后缀表达式并求值

哈尔滨工业大学计算机科学与技术学院实验报告课程名称:数据结构与算法课程类型:必修实验项目名称:线性表的实现与应用实验题目:中缀表达式转成后缀表达式并求值班级:1203103学号:1120310321姓名:张文博设计成绩报告成绩指导老师一、实验目的:1.练习栈的创建和常规操作,例:置空栈,判断空栈,返回栈顶元素,压栈,出栈……2.学习中缀表达式和后缀表达式的定义和表示方法。3.学习中缀表达式和后缀表达式的存储和输出。4.学习中缀表达式转化为后缀表达式。5.学习后缀表达式的求值。6.练习编写循环程
推荐度:
导读哈尔滨工业大学计算机科学与技术学院实验报告课程名称:数据结构与算法课程类型:必修实验项目名称:线性表的实现与应用实验题目:中缀表达式转成后缀表达式并求值班级:1203103学号:1120310321姓名:张文博设计成绩报告成绩指导老师一、实验目的:1.练习栈的创建和常规操作,例:置空栈,判断空栈,返回栈顶元素,压栈,出栈……2.学习中缀表达式和后缀表达式的定义和表示方法。3.学习中缀表达式和后缀表达式的存储和输出。4.学习中缀表达式转化为后缀表达式。5.学习后缀表达式的求值。6.练习编写循环程
哈尔滨工业大学计算机科学与技术学院

实验报告

课程名称:数据结构与算法

课程类型:必修

实验项目名称:线性表的实现与应用

实验题目:中缀表达式转成后缀表达式并求值

班级:1203103

学号:1120310321

姓名:张文博

设计成绩报告成绩指导老师一、实验目的:

1.练习栈的创建和常规操作,例:置空栈,判断空栈,返回栈顶元素,压栈,出栈……

2.学习中缀表达式和后缀表达式的定义和表示方法。

3.学习中缀表达式和后缀表达式的存储和输出。

4.学习中缀表达式转化为后缀表达式。

5.学习后缀表达式的求值。

6.练习编写循环程序的算法。

二、实验要求及实验环境

实验要求:输入中缀表达式,把中缀表达式转化为后缀表达式,输出后缀表达式,并对后缀表达式进行求值输出,其中能运行算术四则运算和求模运算。

实验环境:codeblocks

三、设计思想(本程序中的用到的所有数据类型的定义,主程序的流程图及各程序模块之间的调用关系)

1.逻辑结构:线性结构

2.物理结构:线性存储结构中的顺序结构,即用数组和栈存储数据。

本实验中定义了两种线性表形式:数组和栈。用字符型数组存储输入的字符串和和转化为的后缀表达式。在把中缀表达式转化为后缀表达式时,用字符栈存储字符串中的字符,并永远保证栈顶的字符优先级最高;在进行后缀表达式求值时,用数据栈存储数字,按顺序存储,遇到字符时,从栈顶依次弹出两个数据。此外,还定义了一些整型和字符型变量,用于辅助程序的正确运行。

主函数中调用change函数,把中缀表达式转化为后缀表达式;主函数调用operate函数,进行算术式的运算。Change函数调用precede 函数,进行字符优先级的比较。主函数和change函数都调用in函数,进行是否为字符的判断。此外,主函数和change函数都有调用initstack 函数,push函数,pop函数,gettop函数……来帮助函数的运行。

我编写程序的大致思路:

1.中缀表达式转为后缀表达式

首先是遇见数字存入数组,遇见字符压栈,并且先把字符栈底压入一个‘#’。当遇见‘(’时,根据下一个字符是否是‘-’来判断是否是负数。若有‘-’,是负数,存入数组,若没有,把‘(’压栈。例:(-5)。当遇见‘)’时,开始把运算符弹栈,直到遇到‘(’。

当遇见其他运算符时,根据比较与字符栈顶元素的优先级决定如何压栈。优先级设定:#为0,()为1,+-为2,*/%为3。当栈顶元素的优先级大于等于此运算符时,弹栈进入数组,否则把该运算符压栈。

2.求后缀表达式的值

遇见数字时压栈,遇见运算符时从栈中弹出两个,进行运算。

遇见‘-’时,根据后一位元素是否为数字,进而判断是负号,还是减号,若是负号,求出该负数对应的正数,再取反压栈即可。

遇见浮点数数时,先求小数点前面的整数部分,再求小数点后面整数部分,根据位数a,除以10*a,即可得到小数部分,小数部分与整数部分相加即为该浮点数,压栈即可。

开始

输入中缀表达式

并存储到数组中

调用change函数,

把中缀表达式转

化为后缀表达式

输出相应的

后缀表达式

计算后缀表

达式的值

输出后缀表

达式的值

结束四、测试结果

输入中缀表达式输出后缀表达式结果

(2.5*4+5)/3 2.5 4 * 5 + 3 / 5

(-5)+10*2/(-4) -5 10 2 * -4 / + -10

五、系统不足与经验体会

系统不足:没有完全考虑输错情况下,程序该如何操作,进而导致程序的健壮性不好,此外,没有过多的考虑由于外面因素,程序错误运行的情况。

经验体会:1.对栈的操作要深刻明白先进后出,后进

数据的位于栈顶。

2.数组是按址调用,在调用函数内可以改变

其值。

3.程序循环运行每轮结束后,一定要记得释

放内存,或清空数组里的内容。

4.小数和负数要特殊考虑,编写合适的算法。

5.条件语句中的条件要慎重考虑,反复斟酌。

六、附录:源代码(带注释)

#include

#include

#define SIZE 100#define ERROR 0

typedef struct //定义数据栈

{

float data[SIZE];

int top;

int base;

} SqStack_f;

typedef struct //定义字符栈

{

char data[SIZE];

int top;

int base;

} SqStack_c;

char OPSET[8]= {'+' , '-' , '*' , '/' ,'%','(' , ')' , '#'}; //定义OPSET字符数组为算符集合

void InitStack_f(SqStack_f *s) //置数据栈S为空

{

s->top=0;

s->base=0;

}

void InitStack_c(SqStack_c *s) //置字符栈S为空{

s->top=0;

s->base=0;

}

int Empty_f(SqStack_f *s) //判定s是否为空栈{

if(s->base==s->top)

return 1;

else

return 0;

}

int Empty_c(SqStack_c *s) //判定s是否为空栈{

if(s->base==s->top)

return 1;

else

return 0;}

float GetTop_f(SqStack_f *s)//若数据栈非空,则返回s的栈顶元素;否则返回ERROR

{

if(s->top==s->base)

return ERROR;

return (s->data[s->top-1]);

}

char GetTop_c(SqStack_c *s)//若字符栈非空,则返回s的栈顶元素;否则返回ERROR

{

if(s->top==s->base)

return ERROR;

return (s->data[s->top-1]);

}

void Push_f(SqStack_f *s,float e)//插入e为新的栈顶元素{

s->data[s->top]=e;

s->top++;}

void Push_c(SqStack_c*s,char e)//插入e为新的栈顶元素

{

s->data[s->top]=e;

s->top++;

}

float Pop_f(SqStack_f *s)//若数据栈不空,则删除之,并返回栈顶值;否则返回REEOR

{

float e;

if(s->base==s->top)

return ERROR;

else

{

e=s->data[s->top-1];

s->top--;

}

return e;

}

{

char e;

if(s->base==s->top)

return ERROR;

else

{

e=s->data[s->top-1];

s->top--;

}

return e;

}

int In(char s,char *TestOp)//s为待判断字符,TestOp为已知的算符集合

{

int Find=0,i;

for ( i=0; i<8; i++)

{

if (s == TestOp[i])

{

Find= 1;}

}

return Find;

}

int precede(char Top_char,char s1_char)//判断优先级{

int i,pre[2];

char op[2];

op[0]=Top_char;

op[1]=s1_char;

for(i=0; i<2; i++)

{

switch(op[i])

{

case'#':

pre[i]=0;

break;

case'(':

case')':

pre[i]=1;break;

case'+':

case'-':

pre[i]=2;

break;

case'*':

case'/':

case'%':

pre[i]=3;

break;

}

}

if(pre[0]>=pre[1])

return 1;

else

return 0;

}

void Change(char *s1,char *s2)//将中缀表达式转为后缀表达式{

SqStack_c OPTR;

char ch;

int i=0,j=0;

InitStack_c(&OPTR);

Push_c(&OPTR,'#');

while(s1[i]!='\\0')

{

if(!In(s1[i],OPSET)) //不是运算符则进数组

{

while((s1[i]>='0'&&s1[i]<='9')||s1[i]=='.')

{

s2[j++]=s1[i];

i++;

}

s2[j++]=' ';//存入一个空格

}

else

{

switch(s1[i])

{

case '(':

i++;

if(s1[i]=='-')//此处判断是否是负数,若是,把负数存入数组,若不是,把运算符存入堆栈。

{

while(s1[i]!=')')

{

s2[j++]=s1[i];

i++;

}

s2[j++]=' ';//存入一个空格

i++;

}

else

{

i--;

Push_c(&OPTR,s1[i]);

i++;

}

break;

case ')':

ch=Pop_c(&OPTR);

do //输出括号内的所有运算符 {s2[j++]=ch;

s2[j++]=' ';//补入一个空格作为间隔

ch=Pop_c(&OPTR);

}

while(ch!='(');

i++;

break;

default:

while(precede(GetTop_c(&OPTR),s1[i]))//判断运算符的优先级,始终保存栈顶的优先级最高

{

s2[j++]=Pop_c(&OPTR);

s2[j++]=' ';//补入一个空格作为间隔

}

Push_c(&OPTR,s1[i]);

i++;

}

}

}

while(GetTop_c(&OPTR)!='#')//当s1扫描完成后,把运算符栈中的运算符全部输出存入数组s2

{s2[j++]=Pop_c(&OPTR);

s2[j++]=' ';//补入一个空格作为间隔

}

}

float Operate(float a,char theta, float b)//返回a与b间theta 运算的结果

{

int d,e;

switch(theta)

{

case '+':

return a+b;

break;

case '-':

return a-b;

break;

case '*':

return a*b;

break;

case '/':

if(b==0){

printf("Error Divisor is 0\\n"); return ERROR;

}

return a/b;

break;

case '%':

d=(int)a;

e=(int)b;

if(e==0)

{

printf("Error Divisor is 0\\n"); return ERROR;

}

return (float)(d%e);

break;

default:

printf("Error\\n");

return ERROR;

}

}

{

SqStack_f OPND;

char c,ch;

int i=0,step=0,j=0;

float a=0,b=0,s=0 ;

do

{

i=0;

char receive[100]= {0},exp[100]= {0};

InitStack_f(&OPND);

printf("请输入一个中缀表达式:\\n");

gets(receive); //输入中缀表达式,负数的输入必须要加括号,eg:(-5)+6

Change(receive,exp);

printf("相应的后缀表达式为:\\n");

puts(exp); //输出对应的后缀表达式

ch=exp[0];

while(ch!='\\0') //计算后缀表达式的值

{

if(!In(exp[i],OPSET))//不是运算符则压入栈中

{

s=0;

a=b=step=0;

while(exp[i]>='0'&&exp[i]<='9'&&exp[i]!='.'&&exp[i]!=' ')//算出小数点前面的整数数值

{

s=10*s+exp[i]-48;

i++;

}

if(exp[i]=='.') //满足此条件的为小数,算出小数点后面的数值

{

i++;

while(exp[i]>='0'&&exp[i]<='9'&&exp[i]!=' ')

{

b=10*b+exp[i]-48;

i++;

step++;

}

{

b=b/10;

}

}

a=s+b; //一个数的整数部分和小数部分相加,赋于a

Push_f(&OPND,a);

ch=exp[++i];

}

else if(exp[i]=='-') //判断-为减号还是负号 {

i++;

if(exp[i]>='0'&&exp[i]<='9') //满足此条件为负号,计算出该负数,并压入堆栈

{

s=0;

a=b=step=0;

while(exp[i]>='0'&&exp[i]<='9'&&exp[i]!='.'&&exp[i]!=' ')//算出小数点前面的整数数值{

s=10*s+exp[i]-48;

i++;

}

if(exp[i]=='.')//满足此条件的为小数,算出小数点后面的数值

{

i++;

while(exp[i]>='0'&&exp[i]<='9'&&exp[i]!=' ')

{

b=10*b+exp[i]-48;

i++;

step++;

}

for(j=0; j{

b=b/10;

}

a=-(s+b);//一个数的整数部分和小数部分相加,赋于a并取反,即为该负数值

Push_f(&OPND,a);

ch=exp[++i];

}

else //此时-为减号,按运算符进行运算

{

b=Pop_f(&OPND);

a=Pop_f(&OPND);

Push_f(&OPND,Operate(a,ch,b));

ch=exp[++i];

}

}

else //按相应的运算符进行计算

{

b=Pop_f(&OPND);

a=Pop_f(&OPND);

Push_f(&OPND,Operate(a,ch,b));

i+=2;

ch=exp[i];}

}

printf("后缀表达式的值为:%g\\n

c=getchar();

getchar();

}

while(c=='Y'||c=='y'); //处理是否想要继续操作

return 0;

}

文档

中缀表达式转为后缀表达式并求值

哈尔滨工业大学计算机科学与技术学院实验报告课程名称:数据结构与算法课程类型:必修实验项目名称:线性表的实现与应用实验题目:中缀表达式转成后缀表达式并求值班级:1203103学号:1120310321姓名:张文博设计成绩报告成绩指导老师一、实验目的:1.练习栈的创建和常规操作,例:置空栈,判断空栈,返回栈顶元素,压栈,出栈……2.学习中缀表达式和后缀表达式的定义和表示方法。3.学习中缀表达式和后缀表达式的存储和输出。4.学习中缀表达式转化为后缀表达式。5.学习后缀表达式的求值。6.练习编写循环程
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top