C语言 后缀表达式计算

C语言 后缀表达式计算
C语言 后缀表达式计算

一、设计思想

计算算数表达式并求值,采取的共有两种方法:

1.先将算数表达式转化为后缀表达式,然后对后缀表达式进行计算。

2.对算数表达式进行直接的计算。

第一种算法

这种解决方案又分为两步:

1.将表达式先转化为后缀表达式的字符串数组

2.利用后缀表达式进行计算

在转化过程中,第一,建立一个存符号的栈,和一个字符串数组,用来存放转化以后的表达式

然后,对于得到的用户输入的字符串进行逐个的扫描,如果是数组或者小数点,则直接存放到数组中,并且在后面加入一个分隔符,如果是操作符,则和栈中的已存的进行比较,如果比栈中的操作符的优先级高,则直接入栈,如果优先级低或相等,则栈中元素出栈,存到字符串中,然后再次检查栈顶,直到栈中元素的优先级低于扫描操作符,则此操作符入栈,然后扫描下一个字符,直到遇到字符串的结束符号\0,扫描结束。数组中存的就是后缀表达式。得到后缀表达式后,进行计算,要用到数值栈。首先要将字符表示的数字转化为浮点小数,然后进行扫描,遇到数值,放入栈中,遇到操作符,就从栈中取出两个数,进行计算后再放入栈中,扫描下一个,最后的计算结果就存到了栈中,直接取出栈内元素,就是计算的最后结果。

第二种算发

首先要建立两个栈,一个用来存放操作符,一个用来存放数值。开始对用户输入的字符串进行扫描,如果是数字字符或者小数点,则将字符转化为浮点数存到数栈里,如果是操作符,则观察符号栈,如果栈顶元素的优先级低于观察的操作符,则操作符入栈,如果栈顶元素的优先级高于或者等于观察的操作符,则从数值栈中取出两个浮点数,从符号栈中取出栈顶的操作符,然后进行相应的数值计算,所得的结果再存到数值栈中,重复这样的操作,直到符号栈中栈顶元素的优先级低于观察的操作符,则此操作符入栈,然后对下一个字符进行扫描。如果是左括号,则不进行优先级的比较,直接入栈,入栈后优先级为-1。如果是右括号,则从数值栈中取两个操作数,符号栈中取出一个符号,然后进行计算后得数放入数栈中,不断进行此类操作,直到从栈中取出的是左括号为止,左括号去掉,扫描下一个。扫描结束后,计算也结束了,计算的结果就存放在数值栈中,最后把数值栈中的数取出,就是所得的计算结果。

容错的算法简要:

括号匹配:当扫描到左括号是,左括号直接入栈,扫描到右括号时,则左括号出栈,如果栈为空,则右括号多,如果最后栈中还有括号,则左括号多。给出错误提示。

除数不为0:当扫描到'/'时,就判断其后面的数字是否为0,如果为0报错。

取余运算:取余运算时,操作数判断是否为整数,不为整数报错。

二、算法流程图

第一种算法:先将表达式转化为后缀表达式,然后计算

其主函数流程图为:

图1 主函数算法流程图

其中将中缀表达式转化为后缀表达式的主要流程为:

图2 中缀转化为后缀算法流程图

返回直接计算的结果

得到用户输入 的中缀表达式

调用容错函数

存在错误 报错并结束

无错

调用函数得到

后缀表达式 后缀表达 式的计算 返回计算结果

调用直接计 算的函数 左括号

优先级不高于栈顶

取得字符 并判断

如果是数字 或小数点

直接放入字符数组中 在其后加入分隔符 如果是操作符

与栈顶比较

判断哪类括号

直接入栈 右括号

取出不为'('

从栈中取 出操作符

放入数组

直接入栈

优先级高于栈顶

如果是括号

出栈存入数组中

后缀表达式的计算,实现的流程图为:

图3 后缀表达式计算算法流程图

下面介绍直接计算出结果的算法的实现:

图4 直接计算中缀表达式算法流程图

从数栈取2个数做相应计

算结果存入数栈

判断符号类型 得到后缀表达式

数字字符

操作符

转化为浮点数入栈

从数栈中取出计算结果作为返回值

栈非空

栈空

低于栈顶

高于栈顶

NO

YES

左括号

得到中缀表达式

从字符串中取出一个字符

判断字符类型

数字字符

操作符

转化为浮点数入栈 括号

括号类型

直接入栈

右括号

从栈中取出操作符

