【问题描述】
设计一个算法判别一个算术表达式的圆括号是否正确配对
【输入形式】
一个以@为结尾的算术表达式
【输出形式】
若配对,则输出圆括号的对数;否则输出no
【样例输入】(a+b)/(c+d)@
【样例输出】 2
【样例说明】共有两对括号,输出2
【评分标准】
PS:使用栈相关知识,否则不能得分
思路:
使用堆栈存储左括号。
括号配对的表达式的左右括号对称,根据这一性质,我们可以将左括号压入堆栈,碰到右括号时判断栈顶元素和该右括号是否匹配,匹配成功则将栈顶元素出栈,失败则标志flag为0,直接退出循环。
难点:
我认为这个题的一个难点在于如何将表达式输入。我起初将字符串定义为“char str[MAX] = {0};”使用“cin >> str”输入,后来发现str一旦遇到空格就不会读取后面的表达式,即表达式不完整。cin语句的分隔符为:空格、tab键、换行(回车)。使用gets函数也可以,但可能会用警告,因为gets函数原型为: char *gets(char *str),而我们定义的字符串不是指针型的。
PS:指针字符其实我自己也不太清楚,我在原代码基础上改了一点后,变成运行时错误了。有大佬看到问题的话不妨评论一下告诉小的。(完整的通过代码见最下方!)
#include <iostream>
#include <string>
#include <stack>
#define MAX 100
using namespace std;
/**判断括号是否匹配*/
bool isMatch(char ch1, char ch2)
{
if((ch1 == '(' && ch2 == ')') || (ch1 == '[' && ch2 == ']') || (ch1 == '{' && ch2 == '}'))
{
return true;
}
return false;
}
int main()
{
stack<char> stack1;
string str; // 定义表达式字符串
getline(cin, str); // getline函数输入string字符串
int i = 0, cnt = 0, flag = 1; // i表示字符串下标,cnt为累加器,flag标志是否匹配成功
while(1)
{
// 当扫描到结束符‘@’的时候退出循环
if(str[i] == '@')
{
break;
}
// 为左括号时压栈
if(str[i] == '(' || str[i] == '[' || str[i] == '{')
{
stack1.push(str[i]);
}
// 为右括号时进行判断
else if(str[i] == ')' || str[i] == ']' || str[i] == '}')
{
// 如果栈为空,表示没有匹配的左括号,匹配失败;如果不匹配,也是匹配失败。flag为0,退出循环
if(stack1.empty() || !isMatch(stack1.top(), str[i]))
{
flag = 0;
break;
}
// 匹配成功,栈顶元素出栈,累加器加一
stack1.pop();
cnt++;
}
i++;
}
// 如果栈为空,表示括号匹配完全且成功,flag为1表示没有多余的括号
if(stack1.empty() && flag == 1)
{
cout << cnt;
}
// 匹配失败输出“no”
else
{
cout << "no";
}
return 0;
}