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

C语言实现括号匹配,中缀表达式转后缀表达式并计算具体代码实现

2017-11-17 10:31 956 查看
1.在本项目拟采用顺序栈来实现。

顺序栈的存储定义

typedef struct stack
{
SElemType  *base;//栈底指针
SElemType  *top;//栈顶指针
int  stacksize;//栈分配的存储空间大小
}SqStack;
2.主要功能函数设计及算法描述

(1)初始化栈

算法描述:初始化空栈,包括顺序栈存储单元的分配等。

void InitStack(SqStack  s)
{
s.base=s.top=( SElemType *)malloc(MAXSIZE*sizeof(SElemType));
if(s.base==NULL) exit(-2);
s.stacksize=MAXSIZE;
}


(2)出栈

算法描述:如果栈不空,则将栈顶的元素出栈。

Status Pop(SqStack s,SElemType e)
{if(s.top==s.base) return ERROR;
s.top--;
e=*s.top;
return OK;
}


(3)入栈

算法描述:如果栈没满,则添加新元素进栈,作为新的栈顶元素。

Status Push(SqStack s,SElemType e)
{if(s.top-s.base==s.stacksize) return ERROR;
*s.top=e;
s.top++;
return ok;
}


(4)取栈顶元素

算法描述:当栈非空时,对栈进行访问,返回此时栈顶元素的值,不改变栈中元素。

SElemType GetTop(SqStack s)
{if(s.top!=s.base)
return *(s.top-1);
}


(5)括号匹配算法

算法描述:检查字符串中的括号是否匹配,可以借助栈实现。自左至右扫描字符串,当遇到左括号时,执行入栈操作。当遇到右括号时,与栈顶符号进行匹配,若匹配成功,则执行一次出栈,否则,直接断定匹配失败。如果字符串访问结束时,栈空,则说明匹配成功,否则匹配失败。

int Match(SqStack s ,char *p)
{//检查表达式中小括号是否匹配
flag=0;
while(*p!='\0')
{
if(*p== '(' )
{  if(s.top-s.base ==s.stacksize) exit(-1);
else Push(s,*p);//将所有的左括号入栈
}
if(*p== ')' )
{ if(s.top!=s.base&&GetTop(s)=='(') {
Pop(s);
flag=1; }
else flag=2;}
p++;
}//while
if((flag==1||flag==0)&&s.top==s.base)
return 1;
else if(flag==2)  return 0;}
}//Match


(6)转换后缀表达式算法

算法描述:将中缀表达式转换为后缀表达式。详细的描述请参照我之前一篇算法描述的文章。

void trans(SElemType str[],SElemType rpn[])
{
i=0,t=0;
ch=str[i++];
while(ch!='\0')
{ switch(ch)
{ case '(': Push(op,ch); break;
case ')': while(GetTop(op)!='(' )
{ rpn[t]= GetTop(op);
Pop(op);
t++;
}
op.top--;//此处必须再次进行--运算,才能忽略已经进入的‘(’
break;
case '+':
case '-':
while(op.top!=op.base && GetTop(op)!='(' )
{rpn[t]= GetTop(op);
Pop(op);
t++;
}
Push(op.ch);
break;
case '*':
case '/':
while(GetTop(op)'*'|| GetTop(op)=='/')
{rpn[t]= GetTop(op);
Pop(op);
t++;
}
Push(op.ch);
break;
case ' ':break;
default:
while(ch>='0'&&ch<='9')
{rpn[t]=ch;
t++;
ch=str[i];
i++;
}
i--;
rpn[t]='#';t++;
}//switch
ch=str[i];
i++;
}//while
while(op.top!=op.base)
{rpn[t]= GetTop(op);
t++;
Pop(op);
}//while
rpn[t]='\0';
}//trans


(7)后缀表达式的计算

算法描述:对转换得到的后缀表达式进行计算。详细描述请参照我之前一篇算法描述的文章。

int value(char rpn[])
{
t=0, ch=rpn[t], t++;
while(ch!='\0')
{
switch(ch)
{case '+': m=Pop(st);n=Pop(st);
Push(st,n+m);
break;
case '-': m=Pop(st);n=Pop(st);
Push(st,n-m);
break;
case '*': m=Pop(st);n=Pop(st);
Push(st,n*m);
break;
case '/': if(GetTop(st)!=0)
{m=Pop(st);n=Pop(st);
Push(st,n/m); break;}
else
{printf("\n除0错误!\n");
exit(0);
}
default: d=0;
while(ch>='0'&&ch<='9')
{d=10*d+ch-'0';
ch=rpn[t];
t++;
}
Push(st,d);
}//switch
ch=rpn[t]; t++;
}//while
return GetTop(st);
}//value


具体项目实现

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define MAXSIZE 100
//此程序中存储单元采用malloc( )函数分配,但没有涉及处理溢出的问题,相关涉及可以参//照realloc( )的使用方法
//顺序栈的存储定义
typedef struct stack
{
char *base;//栈底指针
char *top;//栈顶指针
int stacksize;//栈分配的存储空间大小
}SqStack;

SqStack op,st;//顺序栈op用来存储运算符,st用来存放数值