是否为(

丢弃(

放入 数组

与栈顶比较

直接入栈

取出栈顶两个 数作相应计算 结果存入数栈

符号栈是 否为空

将数值栈 顶返回

取栈顶符号与2个数计算,

结果存入数值栈

三、源代码

下面给出的是用先转后缀再计算和直接计算的算法实现的程序的源代码:#include /*导入需要用到的各种包*/

#include

#include

typedef struct /*定义结构体用来存储操作符*/

{

char op; /*存储字符*/

int level; /*存储优先级*/

}OpNode;

typedef struct

{

OpNode op[100];

int top;

int size; /*表示栈内元素的个数*/

} stack; /*定义符号栈*/

void init(stack *st) /*初始化栈*/

{

st->size=0;

st->top=0;

}

OpNode pop(stack *a) / *出栈*/

{

if (a->size==0) /*如果栈为空结束操作*/

{

exit(-1);

}

a->size--;

return a->op[--(a->top)]; /*取出栈顶元素*/

}

void push(stack *a,OpNode op) /*入栈函数*/

{

a->size++;

a->op[(a->top)++]=op;

}

OpNode top(stack *a) /*观察栈顶函数*/

{

if (a->size==0) /*如果栈为空结束操作*/

{

printf("stack is empty\n");

exit(-1);

}

return a->op[(a->top)-1]; /*只得到栈顶的值而不出栈*/

}

typedef struct /*定义数值栈*/

{

double num[100];

int top; /*栈顶指针*/

int size;

} numstack;

void init2(numstack *st) /*初始化数值栈*/

{

st->size=0;

st->top=0;

}

double pop2(numstack *a) /*数值栈出栈*/

{

if (a->size==0) /*出栈前的判空*/

{

exit(-1);

}

a->size--;

return a->num[--(a->top)]; /*得到栈顶的值*/

}

void push2(numstack *a,double num) /*入栈*/

{

a->size++;

a->num[(a->top)++]=num;

}

void main() /*主函数*/

{

void change (char str[],char exp[]); /*声明要用到的各个函数*/

double CalResult(char exp[]); /*声明后缀表达式的计算函数*/

double Directcalresult(char str[]);

int check(char str[],char chestr[100]);

char str[100],exp[100],chestr[100]; /*str存储原算术表达式,exp存储对应的printf("算术表达式为:\n"); 后缀表达式,chestr存储容错字符'^'*/ gets(str);

if(check(str,chestr)) /*调用容错函数*/

{ printf("表达式错在:\n");

printf("%s\n",str);

printf(chestr); /*根据输入情况指出错误的地方*/

exit(-1);

}

change(str,exp); /*调用函数将中缀转化为后缀*/

printf("后缀表达式为:%s\n",exp);

printf("运算结果为:%f\n",CalResult(exp)); /*调用函数计算后缀表达式*/ printf("直接运算的结果为: %f\n",Directcalresult(str)); /*调用直接计算函数*/ }

void change (char str[],char ch[]) /*将前缀表达式转化为后缀表达式*/

{

int i=0; /*str的索引*/

int k=0;

char c; /*字符串中取出的放在C中*/

stack st; /*定义符号栈*/

OpNode op;

OpNode ops;

init(&st); /*初始化符号栈*/

c=str[i++];

while (c!='\0') /*对字符串进行扫描*/

{

if ( (c>='0'&&c<='9')||c=='.') /*如果字符为数字或小数点*/

{

while ( (c>='0'&&c<='9')||c=='.')

{

ch[k++]=c; /*将字符直接放入数组中*/

c=str[i++];

}

ch[k++]='|'; /*在其后面放入一个分隔符*/

}

if (c=='(') /*如果字符是左括号*/

{

op.op='(';

op.level=-1; /*定义其优先级为-1*/

push(&st,op); /*将左括号直接入栈*/

}

if(c==')') /*如果字符为右括号*/

{

op=top(&st); /*首先观察栈顶*/

while (st.size!=0&&op.op!='(') /*如果不是左括号并且栈不为空*/

{

op=pop(&st); /*出栈并存入数组中*/

ch[k++]=op.op;

if (st.size>0) /*再次检查栈是否为空,*/

op=top(&st);

else break; /*为空就结束*/

}

pop(&st); /*去掉左括号*/

}

if (c=='+'||c=='-') /*如果是+-号*/

{

op.op=c;

op.level=1; /*优先级为1*/

if (st.size==0)

{

push(&st,op); /*如果此时栈为空直接入栈*/ }

else

{

ops=top(&st); /*观察栈顶*/

while (ops.level>=op.level) /*如果栈顶优先级高*/

{

ops=pop(&st);

ch[k++]=ops.op; /*将栈顶元素取出存入数组中*/

if (st.size>0)

ops=top(&st); /*进行判空操作,栈为空结束*/

else

break;

}

push(&st,op); /*此时栈顶优先级低,入栈*/ }

}

if(c=='*'||c=='/'||c=='%') /*如果是*/进行*/

{

op.op=c;

op.level=2; /*优先级为1*/

if (st.size==0)

{

push(&st,op); /*如果此时栈为空直接入栈*/ }

else

{

ops=top(&st); /*观察栈顶*/

while (ops.level>=op.level) /*如果栈顶优先级高*/

{

ops=pop(&st); /*将栈顶元素取出存入数组中*/

ch[k++]=ops.op;

if (st.size>0)

ops=top(&st); /*进行判空操作,栈为空结束*/ else

break;

}

push(&st,op); /*此时栈顶优先级低,入栈*/

}

}

c=str[i++]; /*索引自加检索下一个字符*/

}

while(st.size!=0) /*最后判断栈如果不为空*/ {

ops=pop(&st); /*取出栈内元素存入数组中*/

ch[k++]=ops.op;

}

ch[k]='\0'; /*将\0作为结尾存入数组*/

}

double CalResult(char exp[]) /*后缀表达式的计算*/

{

char c;

numstack numst; /*建立数值栈*/

double d1,d2,dr;

int k=0; /*后缀表达式的索引*/

int i=0; /*将字符转化为浮点数的索引*/ char *s;

char trans[100]; /*存字符表示的一段数字*/

init2 (&numst); /*实现数值栈*/

c=exp[k++];

while (c!='\0') /*开始扫描后缀表达式*/

{

if(c=='+'||c=='-'||c=='*'||c=='/'||c=='%') /*如果是操作符*/

{

switch(c)

{

case '+' : /*如果是加法操作*/

d2=pop2(&numst);

d1=pop2(&numst);

dr=d1+d2; /*相加后入栈*/

push2(&numst,dr);

break;

case '-' : /*如果是减法操作*/

d2=pop2(&numst);

d1=pop2(&numst);

dr=d1-d2; /*相减后入栈*/

push2(&numst,dr);

break;

case '*' : /*如果是乘法操作*/

d2=pop2(&numst);

d1=pop2(&numst);

dr=d1*d2; /*相乘后入栈*/

push2(&numst,dr);

break;

case '/' : /*如果是除法操作*/

d2=pop2(&numst);

d1=pop2(&numst);

dr=d1/d2; /*相除后入栈*/

push2(&numst,dr);

break;

case '%' : /*如果是取余操作*/

d2=pop2(&numst);

d1=pop2(&numst);

dr=(double)((int)d1%(int)d2); /*类型转化并取余后入栈*/

push2(&numst,dr);

break;

}

}

if (c>='0'&&c<='9'||c=='.') /*如果是字符表示的数字*/

{

while(c>='0'&&c<='9'||c=='.')

{

trans[i++]=c; /*将字符存入数组进行下一个的扫描*/

c=exp[k++];

}

trans[i++]='\0'; /*将表示数字的字符串结束*/

i=0;

s=trans; /*将指针指向该数组*/

d1=atof(s); /*利用函数将字符串转化为浮点数*/

push2(&numst,d1);

}

c=exp[k++];

}

return pop2(&numst); /*最后结果将在数值栈中,取出作为返回值*/ }

double Directcalresult(char str[]) /*表达式的直接计算出结果*/

{

stack ms; /*建立符号栈*/

numstack mns; /*建立数值栈*/

double calculate(double od1,double od2,OpNode op);

int index=0; /*str的索引*/

int len=strlen(str);

char c;

char trans[100]; /*存放数值的一段字符*/

int i=0; /*trans的索引*/

char * s;

double d;

OpNode tempn; /*存放当前扫描的操作符*/

OpNode templn;

double oda,odb,odr;

double result; /*作为返回值返回结果*/

init (&ms); /*实现两个栈*/

init2(&mns);

while(index

c=str[index++];

if(c>='0'&&c<='9'||c=='.') /*如果是数字字符或小数点*/

{

while(c>='0'&&c<='9'||c=='.')

{

trans[i++]=c; /*将其存入数组扫描下一个*/

c=str[index++];

}

trans[i++]='\0'; /*扫描完一个数结束数组*/

i=0; /*索引归0*/

s=trans;

d=atof(s);

push2(&mns,d); /*转化为浮点数入栈*/ }

if(c=='+'||c=='-') /*如果是+-*/

{

tempn.level=1; /*优先级设为1*/

tempn.op=c;

if(ms.size==0)

{

push(&ms,tempn); /*栈为空直接入栈*/

}

else

{

templn=top(&ms);

while (templn.level>=tempn.level) /*栈顶优先级高*/

{

templn=pop(&ms); /*取出操作数和操作符计算*/

odb=pop2(&mns);

oda=pop2(&mns);

odr=calculate(oda,odb,templn);

push2(&mns,odr); /*结算结果入栈*/

if(ms.size>0)

{

templn=top(&ms); /*如果栈空结束*/

}

else

break;

}

push(&ms,tempn); /*操作符入栈*/

}

}

if(c=='*'||c=='/'||c=='%') /*如果是*/%操作*/

{

tempn.level=2; /*定义优先级为2*/

tempn.op=c;

if(ms.size==0)

{

push(&ms,tempn); /*栈空直接入栈*/

}

else

{

templn=top(&ms);

while (templn.level>=tempn.level) /*栈顶优先级高*/

{

templn=pop(&ms); /*取出操作数和操作符计算*/ odb=pop2(&mns);

oda=pop2(&mns);

odr=calculate(oda,odb,templn);

push2(&mns,odr); /*结算结果入栈*/

if(ms.size>0)

{

templn=top(&ms);

}

else

break; /*如果栈空结束*/

templn=top(&ms);

}

push(&ms,tempn); /*操作符入栈*/

}

}

if(c=='(') /*如果是左括号*/

{

tempn.level=-1;

tempn.op=c; /*直接入栈优先级定位-1*/

push(&ms,tempn);

}

if(c==')') /*如果是右括号*/

{

while(tempn.op!='(') /*遇到左括号结束*/

{

templn=pop(&ms);

odb=pop2(&mns); /*从数栈中取两个数,从符号栈里取操作符*/

oda=pop2(&mns);

odr=calculate(oda,odb,templn); /*计算出结果入栈*/

push2(&mns,odr);

if (ms.size>0)

tempn=top(&ms);

else

break; /*如果栈空结束*/

}

pop(&ms); /*取出左括号*/

}

}

tempn=top(&ms);

while(1)

{

templn=pop(&ms);

odb=pop2(&mns); /*从数栈中取两个数,从符号栈里取操作符*/

oda=pop2(&mns);

odr=calculate(oda,odb,templn); /*计算出结果入栈*/

push2(&mns,odr);

if (ms.size>0)

tempn=top(&ms); /*如果栈空结束*/

else

break;

}

result =pop2(&mns); /*最后的结果在数值栈中返回*/

return result;

}

double calculate(double od1,double od2,OpNode op) /*已知操作符和操作数的计算*/ {

switch(op.op)

{

case '+' : return od1+od2;

case '-' : return od1-od2; /*判断操作符是哪个执行相应计算*/

case '*' : return od1*od2;

case '/' : return od1/od2;

case '%' : return (double)((int)od1%(int)od2);

}

return 0; /*如果上面的都没有执行返回0*/

}

int check(char str[],char chestr[100]) /*容错函数*/

{

char c;

char cdivide;

int i=0; /*str的索引*/

stack che; /*括号匹配用到的栈*/

OpNode temp;

int k=0; /*chestr的索引*/

int isinteger(char integer[100]); /*%计算是判断是否是整数*/

char s1[10]; /*%操作时存储%左右的数字*/

char s2[10];

int indexs1=0; /*s1s2的索引*/

int indexs2=0;

init (&che);

int flag=0; /*0——没有出错1——有错*/

int tag=0;

c=str[i]; /*开始扫描*/

int j; /*数组chestr索引*/

for(j=0;j<99;j++)

{

chestr[j]=' '; /*数组初始化待以后加入'^'*/ }

chestr[j]='\0';

while(c!='\0')

{

if(c=='(') /*如果是左括号就入栈*/

{

temp.op=c;

push(&che,temp);

}

if(c==')') /*如果是右括号*/

{

if(che.size>0)

{

pop(&che); /*栈不为空就取出一个左括号*/ }

else

{

flag=1;

printf("缺少左括号\n"); /*否则提示有错*/

chestr[i]='^'; /*右括号下加'^'*/ }

}

if(c=='/') /*判断除数是否为0*/

{

j=0;

cdivide=str[i+1+j]; /*取出除号后的数*/

while(cdivide>='0'&&cdivide<='9'||cdivide=='.') /*如果是数或小数点就一直存*/ {

s1[j++]=cdivide;

if(cdivide!='0'&&cdivide!='.') /*如果不是0则正确并结束*/

{

tag=1;

break;

}

cdivide=str[i+j+1];

}

if(!tag) /*如果tag为0则存在错误除数为0*/

{

chestr[i+1]='^';

flag=1; /*flag为1表示有错*/

}

}

if(c=='%') /*取余操作的容错*/

{

while(str[i-indexs1-1]>='0'&&str[i-indexs1-1]<='9'

||str[i-indexs1-1]=='.') /*以%为中心向前扫描*/ {

s1[indexs1++]=str[i-indexs1-1]; /*如果是数或小数点*/ } /*放在s1中*/

while(str[i+indexs2+1]>='0'&&str[i+indexs2+1]<='9' /*以%为中心向后扫描*/ ||str[i+indexs2+1]=='.')

{ /*如果是数或小数点*/ s2[indexs2++]=str[i+indexs2+1]; /*放在s1中*/ }

if(isinteger(s1)) /*调用函数判断s1内存到是否是整数*/ {

printf("取余算法第一个数应为整数运算\n");

flag=1; /*记录为有错*/

chestr[i-indexs1]='^';

}

if(isinteger(s2)) /*调用函数判断s2内存到是否是整数*/

{

printf("取余算法第二个数应为整数运算\n");

flag=1; /*记录为有错*/

chestr[i+indexs2]='^';

}

}

i++;

c=str[i]; /*检索下一个字符*/ }

if(che.size>0)

{ /*如果最后栈不为空*/

printf("缺少右括号\n"); /*栈中还有没配对的左括号报错*/ }

return flag; /*返回是否有错*/

}

int isinteger(char integer[100]) /*判断数组内是否是整数*/

{

int i=0; /*传过来的数组的索引*/

char c;

c=integer[i++];

while(c!='\0') /*直到字符串最后扫描结束*/

{

if(c=='.') /*只要有一个字符为小数点就不是整数*/

return 1;

else

c=integer[i++]; /*扫描下一个*/

}

return 0;

}

四、运行结果

在输入表达式没有错误的情况下,可以得到两种算法的运算结果为:

图5 表达式正确时两种算法运行结果图

如果表达式的输入有错误,运行结果分别如下:

1.除数为0

图6 除数为0提示错误图2.取余运算操作数不为整数:

图7取余操作数不为整提示错误图3.括号匹配的问题:

图8 缺少左括号提示错误图

图9缺少右括号提示错误图

五、遇到的问题及解决

在编程的时候总是会有很多的意想不到的为题出现。

这部分我主要遇到了如下两个问题,其内容与解决方法如下所列:

●将字符表示的数字转化为浮点数

这个操作的主要目的就是数字是用一串字符表示的,在计算的过程中就要把字符串转化成对应的浮点数,要解决这个问题,首先查找C语言的库函数,其中找到一个可以将字符串转化为浮点数的函数atof()。那么就需要将数值的一串字符存入预定的数组中。利用循环到时可以得到要求,但是总是出现如下情况:

图10 转化为浮点时的错误

出现这种情况,首先确定后缀表达式是正确的,但在后缀表达式的计算时出现了错误,导致结果出错。检查程序,没有语法错误。逐步打印可以看到的结果,发现在利用atof后用printf函数打印时出现了错误,最后才发现是因为在每一次调用atof时都要将一串字符存入trans数组,可是,每次存储结束时,却忘记将trans数组的索引重新设为0,这就导致了数组中是多个数都存到了数组中,然后就把数组转化为浮点数,导致了浮点数不是应得的数值。只要将trans的数组索引i每次都归零就可以了。

●在将中缀转化为后缀表达式的过程中,得不到结果

得到用户输入的中缀表达式后调用函数,目的是得到后缀表达式

可是总是出现如下的情况:

图11 转化为浮点时的错误

由于学习C语言的时候使用的编译器是WIN TC而这次编程使用的是VC,询问过用VC的人之后才知道,如果字符串没有结束符号就会“喊烫”。检查程序后才知道,在将中缀转化为后缀的时候,在最后没有对字符串手动的加入'\0'来表示结束。因此,在程序的最后加入ch[k]='\0'; 就可以了。

六、心得体会

大一就开始学习C语言,可是,当时学的时候就觉得语言好像是学会了,可是一遇到编程的问题还是头大,总感觉没有什么思路,而这次作业,给自己一个不得不动手操作的机会,在十一的这几天中,复习了以前学过的C的基本知识,然后一点一点的摸索,遇到了错误和同学一起讨论,有问题自己想办法解决,最后程序调试出来的时候,会觉得真的很高兴。我知道,我们现在的水平还很差,要想学习好这门课,在以后就要多动手操作,书上的例题或算法,最好都自己编写程序实现,那样可以加深对算法的理解,也可以提高我们编程的水平。同时,很多的东西,理解了,可是在实现的时候还是有很多的错误发生,在以后的练习和实践中,应该多动手,遇到问题多思考,即使方案不是最优的也要想办法自己解决,然后和好的方案进行比较,从中找出自己的差距在哪里。

后缀表达式求值

一、设计思想 首先,将中缀表达式转换为后缀表达式。转换算法思路:设中缀表达式已存入数组E[n];由于后缀表达式中操作数的次序与中缀表达式一致,故扫描到中缀表达式操作数时直接输出到B[n]即可;对于运算符,视其优先级别,优先级高的运算符先输出;设一存放运算符的栈s,先将s置空;依次扫描E[n]中各分量E[i]送x: 若x=“”(结束符),依次输出栈s中运算符,转换结束; 若x=操作数,直接输出x到B[n]中; 若x=‘)’,反复退栈输出栈s中子表达式运算符,直到栈顶符=‘(’,并退掉栈顶的‘(’; 若x=操作符,反复退栈输出栈s中运算符,直到栈顶符

三、源代码 下面给出的是用后缀表达式求值算法实现的程序的源代码: #include #include #define MaxSize 50 struct { char data[MaxSize]; int top; } op;//定义栈; struct { float data[MaxSize]; int top; } st; //中缀转换为后缀 void trans(char*exp,char*postexp) { int i=0; op.top=-1; while(*exp!='\0') { switch(*exp) { case'(': op.top++;op.data[op.top]=*exp; exp++;break; case')': while(op.data[op.top]!='(') { postexp[i++]=op.data[op.top]; op.top--; } op.top--;exp++;break; case'+': case'-': while(op.top!=-1&&op.data[op.top]!='(') { postexp[i++]=op.data[op.top]; op.top--; }

(完整版)数学表达式计算(c语言实现)

一、设计思想 计算算术表达式可以用两种方法实现: 1.中缀转后缀算法 此算法分两步实现:先将算术表达式转换为后缀表达式,然后对后缀表达式进行计算。具体实现方法如下: (1)中缀转后缀 需要建一个操作符栈op和一个字符数组exp,op栈存放操作符,字符数组用来存放转换以后的后缀表达式。首先,得到用户输入的中缀表达式,将其存入str数组中。 对str数组逐个扫描,如果是数字或小数点,则直接存入exp数组中,当扫描完数值后,在后面加一个#作为分隔符。 如果是操作符,并且栈为空直接入栈,如果栈不为空,与栈顶操作符比较优先等级,若比栈顶优先级高,入栈;如果比栈顶优先级低或相等,出栈将其操作符存到exp数组中,直到栈顶元素优先等级低于扫描的操作符,则此操作符入栈;如果是左括号,直接入栈,如果是右括号,出栈存入exp数组,直到遇到左括号,左括号丢掉。然后继续扫描下一个字符,直到遇到str中的结束符号\0,扫描结束。结束后看op栈是否为空,若不为空,继续出栈存入exp数组中,直到栈为空。到此在exp数组最后加结束字符\0。 我们就得到了后缀表达式。 (2)后缀表达式计算 此时需要一个数值栈od来存放数值。对exp数组进行逐个扫描,当遇到数字或小数点时,截取数值子串将其转换成double类型的小数,存入od栈中。当遇到操作符,从栈中取出两个数,进行计算后再放入栈中。继续扫描,知道扫描结束,此时值栈中的数值就是计算的结果,取出返回计算结果。 2.两个栈实现算法 此算法需要两个栈,一个值栈od,一个操作符栈op。将用户输入的数学表达式存入str数组中,对其数组进行逐个扫描。 当遇到数字或小数点,截取数值子串,将其转换成double类型的数值存入od栈中; 当遇到左括号,直接入op栈;遇到右括号,op栈出栈,再从值栈od中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到操作符栈栈顶为左括号,将左括号丢掉。 如果遇到操作符,若op栈为空,直接入栈;若栈不为空,与栈顶元素比较优先等级,若比栈顶操作符优先等级高,直接入op栈,如果低于或等于栈顶优先等级,op栈出栈,再从值栈中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到栈顶优先等级低于扫描的操作符等级,将此操作符入op栈。继续扫描直到遇到str中的结束字符\0,扫描结束。此时看操作符栈是否为空,若不为空,出栈,再从值栈中取出两个数值进行计算,将其结果存入值栈,一直进行此操作,直到操作符栈为空。此时把值栈中的数值取出,即为所得的最终计算结果。 二、算法流程图 第一种算法:中缀转后缀算法

C语言 后缀表达式计算

一、设计思想 计算算数表达式并求值,采取的共有两种方法: 1.先将算数表达式转化为后缀表达式,然后对后缀表达式进行计算。 2.对算数表达式进行直接的计算。 第一种算法 这种解决方案又分为两步: 1.将表达式先转化为后缀表达式的字符串数组 2.利用后缀表达式进行计算 在转化过程中,第一,建立一个存符号的栈,和一个字符串数组,用来存放转化以后的表达式 然后,对于得到的用户输入的字符串进行逐个的扫描,如果是数组或者小数点,则直接存放到数组中,并且在后面加入一个分隔符,如果是操作符,则和栈中的已存的进行比较,如果比栈中的操作符的优先级高,则直接入栈,如果优先级低或相等,则栈中元素出栈,存到字符串中,然后再次检查栈顶,直到栈中元素的优先级低于扫描操作符,则此操作符入栈,然后扫描下一个字符,直到遇到字符串的结束符号\0,扫描结束。数组中存的就是后缀表达式。得到后缀表达式后,进行计算,要用到数值栈。首先要将字符表示的数字转化为浮点小数,然后进行扫描,遇到数值,放入栈中,遇到操作符,就从栈中取出两个数,进行计算后再放入栈中,扫描下一个,最后的计算结果就存到了栈中,直接取出栈内元素,就是计算的最后结果。 第二种算发 首先要建立两个栈,一个用来存放操作符,一个用来存放数值。开始对用户输入的字符串进行扫描,如果是数字字符或者小数点,则将字符转化为浮点数存到数栈里,如果是操作符,则观察符号栈,如果栈顶元素的优先级低于观察的操作符,则操作符入栈,如果栈顶元素的优先级高于或者等于观察的操作符,则从数值栈中取出两个浮点数,从符号栈中取出栈顶的操作符,然后进行相应的数值计算,所得的结果再存到数值栈中,重复这样的操作,直到符号栈中栈顶元素的优先级低于观察的操作符,则此操作符入栈,然后对下一个字符进行扫描。如果是左括号,则不进行优先级的比较,直接入栈,入栈后优先级为-1。如果是右括号,则从数值栈中取两个操作数,符号栈中取出一个符号,然后进行计算后得数放入数栈中,不断进行此类操作,直到从栈中取出的是左括号为止,左括号去掉,扫描下一个。扫描结束后,计算也结束了,计算的结果就存放在数值栈中,最后把数值栈中的数取出,就是所得的计算结果。 容错的算法简要: 括号匹配:当扫描到左括号是,左括号直接入栈,扫描到右括号时,则左括号出栈,如果栈为空,则右括号多,如果最后栈中还有括号,则左括号多。给出错误提示。 除数不为0:当扫描到'/'时,就判断其后面的数字是否为0,如果为0报错。 取余运算:取余运算时,操作数判断是否为整数,不为整数报错。 二、算法流程图 第一种算法:先将表达式转化为后缀表达式,然后计算 其主函数流程图为:

二级C语言-运算符与表达式

二级C语言-运算符与表达式 (总分:60.00,做题时间:90分钟) 一、{{B}}选择题{{/B}}(总题数:38,分数:38.00) 1.设变量已正确定义并赋值,以下合法的C语言赋值语句是______。 ? A.x=y==5 ? B.x=n%2.5 ? C.x+n=i ? D.x=5=4+1 (分数:1.00) A. √ B. C. D. 解析:[解析] 赋值运算符左侧的操作数必须是一个变量,而不能是表达式或者常量,选项C和D错误。“%”运算符两侧都应当是整型数据,选项B错误。 2.在x值处于-2~2、4~8时值为“真”,否则为“假”的表达式是______。 ? A.(2>x>-2)||(4>x>8) ? B.!(((x<-2)||(x>2))&&((x<=4)||(x>8))) ? C.(x<2)&&(x>=-2)&&(x>4)&&(x<8) ? D.(x>-2)&&(x>4)||(x<8)&&(x<2) (分数:1.00) A. B. √ C. D. 解析:[解析] 本题是考查关系运算和逻辑运算的混合运算。要给出此题的正确答案,首先需要了解数学上的区间在C语言中的表示方法,如x在[a, b]区间,其含义是x既大于等于a又小于等于b,相应的C语言表达式是x>=a&&x<=b。本例中给出了两个区间,一个数只要属于其中一个区间即可,这是“逻辑或”的关系。在选项A中,区间的描述不正确。选项B把“!”去掉,剩下的表达式描述的是原题中给定的两个区间之外的部分,加上“!”否定正好是题中的两个区间的部分,是正确的。选项C是恒假的,因为它的含义是x同时处于两个不同的区间内。选项D所表达的也不是题中的区间。 3.sizeof(double)是______。 ? A.一种函数调用 ? B.一个整型表达式 ? C.一个双精度表达式 ? D.一个不合法的表达式 (分数:1.00)

C语言中条件运算符的语法为

条件运算符的语法为: (条件表达式)?(条件为真时的表达式):(条件为假时的表达式) 例如: x=ay?"greater than":x==y?"equal to":"less than" 它等价于: (x>y)?"greater than":((x==y)?"equal to":"less than") 当x>y时,值为"greater than",x==y时,值为"equal to",否则,值为"less than"。条件运算符的嵌套可读性不够好。 在一个条件运算符的表达式中,如果后面两个表达式的值类型相同,均为左值,则该条件运算符表达式的值为左值表达式。例如: int x=5; long a,b; (x?a:b)=1;//ok:因为a和b都是左值 (x?x:a)=2;//error:x和a不同类型。编译器将其解释为(1ong)x和a (x==271:a)=3;//error:1非左值 "(x?a:b)=1"表示当x为0时,b=1,否则a=1。这里的括号是必须的,否则将被看作x?a:(b=1)。"(x?x:a)=2”中,尽管x是左值,a也是左值,但x与a不同类型,条件运算符要对其进行操作数的隐式转换,使之成为相同的类型。任何被转换的变量都不是左值。 ->在C中,条件运算符是不能作左值的,所以"(x?a:b)=1;"将通不过编译。 getchar 函数名: getchar 功能: 从stdio流中读字符 用法: int getchar(void); 注解:

谭浩强C语言总结

谭浩强C语言总结Revised on November 25, 2020

《C语言程序设计》课程设计报告 第一部分《C语言程序设计》知识点梳理 (注《C语言程序设计》所涉及到的重要知识点及对这些知识点的理解) 一、程序设计 1、计算机语言 (1)机器语言 (2)汇编语言 为客服机器语言的缺点,用符号语言来表示指令(英文字母、数字)的符号语言为符号汇编语言(又称低级语言)。一条符号语言指令对应转换为一条机器指令;转换的过程称为“代真”或“汇编” (3)高级语言 客服低级语言的缺点,接近人们习惯用的自然语言和数学语言;用英语单词表示的指令及语句。功能性强,不依赖于具体机器,对任何型号计算机都适用(或做很少修改)。〔C语言、FORTRAN、QBASIC…〕 C语言特点①语言简洁、紧凑,使用方便、灵活②运算符丰富③数据类型丰富④具有结构化的控制语句⑤语法限制不太严格,程序设计自由度大⑥C语言允许直接访问物理地址,能进行位(bit)操作,能实现汇编语言的大部分功能,可以直接对硬件进行操作⑦用C语言编写的程序可移植性好⑧生成目标代码质量高,程序执行效率高 2、运行C程序的步骤及方法 ①上机输入和编辑源程序,以文件形式存档。 .c作为后缀,生成源程序文件

②对源程序进行编译。进行预处理,连接其它部分组成完整的、可进行正式编译的源程序(检查、转换) ③进行连接处理。把所有编译后得到的目标模块连接装配,与函数库想连接成一个整体,生成一个可供计算机执行的目标程序 ④运行可执行程序,得到运行结果。 二、算法 1、算法的概念 广义的说是解决一个问题所采用的方法和步骤(太极拳动作图解、乐谱)计算机算法分为两大类:1.数值运算算法(求数值解) 2.非数值运算算法(常用于事务管理领域) 2、算法的特性 ①有穷性:一个算法应包含有限的操作步骤 ②确定性:算法中的每一个步骤都应当是确定的,而不是含糊的、模棱两可的(算法的含义应当是唯一的,而不应当产生“歧义性”) ③有零个或多个输入:在执行算法时需要从外界取得必要的信息 ④有一个或多个输出: ⑤有效性:算法中的每一个步骤都应当有效的执行,并得到确定的结果 3、算法描述 (1)自然语言

后缀表达式求值的算法及代码

#include #include struct node // 栈结构声明 { int data; // 数据域 struct node *next; // 指针域 }; typedef struct node stacklist; // 链表类型 typedef stacklist *link; // 链表指针类型 link operand=NULL; // 操作数栈指针 link push(link stack,int value) // 进栈 { link newnode; // 新结点指针 newnode=new stacklist; // 分配新结点 if (!newnode) { printf("分配失败!"); return NULL; } newnode->data=value; // 创建结点的内容 newnode->next=stack; stack=newnode; // 新结点成为栈的开始return stack; } link pop(link stack,int *value) // 出栈 { link top; // 指向栈顶 if (stack !=NULL) { top=stack; // 指向栈顶 stack=stack->next; // 移动栈顶指针 *value=top->data; // 取数据 delete top; // 吸收结点 return stack; // 返回栈顶指针} else *value=-1; } int empty(link stack) // 判栈空 { if (stack!=NULL)

(完整word版)C语言运算符与表达式的练习题答案

C语言运算符与表达式的练习题 单项选择题 (1)以下选项中,正确的 C 语言整型常量是(D)。 A. 32L B. 510000 C. -1.00 D. 567 (2)以下选项中,(D)是不正确的 C 语言字符型常量。 A. 'a' B. '\x41' C. '\101' D. "a" (3)字符串的结束标志是(C)。 A. 0 B. '0' C. '\0' D. "0" (4)算术运算符、赋值运算符和关系运算符的运算优先级按从高到低依次为(B)。 A. 算术运算、赋值运算、关系运算 B. 算术运算、关系运算、赋值运算 C. 关系运算、赋值运算、算术运算 D. 关系运算、算术运算、赋值运算 (5)逻辑运算符中,运算优先级按从高到低依次为(D)。 A. && ! || B. || && ! C. && || ! D. ! && || (6)表达式!x||a==b 等效于(D)。 A. !((x||a)==b) B. !(x||y)==b C. !(x||(a==b)) D. (!x)||(a==b) (7)设整型变量 m,n,a,b,c,d 均为1,执行 (m=a>b)&&(n=c>d)后, m,n 的值是(A)。 A. 0,0 B. 0,1 C. 1,0 D. 1,1 *(8)设有语句 int a=3;,则执行了语句 a+=a-=a*=a; 后,变量 a 的值是(B)。 A. 3 B. 0 C. 9 D. -12 (9)在以下一组运算符中,优先级最低的运算符是(D)。 A. * B. != C. + D. = (10)设整型变量 i 值为2,表达式(++i)+(++i)+(++i)的结果是(B,上机13)。 A. 6 B. 12 C. 15 D. 表达式出错 (11)若已定义 x 和 y为double 类型,则表达式的值是(D)。

后缀表达式转化为前缀表达式并求值

#include #include #include #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 #define OK 1 #define OVERFLOW -2 #define ERROR 0 #define TRUE 1 #define FALSE 0 typedef int Selemtype; typedef int Status; #define MAX 50 char string1[MAX]; //定义两个字符串分别存放中缀表达式和后缀表达式char string2[MAX]; int result; typedef struct { Selemtype *base; //在构造之前和销毁之后,base的值为NULL Selemtype *top; //栈顶指针 int stacksize; //当前分配的存储空间,以元素为单位 }SqStack; Status InitStack(SqStack *S); Status Push(SqStack *S,Selemtype e); Status Pop(SqStack *S,Selemtype e); Status InitStack(SqStack *S) { //构造一个空栈S S->base=(Selemtype*)malloc(STACK_INIT_SIZE*sizeof(Selemtype)); if(!S->base) return OVERFLOW; //存储分配失败 S->top=S->base; S->stacksize=STACK_INIT_SIZE; return OK; } Status Push(SqStack *S,Selemtype e) { //插入元素e为新的栈顶元素 if(S->top-S->base>=S->stacksize)

C语言运算符与表达式的练习题

C语言运算符与表达式的练习题 (作业写到纸质作业本上,在规定时间内交给助教批阅,不要 再网上提交) 一、单项选择题 (1) 以下选项中,正确的C 语言整型常量是。 A. 32L B. 510000 C. -1.00 D. 567 (2) 以下选项中,是不正确的C 语言字符型常量。 A. 'a' B. '\x41' C. '\101' D. "a" (3) 在C 语言中,字符型数据在计算机内存中,以字符 的形式存储。 A. 原码 B. 反码 C. ASCII 码 D. BCD码 (4) 字符串的结束标志是。 A. 0 B. '0' C. '\0' D. "0" (5) 算术运算符、赋值运算符和关系运算符的运算优先级按 从高到低依次为。 A. 算术运算、赋值运算、关系运算 B. 算术运算、关系运 算、赋值运算

C. 关系运算、赋值运算、算术运算 D. 关系运算、算术运算、赋值运算 (6) 逻辑运算符中,运算优先级按从高到低依次为。 A. &&,!,|| B. ||,&&,! C. &&,||,! D. !,&&,|| (7) 表达式!x||a==b 等效于。 A. !((x||a)==b) B. !(x||y)==b C. !(x||(a==b)) D. (!x)||(a==b) (8) 设整型变量m,n,a,b,c,d 均为1,执行(m=a>b)&&(n=c>d)后, m,n 的值是。 A. 0,0 B. 0,1 C. 1,0 D. 1,1 (9) int b=0,x=1;执行语句if(x++) b=x+1; 后,x,b 的值依次为。 A. 2,3 B. 2,0 C. 3,0 D. 3,2 (10) 设有语句int a=3;,则执行了语句a+=a-=a*=a; 后,变量 a 的值是。 A. 3 B. 0 C. 9 D. -12 (11) 在以下一组运算符中,优先级最低的运算符是。 A. * B. != C. + D. =

数据结构计算器(包括中缀转换后缀)课程设计报告

课程设计报告 题目:计算表达式的值 1.问题描述 对于给定的一个表达式,表达式中可以包括常数、算术运行符(“+”、“-”、“*”、“/”)和括号,编写程序计算表达式的值。 基本要求:从键盘输入一个正确的中缀表达式,将中缀表达式转换为对应的后缀表达式,并计算后缀表达式的值。对于表达式中的简单错误,能够给出提示,并给出错误信息;表达式中可以包括单个字母表示的变量。 测试数据:任意选取一个符合题目要求的表达式。 提高要求:(1)能够处理多种操作符。 (2)实现包含简单运算的计算器。 (3)实现一个包含简单运算和函数运算的计算器。 2.需求分析 (1)软件的基本功能 本软件实在win32工程下实现的带有界面和图标的功能较为齐全的计算器。 此计算器分三个方面进行计算,分别为数值表达式的计算,字母表达式的计算和函数计算。可由键盘或用鼠标点击按键输入带有数字或字母的中缀表达式,程序可以将输入的带有数字或字母的中缀表达式转换成对应的后缀表达式,并计算只含有数字的后缀表达式的值。本软件支持含小数、多位数等多种操作数的处理,可以计算含加、减、乘、除、百分号、求余、求幂,求阶乘,求三角函数的值等多种运算符和函数的表达式 (2)输入/输出形式 用户可通过打开图标弹出来的计算器界面任意点击操作。对于在输入时发生的简单错误,软件通过弹出对话框给出提示并且在提示错误的同时自动将用户的出错输入略去转化成正确的表达式进行计算,用户也可选择清楚操作然后重新输入a.对于数值和函数表达式软件会输出其表达式的后缀表达式和计算结果并保留六位小数; b.对于字母表达式因字母无法进行数值运算,软件仅输出其后缀表达式的值;清楚按钮可以清楚有已经输入或输出的数据从头计算; 软件窗口可实现最小化。并且输入编辑框可进行修改,复制,粘贴等操作,但后缀表达式和求值结果的编辑框中的内容不可修改,只能执行复制操作。

后缀表达式的计算

#include #include #include #include using namespace std; int priority(char op) //运算符的优先级 { switch(op) { case '(': return 0; break; case '+': case '-': return 1; break; case '*': case '/': return 2; break; default: return -1; break; } } bool IsOperator(char op) //是否为运算符 { if (op == '+' || op == '-' || op == '*' || op == '/') { return true; } return false; } void inTOpost(char s[],vector &v) //转为后缀表达式{ stack stk; int i = 0,len = strlen(s); while(i < len) { if(s[i] >= '0' && s[i] <= '9') {

v.push_back(s[i]); v.push_back(' '); } else if (s[i] == '(') { stk.push(s[i]); } else if (s[i] == ')') { while(stk.top() != '(') { v.push_back(stk.top()); v.push_back(' '); stk.pop(); } stk.pop(); } else if (IsOperator(s[i])) { if (!stk.empty()) { while(!stk.empty() && priority(s[i]) <= priority(stk.top())) { v.push_back(stk.top()); v.push_back(' '); stk.pop(); } } stk.push(s[i]); } i++; } while(!stk.empty()) { v.push_back(stk.top()); v.push_back(' '); stk.pop(); } } bool compute(vector s,int &res) //计算后缀表达式的值 { int i = 0,num; int len = s.size();

