《數據結構和算法》之符號匹配性檢測

一,問題描述:

        在C語言中有一些符號是成對出現的,括號:(),【】,{},《》,<>;引號:“”,‘’;等都是成對出現,其在C語言中是無處不在的,幾乎所有的編譯器都具有語法檢查的能力,其中有一項就是括號的匹配性檢測,意思就是對應於左括號出現的時候就一定會有對應的右括號的匹配性檢測。如何實現編譯器中的符號成對檢測呢?

二,問題分析:

        可能猛的看到這個題目都不知道要怎麼做,但仔細分析之後可以發現可以從以下這個思路來進行解答:

        1,從第一個字符開始掃描,當遇見普通字符時忽略,當遇見左符號時壓入棧中;

        2,當遇見右符號時就從棧中彈出棧頂符號進行匹配,如果匹配成功則繼續讀入下一個字符,如果匹配失敗,可以立即停止並且報錯;

        3,成功時:這個時候所有字符掃描完畢,且棧爲空。

              失敗時:匹配失敗或者所有字符掃描完畢但棧非空。

       舉例:

           

void f(int a[])
{
     int (*p)[5];

     p= NULL;
}

       首先,從v開始掃描,屬於普通字符,一直掃描直到‘(’被掃描,此時將左符號壓入棧中,接着繼續掃描,又掃描到‘[’的時候遇到左符號,此時將該左符號壓入棧中,繼續掃描則遇到‘]’,此時‘[]’匹配成功,則這個兩個符號從棧中彈出,再繼續掃描,遇到‘)’,則剛好與之前的‘(’相匹配,此時“(”出棧,繼續掃描,遇到‘{’,入棧,再接着‘(’又入棧,繼續掃描直到‘)’此時匹配,出棧,繼續掃描遇到‘[’入棧,繼續遇到‘]’,又匹配成功,出棧;這樣一直匹配到最後遇到‘}’,出棧,匹配成功,此時棧爲空,最後掃描結束。

三,算法框架設計

       

int scanner(const char* code)
{
	LinkStack* stack = LinkStack_Create();//創建棧S; 
	int ret = 0;
	int i = 0;
	
	while( code[i] != '\0')
	{
	    if(isLeft(code[i]))	   //code[i]爲左括號 
	    {
		    LinkStack_Push(stack,(void*)(code + i));  //將code[i]出棧	
		}
		
		if(isRight(code[i]))    //code[i]爲右括號 
		{
		   char* c = (char*)LinkStack_Pop(stack);      //將code[i]入棧 
		   
		   if((c == NULL) || !match(*c,code[i]))    //如果c與code[i]不匹配 
		   {
		        printf("%c does not match!\n",code[i]);     //此時報錯 
				break;		                                //停止循環 
		   }	
		}
		i++;
	}
	
	if((LinkStack_Size(stack)==0)&&(code[i]=='\0'))
	{
	       printf("Succeed!\n");                //如果滿足if裏面的條件則匹配成功 
		   ret = 1;
	}
	else
	{
	       printf("Invalid code!\n");         //如果不滿足那些條件則匹配失敗,報錯 
		   ret = 0;	
	}
	LinkStack_Destroy(stack);                   //銷燬棧,釋放內存 
    return ret;
}
            scanner算法的過程正如上述代碼所示,首先要創建一個棧,按照上面二中的思路進行編寫。判斷左符號和右符號以及匹配函數均如下所示:

            左符號判斷函數:

int isLeft(char c)
{
	int ret = 0;
	 switch(c)
	 {
	    case '<':
		case '(':
		case '[':
		case '{':
		case '\'':
		case '\"':
			ret = 1;
			break;
		default:
			ret = 0;
			break;
				
	  }
	  return ret;
}
            右符號判斷函數:    

int isRight(char c)
{
	int ret = 0;
	 switch(c)
	 {
	    case '>':
		case ')':
		case ']':
		case '}':
		case '\'':
		case '\"':
			ret = 1;
			break;
		default:
			ret = 0;
			break;
				
	  }
	  return ret;
}
               匹配函數:

int match(char left, char right)
{
	int ret = 0;
	
	switch(left)
	{
	    case '<':
			ret = (right == '>');
			break;
		case '(':
			ret = (right == ')');
			break;
		case '[':
			ret = (right == ']');
			break;
		case '{':
			ret = (right == '}');
			break;
		case '\'':
			ret = (right == '\'');
			break;
		case '\"':
		    ret = (right == '\"');
			break;
		default:
			ret = 0;
			break;	
	}
}
四,總的測試代碼

            

#include <stdio.h>
#include <stdlib.h>
#include "LinkStack.h"

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int isLeft(char c)
{
	int ret = 0;
	 switch(c)
	 {
	    case '<':
		case '(':
		case '[':
		case '{':
		case '\'':
		case '\"':
			ret = 1;
			break;
		default:
			ret = 0;
			break;
				
	  }
	  return ret;
}

int isRight(char c)
{
	int ret = 0;
	 switch(c)
	 {
	    case '>':
		case ')':
		case ']':
		case '}':
		case '\'':
		case '\"':
			ret = 1;
			break;
		default:
			ret = 0;
			break;
				
	  }
	  return ret;
}
int match(char left, char right)
{
	int ret = 0;
	
	switch(left)
	{
	    case '<':
			ret = (right == '>');
			break;
		case '(':
			ret = (right == ')');
			break;
		case '[':
			ret = (right == ']');
			break;
		case '{':
			ret = (right == '}');
			break;
		case '\'':
			ret = (right == '\'');
			break;
		case '\"':
		    ret = (right == '\"');
			break;
		default:
			ret = 0;
			break;	
	}
}
int scanner(const char* code)
{
	LinkStack* stack = LinkStack_Create();//創建棧S; 
	int ret = 0;
	int i = 0;
	
	while( code[i] != '\0')
	{
	    if(isLeft(code[i]))	   //code[i]爲左括號 
	    {
		    LinkStack_Push(stack,(void*)(code + i));  //將code[i]出棧	
		}
		
		if(isRight(code[i]))    //code[i]爲右括號 
		{
		   char* c = (char*)LinkStack_Pop(stack);      //將code[i]入棧 
		   
		   if((c == NULL) || !match(*c,code[i]))    //如果c與code[i]不匹配 
		   {
		        printf("%c does not match!\n",code[i]);     //此時報錯 
				break;		                                //停止循環 
		   }	
		}
		i++;
	}
	
	if((LinkStack_Size(stack)==0)&&(code[i]=='\0'))
	{
	       printf("Succeed!\n");                //如果滿足if裏面的條件則匹配成功 
		   ret = 1;
	}
	else
	{
	       printf("Invalid code!\n");         //如果不滿足那些條件則匹配失敗,報錯 
		   ret = 0;	
	}
	LinkStack_Destroy(stack);                   //銷燬棧,釋放內存 
    return ret;
}

int main(int argc, char *argv[])
{
	const char* code = "void fint a[]) {int (*p)[5]; p = NULL;}";
	
	scanner(code);
	return 0;
}
              在輸入"void fint a[]) {int (*p)[5]; p = NULL;}"字符串的時候會出現圖1結果

                                             

                                                                                                                             圖1  結果不成功的現象截圖 

               在輸入"void f(int a[]) {int (*p)[5]; p = NULL;}"的時候會出現圖2結果:

                                               

                                                                                                                             圖2 結果成功的截圖

                                                   

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