2-3 符号配对
分数 6
作者 DS课程组
单位 浙江大学
请编写程序检查C语言源程序中下列符号是否配对:/*与*/、(与)、[与]、{与}。
输入格式:
输入为一个C语言源程序。当读到某一行中只有一个句点.和一个回车的时候,标志着输入结束。程序中需要检查配对的符号不超过100个。
输出格式:
首先,如果所有符号配对正确,则在第一行中输出YES,否则输出NO。然后在第二行中指出第一个不配对的符号:如果缺少左符号,则输出?-右符号;如果缺少右符号,则输出左符号-?。
输入样例1:
1 2 3 4 5 6 7
| void test() { int i, A[10]; for (i=0; i<10; i++) { /*/ A[i] = i; } .
|
输出样例1:
输入样例2:
1 2 3 4 5 6 7
| void test() { int i, A[10]; for (i=0; i<10; i++) /**/ A[i] = i; }] .
|
输出样例2:
输入样例3:
1 2 3 4 5 6 7 8
| void test() { int i double A[10]; for (i=0; i<10; i++) /**/ A[i] = 0.1*i; } .
|
输出样例3:
我的初始错误代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| #include <iostream> using namespace std;
typedef struct { char *elem; int top; }sqStack;
void initStack(sqStack &stack) { stack.elem = new char[100]; stack.top = -1; }
char getTop(sqStack stack) { return stack.elem[stack.top]; }
bool isEmpty(sqStack stack) { if (stack.top == -1) { return true; } return false; }
void push(sqStack &stack, char c) { stack.top++; stack.elem[stack.top] = c; }
void pop(sqStack &stack) { stack.top--; }
void matching(sqStack stack, string str) { int i = 0; int j = i+1; while (str[i] != '.') { if (str[i] == '(' || str[i] == '[' || str[i] == '{') { push(stack, str[i]); } else if (str[i] == '/' && str[j] == '*') { push(stack, str[i]); push(stack, str[j]); i = j; } else if (str[i] == ')') { if (isEmpty(stack)) { cout << "NO" << endl; cout << "(-?"; return; } else if (getTop(stack) == '(') { pop(stack); } } else if (str[i] == ']') { if (isEmpty(stack)) { cout << "NO" << endl; cout << "[-?"; return; } else if (getTop(stack) == '[') { pop(stack); } } else if (str[i] == '}') { if (isEmpty(stack)) { cout << "NO" << endl; cout << "{-?"; return; } else if (getTop(stack) == '{') { pop(stack); } } else if (str[i] == '*' && str[j] == '/') { if (stack.top < 1) { cout << "NO" << endl; cout << "/*-?"; return; } else if (getTop(stack) == '*') { pop(stack); if (getTop(stack) == '/') { pop(stack); } else { cout << "NO" << endl; cout << "?-/*"; return; } } } i++; } cout << "YES"; }
int main() { sqStack stack; initStack(stack); string str; cin >> str; matching(stack, str); }
|
1.输入处理错误:
这种方式只能读取单行输入,且会忽略空格和换行符,无法处理多行的 C 语言代码,也无法检测到单独的.作为结束标志。
改正方案:
1 2 3 4 5 6 7 8
| string line; while (getline(cin, line)) { if (line == ".") { foundEnd = true; break; } }
|
使用getline逐行读取输入,直到遇到只包含.的行才停止,符合题目要求。
2.有右括号的情况下栈中的元素不匹配
有问题
改正1(错误)
发现最后一个答案不正确,又发现把测试用例1输入对应的输出是*-?,
通过在有右括号的情况下的找栈顶发现不匹配的地方,加上了:
如果是*/,就判断栈中是不是*/,其他就直接输出栈顶元素-?
见改正2
| 测试点 |
提示 |
内存(KB) |
用时(ms) |
结果 |
得分 |
|
| 0 |
|
484 |
2 |
答案正确 |
1 / 1 |
|
| 1 |
|
552 |
2 |
答案正确 |
1 / 1 |
|
| 2 |
|
552 |
2 |
答案正确 |
1 / 1 |
|
| 3 |
|
600 |
2 |
答案正确 |
1 / 1 |
|
| 4 |
|
564 |
2 |
答案正确 |
1 / 1 |
|
| 5 |
|
576 |
2 |
答案错误 |
0 / 1 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| #include <iostream> #include <string> #include <stack>
using namespace std;
void matching() { stack<char> symbolStack; string line; string error_symbol = "";
while (getline(cin, line)) { if (line == ".") { break; }
for (size_t i = 0; i < line.size(); ++i) { char c = line[i]; if (c == '(' || c == '[' || c == '{') { symbolStack.push(c); } else if (c == '/') { if (i + 1 < line.size() && line[i + 1] == '*') { symbolStack.push('C'); i++; } } else if (c == ')' || c == ']' || c == '}') { if (symbolStack.empty()) { error_symbol = "?-"; error_symbol += c; goto end_of_check; } char top = symbolStack.top(); symbolStack.pop();
if ((c == ')' && top != '(') || (c == ']' && top != '[') || (c == '}' && top != '{')) { error_symbol = top; error_symbol += "-?"; goto end_of_check; } } else if (c == '*') { if (i + 1 < line.size() && line[i + 1] == '/') { if (symbolStack.empty() || symbolStack.top() != 'C') { error_symbol = "?-*/"; goto end_of_check; } symbolStack.pop(); i++; } } } }
end_of_check:;
if (error_symbol != "") { cout << "NO" << endl; cout << error_symbol << endl; } else if (symbolStack.empty()) { cout << "YES" << endl; } else { cout << "NO" << endl; char top = symbolStack.top(); if (top == 'C') { cout << "/*-?" << endl; } else { cout << top << "-?" << endl; } } }
int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); matching(); return 0; }
|
改正2(错误)
| 测试点 |
提示 |
内存(KB) |
用时(ms) |
结果 |
得分 |
|
| 0 |
|
552 |
2 |
答案正确 |
1 / 1 |
|
| 1 |
|
524 |
2 |
答案正确 |
1 / 1 |
|
| 2 |
|
576 |
2 |
答案正确 |
1 / 1 |
|
| 3 |
|
524 |
2 |
答案正确 |
1 / 1 |
|
| 4 |
|
584 |
2 |
答案正确 |
1 / 1 |
|
| 5 |
|
564 |
2 |
答案错误 |
0 / 1 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| #include <iostream> using namespace std;
typedef struct { char *elem; int top; }sqStack;
void initStack(sqStack &stack) { stack.elem = new char[100]; stack.top = -1; }
char getTop(sqStack stack) { return stack.elem[stack.top]; }
bool isEmpty(sqStack stack) { if (stack.top == -1) { return true; } return false; }
void push(sqStack &stack, char c) { stack.top++; stack.elem[stack.top] = c; }
void pop(sqStack &stack) { stack.top--; }
void matching(sqStack stack) { bool foundEnd = false; string line; while (getline(cin, line)) { if (line == ".") { foundEnd = true; break; } for (int i = 0; i < line.size(); i++) { if (line[i] == '(' || line[i] == '[' || line[i] == '{') { push(stack, line[i]); } else if (line[i] == '/' && i + 1 < line.size() && line[i + 1] == '*') { push(stack, line[i]); push(stack, line[i + 1]); i++; } else if (line[i] == ')') { if (isEmpty(stack)) { cout << "NO" << endl; cout << "?-)"; return; } else if (getTop(stack) == '(') { pop(stack); } else { cout << "NO" << endl; if (stack.top >= 1 && stack.elem[stack.top-1] == '/' && stack.elem[stack.top] == '*') { cout << "/*-?"; return; } cout << getTop(stack) << "-?"; return; } } else if (line[i] == ']') { if (isEmpty(stack)) { cout << "NO" << endl; cout << "?-]"; return; } else if (getTop(stack) == '[') { pop(stack); } else { cout << "NO" << endl; if (stack.top >= 1 && stack.elem[stack.top-1] == '/' && stack.elem[stack.top] == '*') { cout << "/*-?"; return; } cout << getTop(stack) << "-?"; return; } } else if (line[i] == '}') { if (isEmpty(stack)) { cout << "NO" << endl; cout << "?-}"; return; } else if (getTop(stack) == '{') { pop(stack); } else { cout << "NO" << endl; if (stack.top >= 1 && stack.elem[stack.top-1] == '/' && stack.elem[stack.top] == '*') { cout << "/*-?"; return; } cout << getTop(stack) << "-?"; return; }
} else if (line[i] == '*' && i + 1 < line.size() && line[i + 1] == '/') { if (stack.top < 1 || getTop(stack) != '*' && stack.elem[stack.top - 1] != '/') { cout << "NO" << endl; cout << "?-*/"; return; } pop(stack); pop(stack); i++; } } } if (!foundEnd) { cout << "NO"; } if (isEmpty(stack)) { cout << "YES"; } else { cout << "NO" << endl; if (stack.top >= 1 && stack.elem[stack.top-1] == '/' && stack.elem[stack.top] == '*') { cout << "/*-?"; } else { cout << getTop(stack) << "-?"; }
} }
int main() { sqStack stack; initStack(stack); matching(stack); }
|
正确代码
- 正确且简化了代码逻辑
- 把
/*视为一个整体,用单个特殊字符'C'入栈
- 匹配
*/时,只需检查栈顶是否是'C',一次出栈即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| #include <iostream> using namespace std;
typedef struct { char *elem; int top; }sqStack;
void initStack(sqStack &stack) { stack.elem = new char[100]; stack.top = -1; }
char getTop(sqStack stack) { return stack.elem[stack.top]; }
bool isEmpty(sqStack stack) { if (stack.top == -1) { return true; } return false; }
void push(sqStack &stack, char c) { stack.top++; stack.elem[stack.top] = c; }
void pop(sqStack &stack) { stack.top--; }
void matching(sqStack stack) { string line; while (getline(cin, line)) { if (line == ".") { break; } for (int i = 0; i < line.size(); i++) { char c = line[i];
if (c == '(' || c == '[' || c == '{') { push(stack, c); } else if (c == '/' && i + 1 < line.size() && line[i + 1] == '*') { push(stack, 'C'); i++; }
else if (c == ')' || c == ']' || c == '}') { char required_left = (c == ')') ? '(' : (c == ']') ? '[' : '{'; if (isEmpty(stack)) { cout << "NO" << endl; cout << "?-" << c; return; } char top = getTop(stack);
if (top == required_left) { pop(stack); } else if (top == 'C') { cout << "NO" << endl; cout << "/*-?"; return; } else { cout << "NO" << endl; cout << getTop(stack) << "-?"; return; } }
else if (c == '*' && i + 1 < line.size() && line[i + 1] == '/') { if (isEmpty(stack)) { cout << "NO" << endl; cout << "?-*/"; return; } else if (getTop(stack) == 'C') { pop(stack); i++; } else { cout << "NO" << endl; cout << getTop(stack) << "-?"; return; } } } } if (isEmpty(stack)) { cout << "YES"; } else { cout << "NO" << endl; char top = getTop(stack); if (top == 'C') { cout << "/*-?"; return; } else { cout << getTop(stack) << "-?"; return; }
} }
int main() { sqStack stack; initStack(stack); matching(stack); }
|
核心思路:用栈(先进后出) 处理符号配对,将双字符注释/*抽象为单个标识简化逻辑,按 “左符号入栈、右符号匹配出栈” 的规则校验。
关键步骤
- 左符号入栈:遇到
(/[/{直接入栈;遇到/*时,压入特殊字符'C'(代表注释开始,避免双字符拆分混乱)。
- 右符号匹配:
- 遇到
)/]/}时,检查栈顶是否为对应左符号,匹配则出栈,不匹配或栈空直接报错。
- 遇到
*/时,检查栈顶是否为'C'(对应/*),匹配则出栈,否则报错。
- 最终校验:所有输入处理完后,栈为空则配对成功(输出 YES),非空则存在未匹配左符号(输出对应错误)。