题目链接
习题3.8 符号配对 - 浙大版《数据结构(第2版)》题目集
整体思路
- 循环读取字符,将字符存储到字符数组,直到
- 读到EOF
- 读到连续的
\n.\n - 超过字符数组最大限制
- 遍历字符串
- 如果读到左符号,入栈;
- 读到右符号,出栈
- 若栈空,说明缺少左符号,此时退出循环
- 若栈不空,将出栈的左符号与读到的右符号对比,若相等则匹配。若不相等,认为缺少右符号,退出循环
- 遍历结束,根据当前状态判断输出
- 栈不空,认为缺少右符号
- 栈空,若此前因为缺少左符号退出循环,认为缺少左符号。否则认为匹配正确,输出
YES
注意事项
- 左注释符号
/*和右注释符号*/由两个符号组成,此时应单独判断,并应考虑一些重合情况(类似/*/等不能认为匹配成功) - 题目未说明左注释符号
/*和右注释符号*/之间的注释是否需要匹配,实际测试注释中出现的符号也需要匹配 - 存储输入是字符数组,所以
/*入栈简化为将/+*入栈(实际为字符Y)
代码
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define MAX_SIZE 1000
bool Push(char* stack, int* top, char c);
bool Pop(char* stack, int* top, char *c);
bool isLeftChar(char ch);
bool isRightChar(char ch);
bool isLeftCommentChar(char ch, char nextCh);
bool isRightCommentChar(char ch, char nextCh);
bool isMatch(char leftCh, char rightCh);
int main()
{
char ch;
char buff[MAX_SIZE] = {'\0'};
int top = 0;
int num = 0;
char stack[MAX_SIZE] = {'\0'};
bool ret = false;
char rightErrCh = 0;
bool rightErr = false;
char leftErrCh = 0;
bool leftErr = false;
// 读取输入,直到读到EOF或者读到连续的\n.\n或超过字符数组的最大限制
while ((buff[num] = getchar()) != EOF && num < MAX_SIZE)
{
if (num >= 2 && (buff[num] == '\n' && buff[num-1] == '.' && buff[num-2] == '\n'))
{
break;
}
num++;
}
// 处理输入的字符
for (int i = 0; i < num; i++)
{
// 是左符号
if (isLeftChar(buff[i]))
{
// 入栈
ret = Push(stack, &top, buff[i]);
if (ret == false)
{
// 栈满
}
}
// 是右符号
else if (isRightChar(buff[i]))
{
// 出栈
ret = Pop(stack, &top, &ch);
if (ret == false)
{
// 栈空,认为缺少左符号
rightErr = true;
rightErrCh = buff[i];
// 退出循环
break;
}
else if (!isMatch(ch, buff[i]))
{
// 符号不匹配,认为缺少右符号
leftErr = true;
leftErrCh = ch;
// 退出循环
break;
}
}
// 是左注释符号
if (isLeftCommentChar(buff[i], buff[i+1]))
{
// 入栈
ret = Push(stack, &top, '/' + '*');
if (ret == false)
{
// 栈满
}
else
{
// 跳过左注释符号的*
i++;
}
}
// 是右注释符号
else if (isRightCommentChar(buff[i], buff[i+1]))
{
// 出栈
ret = Pop(stack, &top, &ch);
if (ret == false)
{
// 栈空,认为缺少左注释符号
rightErr = true;
rightErrCh = '*' + '/';
// 退出循环
break;
}
else if (!isMatch(ch, '*' + '/'))
{
// 注释符号不匹配,认为缺少右注释符号
leftErr = true;
leftErrCh = ch;
// 退出循环
break;
}
else
{
// 跳过右注释符号的/
i++;
}
}
}
// 输出结果
// 栈不空
if (top > 0)
{
// 由于缺少右符号退出循环
if (leftErr == true)
{
if (leftErrCh == '/' + '*')
{
printf("NO\n/*-?");
}
else
{
printf("NO\n%c-?", leftErrCh);
}
}
// 遍历结束时栈不空,认为缺少右符号
else
{
// 取栈顶元素
leftErrCh = stack[top-1];
if (leftErrCh == '/' + '*')
{
printf("NO\n/*-?");
}
else
{
printf("NO\n%c-?", leftErrCh);
}
}
}
// 栈空
else
{
// 没有错误
if (rightErr == false && leftErr == false)
{
printf("YES");
}
// 有错误
else
{
// 由于缺少左符号退出循环
if (rightErr)
{
if (rightErrCh == '*' + '/')
{
printf("NO\n?-*/");
}
else
{
printf("NO\n?-%c", rightErrCh);
}
}
}
}
return 0;
}
/**
* @brief 入栈
*
* @param stack 栈
* @param top 栈顶索引
* @param c 入栈字符
* @return true 成功入栈
* @return false 栈满,入栈失败
*/
bool Push(char* stack, int* top, char c)
{
bool ret = false;
if (*top >= MAX_SIZE)
{
// 栈满
ret = false;
}
else
{
stack[(*top)++] = c;
ret = true;
}
return ret;
}
/**
* @brief 出栈
*
* @param stack 栈
* @param top 栈顶索引
* @param ch 出栈字符
* @return true 成功出栈
* @return false 栈空,出栈失败
*/
bool Pop(char* stack, int* top, char *c)
{
bool ret = false;
if (*top <= 0)
{
ret = false;
}
else
{
*c = stack[--(*top)];
ret = true;
}
return ret;
}
/**
* @brief 判断是否为左符号
*
* @param ch 字符
* @return true 是左符号
* @return false 不是左符号
*/
bool isLeftChar(char ch)
{
return ch == '(' || ch == '{' || ch == '[';
}
/**
* @brief 判断是否为右符号
*
* @param ch 字符
* @return true 是右符号
* @return false 不是右符号
*/
bool isRightChar(char ch)
{
return ch == ')' || ch == '}' || ch == ']';
}
/**
* @brief 判断是否为左注释符号
*
* @param ch 字符
* @param nextCh 下一个字符
* @return true 是左注释符号
* @return false 不是左注释符号
*/
bool isLeftCommentChar(char ch, char nextCh)
{
return ch == '/' && nextCh == '*';
}
/**
* @brief 判断是否为右注释符号
*
* @param ch 字符
* @param nextCh 下一个字符
* @return true 是右注释符号
* @return false 不是右注释符号
*/
bool isRightCommentChar(char ch, char nextCh)
{
return ch == '*' && nextCh == '/';
}
/**
* @brief 判断左右符号是否匹配
*
* @param leftCh 左符号
* @param rightCh 右符号
* @return true 匹配
* @return false 不匹配
*/
bool isMatch(char leftCh, char rightCh)
{
bool ret = false;
if (leftCh == '(' && rightCh == ')')
{
ret = true;
}
else if (leftCh == '{' && rightCh == '}')
{
ret = true;
}
else if (leftCh == '[' && rightCh == ']')
{
ret = true;
}
else if (leftCh == '/' + '*' && rightCh == '*' + '/')
{
ret = true;
}
return ret;
}