后缀表达式转换为中缀表达式问题

ruan_ji 2015-10-23 11:22:02
初学数据结构,目前遇到一个后缀表达式转换为中缀表达式的问题,
以下是代码,注释部分包括了问题本身和我的求解思路,现在遇到的问题是对于求解简单的几个十几个字符的表达式没问题,稍微多些就提示堆损坏、写入冲突某些位置访问冲突……麻烦哪位帮我调试下找找具体问题所在,感激不尽!我这里有测试样例比如y!!ix/mf+//ii-se**lp*ck+/*-wy-js/+ia*pm*-*!*gl+uh/*tk*ut-*+vm/kn+/ec-jn*+/*w!bq/*qn*on/-/gr+l!+wa/sw/-**/-ak-ch**bi/fr-++us*ll-+hv-r!//+t!vs*+gm/fo-**an*pv**fs-mj*//-*ha/li*-vo-ts/**cb-!uu-ok-**/ak+qt/-vl+fo*/-ju*no*+qu*jj-/--*-/ov+sm/+!mx/ij/-cb-nu*+/-ov-dk*/oe-i!*+yq-cc+/bx-ji-/+++un/ic/*fs*tn/*/ug/cl//y!kk*/-/rx/qq*/wg/!+nj-hp**mm*as-*-//+oo-d!/gg/ut+--fr+xf/-qy-ev+/*/!js-cv/-op*jw*//s!gt*/!*!***sf*mt-+cu*el*-*qc+wo+*ky-nf/++*lq*bh*+kr*sh/-/rn-sj+/pr/oc*--+*mt*v!/ab*vv**+as/pg+/ku-ov*/+/hl/nq/-ye*jh/*-dw/ty+*ua/op*/++//dm+xt-/o!b!*/ia*gr-+ig/xs*+**so/mu/+nt*gf*-/bs/la*/dn/pc//-+/cd+!jt+il*++sd*kt+-pu/xj-*/-cl/mg/*yk*ya//+cl*yh/+na*rx++-**+/jw+ed*/sf*ll/*/yf-!vt+px+tj**///fa+hi-*cj/!*ap/tj**pr*l!-**sx*sq/*qk-xg/-*iu+vq+/rd/sm+-*-*/cd+pr-+bo*rh-**ul*ny*-bf-ju**//oo/pe++ea-ng+-/dw*hh-+py/fa/*//*qq/gy-/fk/!*!!*/nb/xv+*bq-or-*/bb/xo+*my*ye-+/+hj+ib/*ju/tw***ng+sq+*lw+ik--+++vj*yi+*cx+ta/*/vr*ix+/dx-lx+--/b!te*-ou+oj**+wv-gs/-ts/pl/+-*++sw/oe+*ts*iu***!pl/td*/vn/gi-/*fc-av*/sd*gc**-//!***-

