一、算法描述
首先需要提前知道的是,常見分隔符有{ }/* */,它們的使用是循環嵌套的,如果嵌套多層,那麼左分隔符將會一直壓棧,直到遇到第一個右分隔符。
如果分隔符是匹配的,那麼棧頂的左分隔符,就是與之匹配的。例如{[()]},左分隔符入棧,棧頂是’(’,那麼遇到的第一個右分隔符就是’)’,如果不是就匹配失敗。
算法描述:
(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。
如果對您有幫助可以點個贊或關注,將會是我最大的動力 ↩︎