【C/C++】棧的應用—分隔符匹配算法

一、算法描述

首先需要提前知道的是,常見分隔符有{ }/* */,它們的使用是循環嵌套的,如果嵌套多層,那麼左分隔符將會一直壓棧,直到遇到第一個右分隔符。

如果分隔符是匹配的,那麼棧頂的左分隔符,就是與之匹配的。例如{[()]},左分隔符入棧,棧頂是’(’,那麼遇到的第一個右分隔符就是’)’,如果不是就匹配失敗。

算法描述:

(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


  1. 如果對您有幫助可以點個贊或關注,將會是我最大的動力 ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章