一、要求
输入一串任意的中缀表达式,对该表达式的合法性进行判断。
二、分析
不合法的表达式如:
(a+b | *a+b | a+() | (a+b)(a-b) |
大致可以归纳为以下四种非法情况:
1、括号不匹配
例如:
(a+b:左括号未匹配
a+b):右括号未匹配
a+b)+(a+c:括号数量相同但显然不匹配
2、操作符左右元素不合法
中缀表达式的操作符是以中缀形式位于运算数中间,所以一个操作符的左右应该都有元素,且必须是运算数(中缀表达式经常使用括号,所以这里的运算数不局限于数字,也可以是一个表达式)。
例如:
+(a+b):操作符 + 号前一位没有运算数
(a+b)*:操作符 * 号后一位没有运算数
a+-b:操作符 + 号后一位还是操作符
(a+b)-(a+c):虽然操作符 - 号的前后一位都是括号,但是这里应该把 a+b 和 a+c 整体的表达式看作一个运算数,所以是合法的
总结:
① 操作符前后位不能为空
② 操作符前后位不能为操作符
③ 操作符前一位可以为 ),但不能为 ( ;操作符后一位可以为 (,但不能为 ) 。
注:'-' 号比较特殊,需要判断它是作为负数符号还是操作符。
3、左括号和右括号相邻
例如:
(a+b)(a-b):括号匹配但明显不合法
(a+b)-():括号匹配但明显不合法
注:以上三种情况可能会出现重叠,但问题不大,只要能检测出不合法就行
三、算法实现
程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<ctype.h>
#define ERROR 0
#define OK 1
#define STACK_INT_SIZE 10 /*存储空间初始分配量*/
#define STACKINCREMENT 5 /*存储空间分配增量*/
#define M 50
typedef char ElemType; /*定义字符数据类型*/
/*字符栈*/
typedef struct{
ElemType *base;
ElemType *top;
int stacksize; /*当前已分配的存储空间*/
}SqStack;
int InitStack(SqStack *S); /*构造空栈*/
int push(SqStack *S,ElemType e); /*入栈*/
int Pop(SqStack *S,ElemType *e); /*出栈*/
int StackEmpty(SqStack *s); /*栈空判断*/
int isoperator(char c); /*操作符判断*/
int ExpressionCheck(ElemType *str); /*中缀表达式合法性检查*/
/*初始化栈*/
int InitStack(SqStack *S){
S->base=(ElemType *)malloc(STACK_INT_SIZE * sizeof(ElemType));
if(!S->base)
return ERROR; //分配失败
S->top = S->base;
S->stacksize = STACK_INT_SIZE;
return OK;
}/*InitStack*/
/*入栈*/
int Push(SqStack *S,ElemType e){
//判断栈满
if(S->top - S->base >= S->stacksize){
S->base = (ElemType *)realloc(S->base,(S->stacksize + STACKINCREMENT)*sizeof(ElemType));
if(NULL == S->base) //分配失败
return ERROR;
S->top = S->base + S->stacksize;
S->stacksize = S->stacksize+STACKINCREMENT;
}
*S->top = e;
S->top++;
return OK;
}
/*出栈*/
int Pop(SqStack *S,ElemType *e){
//判断栈空
if(S->top == S->base)
return ERROR;
S->top--;
*e=*S->top;
return OK;
}/*Pop*/
/*判断栈空*/
int StackEmpty(SqStack *s){
if(s->top == s->base)
return OK;
return ERROR;
}/*StackEmpty*/
/*判断字符c是否为运算符*/
int isoperator(char c)
{
switch(c)
{
case '+':return OK;
case '-':return OK;
case '*':return OK;
case '/':return OK;
default:return ERROR;
}
}
/*判断中缀表达式是否合法*/
//str为输入的中缀表达式字符串
int ExpressionCheck(ElemType *str)
{
//初始化一个字符栈
SqStack s;
InitStack(&s);
ElemType e;
int i;
//不合法情况1:括号不匹配
for(i=0 ; i<strlen(str) ; i++) //遍历中缀表达式
{
if(str[i] == '(')
Push(&s,str[i]);
if(str[i] == ')')
{
if(StackEmpty(&s))
return ERROR;
Pop(&s,&e);
}
}
if(!StackEmpty(&s))
return ERROR;
//不合法情况2:操作符左右元素不合法
for(i=0 ; i<strlen(str) ; i++)
{
//先判断 '-' 是不是负数符号
if('-' == str[i])
{
if( 0==i || '('==str[i-1] ) //如果 - 在第一位或者前面有(,一定是作为负数符号而非操作符
i++;
}
if(isoperator(str[i]))
{
if( 0==i || strlen(str)-1==i )
return ERROR;
if( isoperator(str[i-1]) || isoperator(str[i+1]) )
return ERROR;
if( '('==str[i-1] || ')'==str[i+1] )
return ERROR;
}
}
//不合法情况3:左括号和右括号相邻,例:a+()和(a+b)(a+b)
for(i=0 ; i<strlen(str) ; i++)
{
if(str[i]=='(' && str[i+1]==')')
return ERROR;
if(str[i]==')' && str[i+1]=='(')
return ERROR;
}
return OK; //未出现不合法情况,返回1
}
int main()
{
char str[M];
printf("\n输入一串中缀表达式:\n");
gets(str);
int v = ExpressionCheck(str);
if( v )
{
printf("\n中缀表达式合法\n");
return 0;
}
printf("\n中缀表达式不合法\n");
return 0;
}
- 运行结果:
非法情况1:
非法情况2:
'-' 作为负数符号
非法情况3:
合法情况判断: