括号匹配问题 - 九度教程第26题
题目:
时间限制:1 秒 内存限制:32 兆 特殊判题:否
题目描述:
在某个字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"标注,不能匹配的右括号用"?"标注.
输入:
输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母,字符串长度不超过100。
输出:
对每组输出数据,输出两行,第一行包含原始输入字符,第二行由"$","?"和空格组成,"$"和"?"表示与之对应的左括号和右括号不能匹配。样例输入:
样例输出:
括号匹配问题是堆栈的一个典型应用。
每一个右括号与在其之前所有未被匹配的左括号中最靠右的一个匹配。
若按照从左至右的顺序遍历字符串,并将遇到的所有左括号都放入堆栈中等待匹配;若在遍历过程中遇到一个右括号,由于按照从左向右的顺序遍历字符串,若此时堆栈非空,那么栈顶左括号即为与其匹配的左括号;相反,若堆栈为空,则表示在其之前不存在未被匹配的左括号,匹配失败。
注:
ans[i]='\0'; //或者ans[i]=0,为了使输出形成字符串,在其最后一个字符后添加一个空字符。
注:'\0’代表ASCII码为0的字符,从ASCII码表中可以查到ASCII码为0的字符不是一个可以显示的字符,而是一个“空操作符”,即它什么也不干。用它来作为字符串结束标志不会产生附加的操作或增加有效字符,只起一个供辨别的标志。
C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。字符串总是以'\0'
作为串的结束符。因此当把一个字符串存入一个数组时,也把结束符 '\0'
存入数组,并以此作为该字符串是否结束的标志。有了'\0'
标志后,就不必再用字符数组的长度来判断字符串的长度了。
代码:
#include<stdio.h>
#include<stack>
using namespace std;
stack<int> S; //定义一个堆栈
char str[110];//保存输入字符串
char ans[110];//保存输出字符串
int main()
{
while(scanf("%s",str)!=EOF) //输入字符串
{
int i;
for(i=0;str[i]!=0;i++)//从左到右遍历字符串
{
if(str[i]=='(') //若遇到左括号
{
S.push(i); //将其数组下标放到堆栈中
ans[i]=' '; //暂且将对应的输出字符串位置改为空格
}
else if(str[i]==')') //若遇到右括号
{
if(S.empty()==false)//若此时堆栈非空
{
S.pop(); //栈顶位置左括号与其匹配,从栈中弹出该已经匹配的左括号
ans[i]=' '; //修改输出中该位置为空格
}
else
{
ans[i]='?'; //若堆栈为空,则无法找到左括号与其匹配,修改输出中该位置为“?”
}
}
else
{
ans[i]=' ';
}
}
while(!S.empty())//当字符串遍历完成后,尚留在堆栈中的左括号无法匹配
{
ans[S.top()]='$'; //修改其在输出位置中的位置为'$'
S.pop(); //弹出
}
ans[i]='\0'; //为了使输出形成字符串,在其最后一个字符后添加一个空字符
puts(str);//输出原字符串
puts(ans);//输出答案字符串
}
return 0;
}