一、算法描述
首先需要提前知道的是,常见分隔符有{ }/* */,它们的使用是循环嵌套的,如果嵌套多层,那么左分隔符将会一直压栈,直到遇到第一个右分隔符。
如果分隔符是匹配的,那么栈顶的左分隔符,就是与之匹配的。例如{[()]},左分隔符入栈,栈顶是’(’,那么遇到的第一个右分隔符就是’)’,如果不是就匹配失败。
算法描述:
(1)从左到右读取字符,每次读取一个字符,若判定为是左分割符,则将它压入栈;
(2)当读取到一个右分割符时,则弹出栈顶 的左分隔符,并判定它是否和此右分隔符匹配,若它们不匹配,则匹配失败,函数返回false;
(3)若栈一直存在没有被弹出的左分隔符,即左分隔符多余,则匹配失败,函数返回false;
(4)若所有的字符都匹配,那么栈顶一直弹出,直到栈为空。等到读入结束后,栈就为空,则表示匹配成功,函数返回true即只有当栈为空才返回true,其他情况均不匹配,返回false
二、 实现代码
#include <iostream>
#include <stack>
using namespace std;
bool delimiterMatching(char* file);//定义判断分隔符是否匹配的函数
int main()
{
char fileName[50];//定义字符数组
cout << "Enter a statement (Ex. s=t[5]+x/(m*(n+y)); : ";
cin >> fileName;
if (delimiterMatching(fileName))//将fileName传入delimiterMatching函数
cout << endl << "Matching success." << endl;
else
cout << endl << "Matching failure." << endl;
}
bool delimiterMatching(char* file)
{
stack<char> var;//定义一个栈
int counter = 0;//计数
char ch, temp, popd;//ch储存字符的变量,temp暂时储存字符的变量,popd暂时储存栈顶部元素
do {
ch = file[counter];//file的第一个字符
if (ch == '(' || ch == '[' || ch == '{')//如果该字符为左分隔符
{
var.push(ch);//将ch压入栈
}
else if (ch == '/')//如果该字符为左分隔符
{
temp = file[counter + 1];//获取‘/’的下一个字符
if (temp == '*')//下一个字符为‘*’,就是注释,需要寻找匹配
{
var.push(ch);//将‘/’压入栈
counter++;
}
else//如果是其他的字符,不压栈
{
counter++;//下一个字符
continue;//回到循环开始
}
}
else if (ch == ')' || ch == ']' || ch == '}') //如果该字符为右分隔符
{
popd = var.top();//返回栈顶部元素
var.pop();//栈顶部元素出栈,栈中元素-1
if ((ch == ')' && popd != '(') || (ch == ']' && popd != '[') || (ch == '}' && popd != '{'))//如果ch和弹出的分隔符不匹配,就报告错误
return false;
}
else if (ch == '*')//如果该字符为右分隔符
{
temp = file[counter + 1];//获取下一个字符
popd = var.top();//返回栈顶部的元素
var.pop();//栈顶部元素出栈
if (temp == '/')//如果下一个字符为‘/’,则为注释的后半部分,需要寻找匹配
{
if (popd == '/')//如果匹配成功
{
counter++;//下一个字符
continue;//回到循环开始
}
else//匹配不成功,报告错误
{
return false;
break;
}
}
else//不是则重新循环 - 为*运算符
{
var.push(popd);//归还出栈的顶部元素
counter++;//下一个字符
continue;//回到循环开始
}
}
counter++;//字符不符合以上要求跳过,进行下一个字符的判断
} while (ch != '\0');//当遇到空字符,终止循环
if (var.empty())//如果栈为空,则正确匹配,返回true
return true;
else
return false;
}
需要注意的是:对于有多种用处的字符,需要对其进行额外的判断,例如:*和/,既可以是算术运算符,也可以是注释里的符号。因此上面的判断函数中,就判断其是不是注释的分隔符,如果不是就跳过,因为运算符不是分隔符。
三、运行效果
如有不足之处,还望指正 1。
如果对您有帮助可以点个赞或关注,将会是我最大的动力 ↩︎