逻辑运算符和表达式(c语言)

南京高等职业技术学校 课堂教学设计 授课时间:2014年11月6日第11周星期四教学目标教学准备 授课教师课时课程通过本节课的学习,学生能够: 1.清晰地说出各种逻辑运算符; 2.正确运算出逻辑表达式的值,并 通过程序验证结果; 重点教案□√ 马丽娟 1 C语言多媒体课件□√班级授课地点课题教学讲义□ 512212 机房4.2逻辑运算符与逻辑表达 式 1.逻辑表达式的求值运算; 2.逻辑表达式的求值优化。 学生工作页□ 课堂特殊要求(指教师、学生的课前准备活动等) 教师:安装Win-TC程序难点 教具□√ 逻辑表达式的求值优化授课形式 理论讲授课 教学环节时间分配教师活动学生活动教学方法媒体手段导入新课 5 提出问题,并举例说明听讲、思考、回答讲授法PPT 新课讲授20 讲授、分析听讲、讨论并记录讲授法PPT 巩固练习15 布置任务、巡视、答疑思考、编程并回答问题练习法Win-TC 课堂小结 3 归纳、总结听讲、回答问题讲授法PPT 布置作业 2 布置作业记录讲授法PPT 板书设计 §4.2 逻辑运算符与逻辑表达式 ?逻辑运算符:&&、||、! ?逻辑表达式的值:非0即1 ?逻辑运算的求值优化工作任务/教学情境设置 无课后作业 书面作业:P52 随堂练习 课后反思

