【C++】括号匹配问题与逆波兰表达式

一、括号匹配

1.输入一组字符,通过函数判断括号是否匹配,这样可以大大提高工作效率。

这个函数的作用很大,使用的方面也很多,在Vs中就有这样的功能,当你写代码时,当代码中的括号不匹配时,就会出现下划线,这样就省去了我们自己去找的时间。

2.函数的实现:

(1)应对  ( , ) , < , >  , [  , ] , {  ,  } 这些主要的符号进行处理

(2)获取一个字符串用循环语句,一个接一个查看字符,当字符不是  ( , ) , < , >  , [  , ] , {  ,  } 时,不处理

(3)当获取的字符为 ( ,<,{,[ 时存入栈中;当获取的字符为 ),> ,},] 时让栈顶元素并与当前字符判断,当能构成 (),[  ] ,{  } 时,出栈一次,当栈为空--->右括号多了,当不匹配时--->括号次序不对,当字符取完时栈不为空---->左括号多了

(4)当字符取完时,栈也为空---->括号匹配


3.函数代码

#include<stack>                              //2.括号匹配
bool MatchBrackets(char* pStr)
{
	if (pStr == NULL)
		return true;
	stack<char> s;
	int len = strlen(pStr);
	for (int i = 0; i < len; i++)
	{
		if (pStr[i] != '(' && pStr[i] != ')' &&
			pStr[i] != '[' && pStr[i] != ']' &&
			pStr[i] != '{' && pStr[i] != '}')
			continue;
		else
		{
			if (pStr[i] == '(' || pStr[i] == '[' || pStr[i] == '{')
				s.push(pStr[i]);
			if (pStr[i] == ')' || pStr[i] == ']' || pStr[i] == '}')
			{
				if (s.empty())
				{
					cout << "右括号多" << endl;
					return false;
				}
				if ((s.top()=='('&&pStr[i]==')')||(s.top()=='['&&pStr[i]==']')||(s.top()=='{'&&pStr[i]=='}'))
					s.pop();
			    else
					{
						cout << "次序错误" << endl;
						return false;
					}
			}
		}
	}
	if (!s.empty())
	{
		cout << "左括号多" << endl;
		return false;
	}
	else
		return true;
}
测试

int main()
{
	char *p = "(()]";        //括号不匹配
	/*char*p = "()()()(";    //左括号多
	char*p = "()()(()))";    //右括号多了
	char*p = "(){}[]";*/     //括号不匹配
	bool ret=MatchBrackets(p);   
	cout << ret << endl;  
	system("pause"); 
	return 0;
}
这里就完成了一个简单的括号匹配函数


二、逆波兰表达式

1.逆波兰表达式也称后缀表达式

2.在我们写一个算式时,一般都会写成  12x(3+4)-6+8/2  这个是中缀表达式。

将这个中缀表达式改成后缀表达式则为 12 3 4  -  * 6 - 8 2 / +

3.给出一个后缀表达式,按其格式写代码求出其值

enum OPERATOR                    //3.简易版后缀表达式的实现
{
	ADD,
	SUB,
	MUL,
	DIV,
	DATA
};
struct Cell
{
	OPERATOR _op;
	int data;
};
int CalcRPN(Cell* p, int size)
{
	stack<int> s;
	for (int i = 0; i < size; i++)
	{
		if (DATA == p[i]._op)
			s.push(p[i].data);
		else
		{
			int right = s.top();
			s.pop();
			int left = s.top();
			s.pop();
			switch (p[i]._op)
			{
			case ADD:
				s.push(left + right);
				break;
			case SUB:
				s.push(left - right);
				break;
			case MUL:
				s.push(left*right);
				break;
			case DIV:
				s.push(left / right);
				break;
			default:
				break;
			}
		}
	}
	return s.top();
}
int main()
{
	Cell RPN[] = { { DATA, 12 }, { DATA, 3 }, { DATA, 4 }, { ADD, 0 }, { MUL, 0 },
	{ DATA, 6 }, { SUB, 0 }, { DATA, 8 }, { DATA, 2 }, { DIV, 0 }, { ADD, 0 } };
	int ret=CalcRPN(RPN, sizeof(RPN) / sizeof(Cell));
	cout << ret << endl;
	system("pause");
	return 0;
}

4.中缀式转换成后缀式

代码实现

#include<assert.h>
bool Isoperator(const char ch)
{
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%' || ch == '(' || ch == ')')
		return true;
	return false;
}
//栈内操作符
int isp(char ch)
{
	switch (ch)
	{
	case '#':
		return 0;
	case '(':
		return 1;
	case '*':
	case '/':
	case '%':
		return 5;
	case '+':
	case '-':
		return 3;
	case ')':
		return 6;
	default:
		assert(0);
		cout << "运算符不合法" << endl;
	}
	return 0;
}
//栈外操作符
int icp(char ch)
{
	switch (ch)
	{
	case '#':
		return 0;
	case '(':
		return 6;
	case '*':
	case '/':
	case '%':
		return 4;
	case '+':
	case '-':
		return 2;
	case ')':
		return 1;
	default:
		assert(0);
		cout << "运算符不合法" << endl;
	}
	return 0;
}
void Postfixnotation(char*Expre)
{
	//stack<char>Data;
	string str;
	char ch;
	stack<char>Op;
	Op.push('#');
	int i = 0;
	while (Expre[i])
	{
		if (!Isoperator(Expre[i]))
		{
			str.push_back(Expre[i]);
			cout << Expre[i];
		}
		else
		{
			str.push_back(' ');
			cout << ' ';
			ch = Op.top();
			if (icp(Expre[i]) > isp(ch))
				Op.push(Expre[i]);
			else if (icp(Expre[i]) < isp(ch))
			{
				str.push_back(ch);
				Op.pop();
				cout << ch;
				continue;
			}
			else
			{
				if (Op.top() == '(')
				{
					Op.pop();
				}
			}
		}
		++i;
	}
	while (Op.top() != '#')
	{
		ch = Op.top();
		str.push_back(ch);
		cout << ch;
		Op.pop();
	}
	cout << endl;
	str.push_back(0);
}

测试函数

int main()
{
	char*p = "12*(3+4)-6+8/2";
	Postfixnotation(p);
	system("pause");
	return 0;
}
可得后缀表达式







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值