题目
请编写程序检查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
我的代码里写了不少的if-else
语句,代码写着写着就把自己给绕晕了。理清思路很重要。
思路分析
源程序一行一行地输入,用字符数组partCodes
接收。先把源程序的要配对的符号提取到字符数组 bracketInCodes
中。
接着遍历 bracketInCodes
,如果是左括号或者 /*
就入栈,如果是右括号或者 */
就从栈中弹出字符来配对:
----如果配对就令栈的指针top
减一位;
----如果不配对就输出缺少的括号或者注释符号,缺少左边与右边的又要分类讨论。
如果遍历完后且栈为空,说明配对成功,输出 YES
;
如果遍历完后栈不为空,则说明左括号或者/*
多了,缺少右括号或者 */
。
在配对那一步中,程序利用了paringSymbols
这个字符数组来辅助配对。这个字符串其实只存了4个字符,却得用125个字节来存储,确实浪费。如果可以用java的Map集合就好了,或者自己实现一个。
此外,其实这题不用栈也是能实现的,而且可读性会高不少,直接拿一个字符数组和一个top
指针就可以了,毕竟这里只用了一个栈。用了栈反而还麻烦了不少。
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxSize 1000
typedef struct stack {
char arrays[100];
int top;
} * Stack;
Stack creatStack();
int isEmpty(Stack stack);
void push(Stack stack, char ch);
void pairSymbols(Stack stack);
int main() {
Stack stack = creatStack();
pairSymbols(stack);
return 0;
}
void pairSymbols(Stack stack) {
// 用来后续的配对
char paringSymbols[125] = "";
paringSymbols['('] = ')';
paringSymbols['['] = ']';
paringSymbols['{'] = '}';
// 用 < 代替 /*
paringSymbols['<'] = '>';
char bracketInCodes[100] = "";
int length = 0;
while (1) {
char partCodes[100];
gets(partCodes);
// 判断结束输入
if (partCodes[0] == '.' && partCodes[1] == '\0')
break;
// 先把源程序的要配对的符号提取到字符数组 bracketInCodes 中
for (int i = 0; partCodes[i] != '\0'; i++) {
if (partCodes[i] == '(' || partCodes[i] == ')' || partCodes[i] == '{' || partCodes[i] == '}' || partCodes[i] == '[' || partCodes[i] == ']')
bracketInCodes[length++] = partCodes[i];
else if (partCodes[i] == '/' && partCodes[i + 1] == '*') {
bracketInCodes[length++] = '<';
i++;
} else if (partCodes[i] == '*' && partCodes[i + 1] == '/') {
bracketInCodes[length++] = '>';
i++;
}
}
}
// 遍历 bracketInCodes ,如果是左括号就入栈;如果是右括号就从栈中弹出字符来配对;
int flag = 1;
for (int i = 0; i < length; i++) {
if (bracketInCodes[i] == '(' || bracketInCodes[i] == '[' || bracketInCodes[i] == '{' || bracketInCodes[i] == '<')
push(stack, bracketInCodes[i]);
else {
// 配对成功
if (paringSymbols[stack->arrays[stack->top]] == bracketInCodes[i])
stack->top--;
// 不配对就输出缺少的括号或者注释符号
else {
printf("NO\n");
// 缺少左边括号或者 /*
if (stack->top == -1) {
if (bracketInCodes[i] == '>')
printf("?-*/");
else
printf("?-%c", bracketInCodes[i]);
} else {
// 缺少右边边括号或者 */
if (stack->arrays[stack->top] == '<')
printf("/*-?");
else
printf("%c-?", stack->arrays[stack->top]);
}
flag = 0;
break;
}
}
}
if (flag && isEmpty(stack))
printf("YES");
// 当bracketInCodes为[[[]这种时,虽然flag=1,但是也是错误的
else if (flag && !isEmpty(stack)) {
// 缺少右边边括号或者 */
printf("NO\n");
if (stack->arrays[stack->top] == '<')
printf("/*-?");
else
printf("%c-?", stack->arrays[stack->top]);
}
}
Stack creatStack() {
Stack stack;
stack = (Stack)malloc(sizeof(struct stack));
stack->top = -1;
strcpy(stack->arrays, "");
return stack;
}
int isEmpty(Stack stack) {
if (stack->top == -1)
return 1;
else
return 0;
}
void push(Stack stack, char ch) {
stack->top++;
stack->arrays[stack->top] = ch;
}