/*
程序功能:将后缀表达式转换为中缀表达式
程序要求:用户输入一个后缀表达式(字符串形式),表达式中只能含有英文小写
字母(表示操作数)和加减乘除以及阶乘符号,要求输出中操作数之间顺序不得交换,
也不能出现不必要的括号,但是为了保证运算顺序需添加必要的括号
程序思路:设定一个栈Stack,每个栈结点存储表达式、表达式操作符号,然后开始从用
户输入的字符串表达式中单个字符的读入,如果是操作数就入栈,如果是阶乘操作符就将之前
的栈顶元素出栈并加上阶乘符号(注意视情况决定栈顶元素是否加括号),如果是加减乘除操
作符则将之前的两个元素依次出栈,用倒数第二个元素作为被操作数,操作符连接在后面,再
在后面连接上第一个出栈的元素(这两个元素都要视优先级情况决定是否加括号)。为了解决
决定是否加括号问题,另外设了一个结构体指针Stack2,里面存储对应结点的表达式和操作符
只需要将倒数第一个和倒数第二个元素的操作符分别于读入的操作符比较即可确定是否加括号*/
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
typedef char* STRING;//自定义字符串类型
typedef struct Node//定义链式栈的节点
{
STRING expression;//存储结点字符串表达式,可以是单个字符(代表操作数)
char symbol;//存储结点操作符号
struct Node* next;
}StackNode,*Stack;
typedef struct Node2
{
STRING expression;
char symbol;
}Node2,*Stack2;
#define size1 (Stack)malloc(sizeof(StackNode))
#define size2 (STRING)malloc(sizeof(char))
#define size3 (Stack2)malloc(sizeof(Node2))
Stack head;//定义全局头指针,其数据域不存数据,next指针域指向栈顶
Stack2 top;//定义全局结构体指针,用于存储当前出栈的那个元素
Stack2 Pop(Stack head,Stack2 top);//将一个元素(即栈顶元素)出栈,返回结点
STRING s=NULL;
char* add="+";
char* sub="-";
char* time="*";
char* divided="/";
char* jiecheng="!";
char* leftbracket="(";
char* rightbracket=")";
void Push(Stack head,STRING str,char c);//将一个元素(字符串)入栈
void InitStack(Stack head);
int ComparePriority(char c1,char c2);//比较两种运算符的优先级的函数
STRING TransformCharIntoString(STRING s,char c);//将字符转换成字符串
int main()
{
STRING LeftBracket=NULL,RightBracket=NULL;
STRING string;//记录后缀表达式字符串
STRING string1,string2;//分别记录倒数第一个出栈和倒数第二个出栈元素的表达式字符串
STRING string3,string4;
unsigned int i;
char character;//分别是记录单个字符
char symbol1;//记录倒数第一个元素表达式即栈顶元素的符号
char symbol2;//记录倒数第二个元素的符号
head=size1;
top=NULL;
string=(STRING)malloc(sizeof(char));
string1=size2;
string2=size2;
string3=size2;
string4=size2;
InitStack(head);
scanf("%s",string);
for(i=0;i<strlen(string);i++)
{
character=string[i];//读入单个字符
if(character>='a'&&character<='z')//为操作数时入栈
{
//printf("\n本轮操作符转换成字符串后是%s\n",TransformCharIntoString(s,character));
Push(head,TransformCharIntoString(s,character),'\0');
}
else//为操作符时将之前的一个或者两个元素出栈
{
if(character=='!')//为阶乘符号时将栈顶元素退栈并加上阶乘符号再入栈
{
top=Pop(head,top);
string1=top->expression;
symbol1=top->symbol;//记录倒数第一个元素符号
if(ComparePriority(character,symbol1)==0||symbol1=='\0')//如果栈顶元素是操作数或者也为阶乘时无需加括号,
{
string3=string1;
}
else//栈顶元素符号为加减乘除时需要加括号
{
LeftBracket=size2;
RightBracket=size2;
string3=strcat(strcat(strcpy(LeftBracket,leftbracket),string1),strcpy(RightBracket,rightbracket));//把前后括号加入倒数第一个元素
}
string4=strcat(string3,jiecheng);
Push(head,string4,'!');
free(top);
}
else//不是阶乘符号时需要将之前的两个元素退栈并用操作符连接
{
//注意还需要单独考虑栈顶元素为操作数的情况
top=Pop(head,top);
string1=top->expression;//记录倒数第一个元素表达式
symbol1=top->symbol;//记录倒数第一个元素符号
top=Pop(head,top);
string2=top->expression;//记录倒数第二个元素表达式
symbol2=top->symbol;//记录倒数第二个元素符号
free(top);
if(symbol1=='\0')//如果栈顶元素为操作数则都无需加括号
{
if(character=='+')
Push(head,strcat(strcat(string2,add),string1),character);
else if(character=='-')
Push(head,strcat(strcat(string2,sub),string1),character);
else if(character=='*')
Push(head,strcat(strcat(string2,time),string1),character);
else
Push(head,strcat(strcat(string2,divided),string1),character);
}
else if(symbol2=='\0')//倒数第二个元素为操作数,此时string2不加括号
{
if(ComparePriority(character,symbol1)>=0)//此时character为乘除,symbol1为加减,或者两者优先级相同,栈顶元素要加括号
{
LeftBracket=size2;
RightBracket=size2;
string3=strcat(strcat(strcpy(LeftBracket,leftbracket),string1),strcpy(RightBracket,rightbracket));//把前后括号加入倒数第一个元素
}
else//此时栈顶元素无需加括号
{
string3=string1;
}
if(character=='+')
Push(head,strcat(strcat(string2,add),string3),character);
else if(character=='-')
Push(head,strcat(strcat(string2,sub),string3),character);
else if(character=='*')
Push(head,strcat(strcat(string2,time),string3),character);
else
Push(head,strcat(strcat(string2,divided),string3),character);
}
else//倒数第一个元素和倒数第二个元素都不是操作数
{
//printf("\n读入的不是阶乘且两个元素都不是操作数");
if(ComparePriority(character,symbol1)>0)//栈顶元素必须加括号,此时character必然是乘除
{
//printf("\n栈顶元素小于读入的元素\n");
LeftBracket=size2;
RightBracket=size2;
string3=strcat(strcat(strcpy(LeftBracket,leftbracket),string1),strcpy(RightBracket,rightbracket));//把前后括号加入倒数第一个元素
//printf("栈顶元素加括号后是%s",string3);
if(ComparePriority(character,symbol2)>0)//此时倒数第二个元素也必须加括号
{
LeftBracket=size2;
RightBracket=size2;
string4=strcat(strcat(strcpy(LeftBracket,leftbracket),string2),strcpy(RightBracket,rightbracket));//把前后括号加入倒数第二个元素
}
else//此时倒数第二个元素符号为乘除或者阶乘
{
string4=string2;//倒数第二个元素不加括号
//printf("倒数第二个元素是%s\n",string4);
}
if(character=='*')
Push(head,strcat(strcat(string4,time),string3),character);
else
Push(head,strcat(strcat(string4,divided),string3),character);

}
else if(ComparePriority(character,symbol1)<0)//当读入的操作符优先级低于栈顶元素运算符时,栈顶元素当然不用加括号
{
if(ComparePriority(character,symbol2)<=0)//此时倒数第二个元素也不用加括号
{
string4=string2;
}
else//此时倒数第二个元素必须加括号
{
LeftBracket=size2;
RightBracket=size2;
string4=strcat(strcat(strcpy(LeftBracket,leftbracket),string2),strcpy(RightBracket,rightbracket));//把前后括号加入倒数第二个元素
//printf("把前后括号加入倒数第二个元素后是%s",string4);

}
if(character=='+')
Push(head,strcat(strcat(string4,add),string1),character);
else if(character=='-')
Push(head,strcat(strcat(string4,sub),string1),character);
else if(character=='*')
Push(head,strcat(strcat(string4,time),string1),character);
else
Push(head,strcat(strcat(string4,divided),string1),character);
//printf("合并后入栈后是%s",head->next->expression);//以样例“y!!ix/mf+//ii-se**lp*ck+/*-wy-js/+ia*pm*-*!*”调试未能执行到这一步
}
else//当读入的操作符优先级等于栈顶元素优先级时,分析可知栈顶元素需要加括号
{
LeftBracket=size2;
RightBracket=size2;
string3=strcat(strcat(strcpy(LeftBracket,leftbracket),string1),strcpy(RightBracket,rightbracket));//把前后括号加入倒数第一个元素
if(ComparePriority(character,symbol2)<=0)//此时倒数第二个元素无需加括号
{
string4=string2;
}
else//此时character为乘除,symbol2为加减,此时倒数第二个元素要加括号
{
LeftBracket=size2;
RightBracket=size2;
string4=strcat(strcat(strcpy(LeftBracket,leftbracket),string2),strcpy(RightBracket,rightbracket));//把前后括号加入倒数第二个元素
}
if(character=='+')
Push(head,strcat(strcat(string4,add),string3),character);
else if(character=='-')
Push(head,strcat(strcat(string4,sub),string3),character);
else if(character=='*')
Push(head,strcat(strcat(string4,time),string3),character);
else
Push(head,strcat(strcat(string4,divided),string3),character);
}
}

}
}
//printf("第%d轮循环后栈顶元素是%s,栈顶符号是%c\n",i+1,head->next->expression,head->next->symbol);
}
//printf("\n最后结果为%s\n",head->next->expression);
printf("%s",head->next->expression);
return 0;
}
void InitStack(Stack head)
{
head=size1;
head->expression=NULL;
head->next=NULL;
head->symbol='\0';
}
Stack2 Pop(Stack head,Stack2 top)//将一个元素(即栈顶元素)出栈并返回该栈顶元素,注意要返回整个结点
{
top=size3;
if(top==NULL)
{
printf("本次用以记录栈顶元素的top指针内存分配失败!");
system("pause");
}
top->expression=head->next->expression;//记录栈顶元素值
top->symbol=head->next->symbol;
head->next=head->next->next;//将下一个结点作为新的头结点
return top;
}
void Push(Stack head,STRING str,char c)//将一个元素(表达式或者仅有操作数)入栈
{

StackNode* p;
p=(StackNode*)malloc(sizeof(StackNode));
if(p==NULL)
{
printf("本次入栈时内存分配失败!");
system("pause");
}
p->expression=str;
p->symbol=c;
p->next=head->next;
head->next=p;
}
int ComparePriority(char c1,char c2)
{
if(c1==c2)
return 0;
else
{
if(c1=='+'||c1=='-')
{
if(c2=='-'||c2=='+')
return 0;
else
return -1;
}
if(c1=='*'||c1=='/')
{
if(c2=='/'||c2=='*')
return 0;
else if(c2=='+'||c2=='-')
return 1;
else
return -1;
}
if(c1=='!')
return 1;

}
}
STRING TransformCharIntoString(STRING s,char c)//将字符转换成字符串
{
//STRING s;
s=(STRING)malloc(2*sizeof(char));
if(s==NULL)
{
printf("本次转换成字符串时内存分配失败!");
system("pause");
}
s[0]=c;s[1]='\0';
return s;
}
...全文
317 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
ruan_ji 2015-10-24
  • 打赏
  • 举报
回复
第一次用csdn,还完全不熟悉规则多包涵
liganglester 2015-10-24
  • 打赏
  • 举报
回复
楼主,为了提高别人回答你的可能性,我觉得你可以 用CSDN发帖的代码格式,代码部分的显示格式会更清晰易懂

70,024

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