void Menu();
void InitStack();
void trans(char str[],char rpn[]);
int value(char rpn[]);
int Match(char *p);
//*****************************************************************************
void Menu()
{//界面函数
printf("*********表达式求值(只能包含+、-、*、/、()和正整数)********* ******\n");
printf("请选择:1.输入表达式 2.括号匹配检查 3.转换后缀表达式 4.表达式计算5.退出\n");
}
//*****************************************************************************
void InitStack()
{//初始化栈op、st
op.base=op.top=(char *)malloc(MAXSIZE*sizeof(char));
if(op.base==NULL) exit(-2);
st.base=st.top=(char *)malloc(MAXSIZE*sizeof(char));
if(st.base==NULL) exit(-2);
op.stacksize=op.stacksize=MAXSIZE;
}
//*****************************************************************************
int Match(char *p)
{//检查表达式中小括号是否匹配
int flag=0;
SqStack s;

s.base=s.top=(char*)malloc(MAXSIZE*sizeof(char));
if(!s.base) exit(-2);
s.stacksize=MAXSIZE;
while(*p!='\0')
{
if(*p== '(')
{  if(s.top-s.base ==s.stacksize) exit(-1);
else {*s.top=*p;
s.top++;//将所有的左括号入栈
}
}
if(*p== ')')
{ if(s.top!=s.base&&*(s.top-1)=='(') {
s.top--;
flag=1; }
else flag=2;}
p++;
}//while
if((flag==1||flag==0)&&s.top==s.base)
{s.top=s.base;//将栈清空
return 1;}
else if(flag==2) {s.top=s.base;//将栈清空
return 0;}
}//Match
//*****************************************************************************
void trans(char str[],char rpn[])
{//将中缀表达式转换为后缀表达式
char ch;
int i=0,t=0;
ch=str[i];
i++;
while(ch!='\0')
{ switch(ch)
{ case '(': *op.top++=ch; break;
case ')': while(*(op.top-1)!='(')
{ rpn[t]=*(op.top-1);
op.top--;
t++;
}
op.top--;//此处必须再次进行--运算,才能忽略已经进入的‘(’
break;
case '+':
case '-':
while(op.top!=op.base && *(op.top-1)!='(')
{rpn[t]=*(op.top-1);
op.top--;
t++;
}
*op.top++=ch;
break;
case '*':
case '/':
while(*(op.top-1)=='*'||*(op.top-1)=='/')
{rpn[t]=*(op.top-1);
op.top--;
t++;
}
*op.top++=ch;
break;
case ' ':break;
default:
while(ch>='0'&&ch<='9')
{rpn[t]=ch;
t++;
ch=str[i];
i++;
}
i--;
rpn[t]='#';t++;
}//switch
ch=str[i];
i++;
}//while
while(op.top!=op.base)
{rpn[t]=*(op.top-1);
t++;
op.top--;
}//while
rpn[t]='\0';
}//trans
//*****************************************************************************
int value(char rpn[])
{//后缀表达式求值
float d;
char ch;
int t=0;

ch=rpn[t];
t++;
while(ch!='\0')
{
switch(ch)
{case '+':
*(st.top-2)=*(st.top-2) + *(st.top-1);
st.top--;
break;
case '-':
*(st.top-2)=*(st.top-2) - *(st.top-1);
st.top--;
break;
case '*':
*(st.top-2)=*(st.top-2) * *(st.top-1);
st.top--;
break;
case '/':
if(*(st.top-1)!=0)
*(st.top-2)=*(st.top-2) / *(st.top-1);
else
{printf("\n除0错误!\n");
exit(0);
}
st.top--;
break;
default:
d=0;
while(ch>='0'&&ch<='9')
{d=10*d+ch-'0';
ch=rpn[t];
t++;
}
*(st.top++)=d;
}//switch
ch=rpn[t]; t++;

}//while
return *(st.top-1);
}//value
//*****************************************************************************
int main()
{//主函数
char str[MAXSIZE],rpn[MAXSIZE],g,f;
//str数组用来存储接收到的字符串,rpn用来存放转换出来的后缀表达式
int i,j=0;
InitStack();
Menu();

while(1)
{
scanf("%d",&g);
switch(g)
{
case 1: printf("请输入表达式:");
scanf("%s",str);
i=Match(str);
break;
case 2: if(i==1) printf("匹配成功!\n");
else printf("匹配失败!\n");
break;
case 3: if(i==1)
{trans(str,rpn);
printf("后缀表达式为:%s\n", rpn);
j=1;}
else  {j=0; printf("表达式中括号匹配错误!\n");}
break;
case 4: if(j) printf("计算结果为:%d\n",value(rpn));
else printf("后缀表达式转换遇到问题!\n");
break;
case 5: printf("确定要退出系统吗?(y/n)\n");
getchar();f=getchar();
if(f=='y'||f=='Y') exit(0);
else {printf("请重新选择!\n");break;}
default:printf("输入错误!\n");
exit(1);
}//switch
}//while
return 0;
}//main


项目运行与测试

编译运行后显示结果为:
运行主界面:



 运行首界面

 

 

运行测试,如图所示。分三种情况进行测试:一是不包含小括号的表达式、二是包含小括号并且匹配成功、三是包含小括号但匹配失败。

 



运行测试

 
 
 

退出环节设计运行,如图所示。



退出设计

 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