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

本文是具体代码实现,详解请看https://blog.csdn.net/MistyWood/article/details/99486551

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

项目运行与测试

编译运行后显示结果为:

运行主界面:
运行首界面

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

运行测试

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

运行环境是VC++6.0,有人反馈在别的运行环境下出错的情况,具体原因不明,没有用过别的编译器,有机会研究一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值