7-22 符号配对
题目背景
请编写程序检查C语言源程序中下列符号是否配对:/*
与*/
、(
与)
、[
与]
、{
与}
。
输入格式:
输入为一个C语言源程序。当读到某一行中只有一个句点.
和一个回车的时候,标志着输入结束。程序中需要检查配对的符号不超过100个。
输出格式:
首先,如果所有符号配对正确,则在第一行中输出YES
,否则输出NO
。然后在第二行中指出第一个不配对的符号:如果缺少左符号,则输出?-右符号
;如果缺少右符号,则输出左符号-?
。
输入样例1:
void test()
{
int i, A[10];
for (i=0; i<10; i++) { /*/
A[i] = i;
}
.
输出样例1:
NO
/*-?
输入样例2:
void test()
{
int i, A[10];
for (i=0; i<10; i++) /**/
A[i] = i;
}]
.
输出样例2:
NO
?-]
输入样例3:
void test()
{
int i
double A[10];
for (i=0; i<10; i++) /**/
A[i] = 0.1*i;
}
.
输出样例3:
YES
鸣谢用户 王渊博 补充数据!
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB
题目分析
本题其实是一个经典的使用堆栈结构解决符号匹配问题。
首先需要明确什么样的符号组合是不合法的
缺少左符号的定义:
例如:}或{}}等情况。前面的符号全部得到匹配,但是出现了没有左边符号的右符号。
缺少右符号的定义:
例如:{或{【】等情况。出现一直未能匹配的左符号。
所谓的第一个不匹配的符号:
例如:出现情况{】,左右符号不能匹配,此时应该提示出现的较早的{的问题,即缺少右符号。
特别的,出现情况{【},应当判定为“符号【缺少右符号”,出现情况{】}却应该判定为“符号{缺少右符号”。
据此,本题有如下难点或易错点:
- 堆栈空:容易访问空的栈。每次取出栈顶元素时,应当首先判断栈是否为空!在不同时候堆栈空可能对应不同的问题。
- 符号长度不同:对于括号和注释,占用的长度不同,需要特别注意。
- 循环结束后的判断:循环检查结束后,不要忘记检查栈,若栈内还有元素,应当是错误的程序,应该给出NO的判断。
代码思路
栈的定义
由于符号长短不一,将栈定义为string类型,可以储存不同长度的左符号。
获取输入
由于要求一排一排查看是否退出,所以需要使用getline来读取。然后在每排查看符号是否是左右符号,对符合左右符号的位置进行检测。
检测思路
遇到左符号,无需顾虑太多,直接入栈即可。注意,符号“/*”的检测可以使用:data[i] == '/' && i + 1 < data.length() && data[i+1] == '*'即可。该符号检测完,应该让i额外加一,以跳过第二个字符。
遇到右符号,首先看栈是否为空。如果为空,显然此时是缺少左符号,按照当前右符号输出对应提示即可。
如果栈不为空,那么取出栈顶元素。栈顶元素如果与当前右符号匹配,则弹栈即可。
如果不匹配,那么此时是例如{】的情况,按上文所述,判断为缺少右符号,提示栈顶元素缺少右符号即可。
另外,右符号“*/”识别思路与上文“/*”相似,同样应该注意检测完,应该让i额外加一,以跳过第二个字符。
最后整个程序结束后,判断栈是否空。若为空且前面未检测出异常,则整个程序无误。若不为空,那么显然犯了缺少右符号的问题。此时提示栈顶元素缺少有符号即可。
代码
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int main() {
stack<string> fh;
string data;
int OK = 0;
while (OK >= 0) {
getline(cin, data);
if (data == ".") {
break;
}
for (int i = 0; i < data.length(); i++) {
if (data[i] == '(') {
fh.push("(");
}
if (data[i] == '[') {
fh.push("[");
}
if (data[i] == '{') {
fh.push("{");
}
if (data[i] == '/' && i + 1 < data.length()) {
if (data[i + 1] == '*') {
fh.push("/*");
if (i + 2 < data.length()) {
i++;
continue;
} else {
break;
}
}
}
if (data[i] == ')') {
if (fh.empty()) {
cout << "NO" << endl;
cout << "?-)";
OK = -1;
break;
} else if (fh.top() != "(") {
cout << "NO" << endl;
cout << fh.top() << "-?";
OK = -1;
break;
} else {
fh.pop();
}
}
if (data[i] == ']') {
if (fh.empty()) {
cout << "NO" << endl;
cout << "?-]";
OK = -1;
break;
} else if (fh.top() != "[") {
cout << "NO" << endl;
cout << fh.top() << "-?";
OK = -1;
break;
} else {
fh.pop();
}
}
if (data[i] == '}') {
if (fh.empty()) {
cout << "NO" << endl;
cout << "?-}";
OK = -1;
break;
} else if (fh.top() != "{") {
cout << "NO" << endl;
cout << fh.top() << "-?";
OK = -1;
break;
} else {
fh.pop();
}
}
if (data[i] == '*') {
if (i + 1 < data.length()) {
if (data[i + 1] == '/') {
if (fh.empty()) {
cout << "NO" << endl;
cout << "?-*/";
OK = -1;
break;
} else if (fh.top() != "/*") {
cout << "NO" << endl;
cout << fh.top() << "-?";
OK = -1;
break;
} else {
fh.pop();
if (i + 2 < data.length()) {
i++;
continue;
} else {
break;
}
}
}
}
}
}
}
if (OK == 0) {
if (fh.empty()) {
cout << "YES";
} else {
cout << "NO" << endl;
cout << fh.top() << "-?";
}
}
}