教案纸 教学内容 4.2 逻辑运算符与逻辑表达式 一、复习导入(5min) 1. 复习:请学生说出关系运算符有哪些? 请学生回答关系运算表达式的值? 教师进行补充。 2.导入新课: 1、学生参加技能大赛培训的条件? ?扎实的专业知识与较高的实践能力 教师强调与的关系 2、参加技能大赛集训而停课的条件? ?移动互联或智能家居 教师强调或的关系 3、学生回答引入禁烟区的条件? ?没有吸烟非 教师强调非的关系 二、新课讲授(20min) 逻辑运算符 1.教师根据逻辑关系给出三种逻辑运算符的表示形式: &&、||、! 2.教师利用具体的表达式关系分析各种逻辑运算符的作用: 逻辑与相当于英语中的and; 逻辑或相当于英语中的or; 逻辑非相当于英语中的no; 3.教师根据具体的逻辑关系引出逻辑表达式的概念及表示形式: 表达式1&&表达式2 a&&b 表达式1||表达式2 a || b !表达式!a

c语言实现中缀,后缀,前缀表达式转换并求值

c语言实现中缀,后缀,前缀表达式转 换并求值 c语言实现中缀,后缀,前缀表达式转换并求值九#include #include #define MAXNUM 100 typedef struct Node//定义存储中缀表达式的结点类型{int data; int data1; char data2; struct Node *next; }Lnode; typedef struct Node2//定义存储前缀表达式的结点类型{int data; int data1; char data2; struct Node2 *next; struct Node2 *prior; }Lnode2; typedef int selemtype1;//定义运算数栈的结点typedef struct//定义运算数栈的类型{selemtype1 *base; selemtype1 *top; }sqstack1; void InitStack1(sqstack1 &s)//新建一个空运算数栈{=(selemtype1 *)malloc(MAXNUM*sizeof(selemtype1));

=; if(!) printf(“出错:申请空间失败!\\n”); } void Push1(sqstack1 &s,selemtype1 &e)//运算数栈,入栈:插入元素e为新的栈顶元素{ if(>=MAXNUM) printf(“出错:表达式过长!1\\n”); *++ =e; } void GetTop1(sqstack1 s,selemtype1 &e)//运算数栈,用e返回栈顶元素{e=*(); } void Popopnd1(sqstack1 &s,selemtype1 &e) //运算数栈,退栈:删除栈顶元素,并用e返回其值{e=*--; } int stackempy1(sqstack1 s) //运算数栈,若为空栈返回1,否则返回0 {if(==) return 1; else return 0; } typedef char selemtype2;//定义运算符栈的结点类型typedef struct//定义运算符栈类型{selemtype2 *base; selemtype2 *top; }sqstack2; void InitStack2(sqstack2 &s)//新建一个空运算符栈{=(selemtype2 *)malloc(MAXNUM*sizeof(selemtype2)); =; if(!) printf(“出错:申请空间失败!

数学表达式解析(前缀中缀后缀)

它们都是对表达式的记法,因此也被称为前缀记法、中缀记法和后缀记法。它们之间的区别在于运算符相对与操作数的位置不同:前缀表达式的运算符位于与其相关的操作数之前;中缀和后缀同理。 举例: (3 + 4) × 5 - 6 就是中缀表达式 - × + 3 4 5 6 前缀表达式 3 4 + 5 × 6 - 后缀表达式 中缀表达式(中缀记法) 中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。 虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单。 前缀表达式(前缀记法、波兰式) 前缀表达式的运算符位于操作数之前。 前缀表达式的计算机求值: 从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素op 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。 例如前缀表达式“- × + 3 4 5 6”: (1) 从右至左扫描,将6、5、4、3压入堆栈; (2) 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做比较),计算出3+4的值,得7,再将7入栈; (3) 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈; (4) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。 可以看出,用计算机计算前缀表达式的值是很容易的。 将中缀表达式转换为前缀表达式: 遵循以下步骤: (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2; (2) 从右至左扫描中缀表达式; (3) 遇到操作数时,将其压入S2; (4) 遇到运算符时,比较其与S1栈顶运算符的优先级: (4-1) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈; (4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1; (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较; (5) 遇到括号时:

中缀表达式转后缀表达式并计算结果(C语言版)

中缀表达式转后缀表达式 中缀表达式转后缀表达式的规则。 1.遇到操作数:直接输入到后缀表达式栈 2.遇到运算符,直接入操作符栈 3.遇到左括号:直接将其入栈 4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。 5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈 6.最终将操作符栈中的元素依次出栈,输出到后缀表达式栈。 以下是自己写的代码。亲测没有问题。(模拟一个计算器,可以带括号,中间可以空格,只支持整数输入,但是输出结果精确到小数后6位) #include "stdio.h" #define MAX_LEN 100 typedef struct cal{ unsigned char isOper;//是否是操作数1,操作符0.操作数 double Num; //值。或者是操作符的ASCII值 }STRUCT_CAL; #define IS_NUM 0x00 #define IS_OPER 0x01 STRUCT_CAL stackCal[MAX_LEN]; STRUCT_CAL stackCalBack[MAX_LEN]; unsigned char topCal; char stackOper[MAX_LEN]; unsigned char topOper; /***************************************************************** * 堆栈初始化 *****************************************************************/ void stackInit(void)

四则混合运算和后缀表达式

/// 四则混合运算。 波兰表达式。 逆波兰表达式(后缀表达式)生成算法: (1)构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。 (2)读入一个用中缀表示法表示的简单算术表达式,为方便起见,认为地在字符串后面加入一个特殊字符“;”,并设其优先级为0。 (3)从左至右扫描该算术表达式的每一个字符,如果该字符是数字,则分析到该数字串的结束并将该数字串加入结果字符串,小数点亦算入数字串。 (4)如果该字符是运算符,则按如下操作:优先级高的放在前面,通过出入栈操作。 如果该字符是左括号“(”,则该字符直接压入运算符栈。 如果该字符是右括号“)”,则把运算符栈顶元素弹出直至第一次遇到左括号。如果该字符是算术运算符且其优先关系高于运算符栈顶的运算符,则将该运算符入栈。 否则,将栈顶的运算符从栈中弹出至结果字符串末尾,直至栈顶运算符的优先级低于当前运算符,并将该字符入栈。 (5)重复上述操作(3)-(4)直至扫描完整个简单算术表达式(遇到特殊字符“;”)。 如: 一般简单表达式:((4+5)*6-5)/2+3*2 逆波兰表达式:4 5 + 6 * 5 - 2 / 3 2 * + 步骤如下: 运算符栈结果字符串 第1步:; "" 第2步:;( "" 第3步:;(( "" 第4步:;(( "4" 第5步:;((+ "4 5" 第6步:;( "4 5 +" 第7步:;(* "4 5 +" 第8步:;(* "4 5 + 6" 第9步:;(- "4 5 + 6 *" 第10步:;(- "4 5 + 6 * 5" 第11步:; "4 5 + 6 * 5 -"

第12步:;/ "4 5 + 6 * 5 -" 第13步:;/ "4 5 + 6 * 5 - 2" 第14步:;+ "4 5 + 6 * 5 - 2 /" 第15步:;+ "4 5 + 6 * 5 - 2 / 3" 第16步:;+* "4 5 + 6 * 5 - 2 / 3" 第17步:;+* "4 5 + 6 * 5 - 2 / 3 2" 第18步:;+ "4 5 + 6 * 5 - 2 / 3 2 *" 第19步:; "4 5 + 6 * 5 - 2 / 3 2 * +" 其中运算符优先级如下: * / :2 + - :1 ;:0 逆波兰表达式求值算法: (1)构建一个操作数栈,类型为float; (2)依次扫描逆波兰表达式的每一项; (3)如果是数字串则压入操作数栈; (4)如果是运算符,则从操作数栈顶弹出两个操作数,与运算符进行运算,结果压入操作数栈。 (5)不断重复以上步骤直至扫描完逆波兰表达式。 (6)此时操作数栈必定只剩一个数据,即为逆波兰表达式的值,弹出输出。如:如上表达式计算结果为:30.5.

c语言实现一.二叉树操作 二.用栈实现算术表达式求值 课设报告

目录 题目一.二叉树操作(1)二.算术表达式求 (1) 一、课程设计的目的 (1) 二、课程设计的内容和要求 (1) 三、题目一设计过程 (2) 四、题目二设计过程 (6) 五、设计总结 (17) 六、参考文献 (18)

题目一.二叉树操作(1)二.算术表达式求 一、课程设计的目的 本学期我们对《数据结构》这门课程进行了学习。这门课程是一门实践性非常强的课程,为了让大家更好地理解与运用所学知识,提高动手能力,我们进行了此次课程设计实习。这次课程设计不但要求学生掌握《数据结构》中的各方面知识,还要求学生具备一定的C语言基础和编程能力。 (1)题目一的目的: 1、掌握二叉树的概念和性质 2、掌握二叉树的存储结构 3、掌握二叉树的基本操作 (2)题目二的目的: 1、掌握栈的顺序存储结构和链式存储结构 2、掌握栈的先进后出的特点 3、掌握栈的基本运算 二、课程设计的内容和要求 (1)题目一的内容和要求: 1、编写已知二叉树的先序、中序序列,恢复此二叉树的程序 2、编写求二叉树深度的程序 (2)题目二的内容和要求: 1、算术表达式由操作数、运算符和界限符组成。操作数是正整数,运算符为 加减乘除,界限符有左右括号和表达式起始 2、将一个表达式的中缀形式转化为相应的后缀形式 3、依据后缀表达式计算表达式的值

三、题目一设计过程 1、题目分析 现已知一棵二叉树的先序遍历序列和中序遍历序列,依次从先序遍历序列中取结点,由先序序列确定根结点(就是第一个字母),每次取出一个结点就与中序遍历的序列进行比较,当相等的时候,中序遍历序列就被分成以该结点为根的二叉树子树,该结点左部分为左子树,右部分为右子树,直到取完先序列里的所有结点,则二叉树构造完毕(树用链式存储结构存储),用递归实现! 由建好的二叉树,先判断这棵树是否为空,若不为空则找数的左子树,统计它的高度,然后找树的右子树,统计它的高度,比较左子树和右子树的高度,然后返回其中大的那个值加一,则求出数的高度。这里用递归实现! 2、算法描述 main ( )(主函数) 先构造一颗二叉树,初始化为空,用来存储所构造的二叉树,并输入一棵树的先序序列和中序序列,并统计这个序列的长度。然后调用实现功能的函数。 void CreateBiTree(BiTree *T,char *pre,char *in,int len)(由先序序列和中序序列构造二叉树) 根据前序遍历的特点, 知前序序列(pre)的首个元素(pre[0])为根(root), 然后在中序序列(in)中查找此根(pre[0]), 根据中序遍历特点, 知在查找到的根(root) 前边的序列为左子树, 后边的序列为右子树。设根前边有n个元素,则又有, 在前序序列中,紧跟着根(root)的n个元素序列(即pre[1...n]) 为左子树, 在后边的为右子树,而构造左子树问题其实跟构造整个二叉树问题一样,只是此时前序序列为pre[1...n]), 中序序列为in[0...n-1], 分别为原序列的子串, 构造右子树同样。这里用递归实现! int Depth(BiTree T)(求树的深度) 当所给的参数T是NULL时,返回0。说明这个树只有一个叶子节点深度为0,当所给的参数不是NULL时,函数调用自己看看这个参数的左分支是不是NULL,

将中缀表达式转换为后缀表达式并计算

《数据结构》实验报告 ◎实验题目:使用键盘输入表达式,计算表达式的值并输出;将表达式转化成后缀表达式输出,利用后缀表达式求表达式的值并输出。 ◎实验目的:使用栈的操作编写关于数据结构的程序。 ◎实验内容:写出程序并上机调试、通过。 一、需求分析 1、演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“请输入表达式”时输入中缀表达式。然后计算机终端输出转换后的后缀表达式及计算后的结果。 2、程序执行的命令包括: (1)构造链栈;(2)输入数据;(3)判断输入的表达式是否为非法表达式;(4)将中缀表达式转换为后缀表达式;(5)计算表达式的值;(6)输出。(7)结束 4、本程序能将中缀表达式转换为后缀表达式,并且能计算表达式的值。 5、输入及输出示例: 例1: 请输入表达式 6+3*(6+5) 后缀表达式:6 3 6 5 + * + 计算结果为:39 Press any key to continue 例2: 请输入表达式 6-3*(7+1 ERROR:表达式错误 Press any key to continue 二概要设计 1.基本操作 (1)、struct node 操作结果:创建结构体 (2)、int Searchexpression(char string1[]) 初始条件:表达式string1已经存在。 操作结果:判断表达式是否非法 (3)、struct node *Initialization() 操作结果:创建栈链。 (4)、struct node *assort(struct node *s) 初始条件:string1、string2已存在。

操作结果:将中缀表达式转换为后缀表达式并存在string2中。 (5)、struct node *calcolate(struct node *s) 操作结果:求出表达式的值 2、模块调用图 三详细设计 1、每个模块: (1) 定义结构体 struct node { char data; int num; struct node *next; }; (2) 判断表达式是否非法 int Searchexpression(char string1[]) { int i1,b1,b2; int m; m=strlen(string1); if(string1[0]<'0'||string1[0]>'9') { printf("ERROR:表达式缺操作数!\n");return(WRONG); } for(i1=0;i1<=m;i1++) { if(string1[i1]=='(') b1++; else if(string1[i1]==')') b2++; } if(b1!=b2) {printf("ERROR:缺少括号\n");return(WRONG);} for(i1=0;i1

相关文档
最新文档