編譯原理字元串長度
1. 急求:編譯原理判斷文法類型的C語言源代碼!!!!!!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/**//*全局變數定義*/
char inputString[10]; /**//*用來存儲用戶輸入的字元串,最長為20個字元*/
char stack[10]; /**//*用來進行語法分析的棧結構*/
int base=0; /**//*棧底指針*/
int top=1; /**//*棧頂指針*/
char VT[4]={'a','d','b','e'}; /**//*用來存放5個終結符*/
char chanShengShi[10]; /**//*用來存放預測分析表M[A,a]中的一條產生式*/
int firstCharIntex=0; /**//*如果a匹配產生式,則每次firstCharIntex 自增 1 */
/**//*firstCharIntex用來存放用戶輸入串的第一個元素的下標*/
/**//*自定義函數聲明*/
char pop() ; /**//*彈出棧頂元素*/
int push(char) ; /**//*向棧內添加一個元素,成功返回1,若棧已滿則返回0*/
int search(char temp) ; /**//*查找非終結符集合VT中是否存在變數temp,存在返回1,不存在返回0*/
int M(char A, char a) ; /**//* 若預測分析表M[A,a]中存在產生式,
則將該產生式賦給字元數組chanShengShi[10],並返回 1,
若M[A,a]中無定義產生式則返回 0
*/
void init() ; /**//*初始化數組inputString[10] 、棧 stack[10] 和 chanShengShi[10]*/
int yuCeFenXi() ; /**//* 進行輸入串的預測分析的主功能函數,
若輸入串滿足文法則返回 1,不滿足則返回0
*/
void printStack(); /**//*列印棧內元素 */
void printinputString(); /**//*列印用戶輸入串 */
/**//*進入主函數*/
void main()
{
system("cls");
yuCeFenXi(); /**//*調用語法預測分析函數*/
system("pause");
}
/**//*函數的定義*/
int yuCeFenXi()
{
char X; /**//*X變數存儲每次彈出的棧頂元素*/
char a; /**//*a變數存儲用戶輸入串的第一個元素*/
int i;
int counter=1; /**//*該變數記錄語法分析的步驟數*/
init(); /**//*初始化數組*/
printf("wen fa : \n"); /**//*輸出文法做為提示*/
printf("S -> aH \n");
printf("H -> aMd | d \n");
printf("M -> Ab | \n");
printf("A -> aM | e \n");
printf("\ninput string ,'#' is a end sign !!(aaabd#) \n"); /**//*提示用戶輸入將要測試的字元串*/
scanf("%s",inputString);
push('#');
push('S');
printf("\nCounter-----Stack---------------Input string \n"); /**//*輸出結果提示語句*/
while(1) /**//*while循環為語法分析主功能語句塊*/
{
printf(" ");
printf(" %d",counter); /**//*輸出分析步驟數*/
printf(" "); /**//*輸出格式控制語句*/
printStack(); /**//*輸出當前棧內所有元素*/
X=pop(); /**//*彈出棧頂元素賦給變數X*/
printinputString(); /**//*輸出當前用戶輸入的字元串*/
if( search(X)==0 ) /**//*在終結符集合VT中查找變數X的值,存在返回 1,否則返回 0*/
{
if(X == '#') /**//*棧已經彈空,語法分析結果正確,返回 1*/
{
printf("success \n"); /**//*語法分析結束,輸入字元串符合文法定義*/
return 1;
}
else
{
a = inputString[firstCharIntex];
if( M(X,a)==1 ) /**//*查看預測分析表M[A,a]是否存在產生式,存在返回1,不存在返回0*/
{
for(i=0;i<10;i++) /**//* '$'為產生式的結束符,for循環找出該產生式的最後一個元素的下標*/
{
if( chanShengShi[i]=='$' ) break;
}
i-- ; /**//*因為 '$' 不是產生式,只是一個產生式的結束標志,所以i自減1*/
while(i>=0)
{
push( chanShengShi[i] ); /**//*將當前產生式逆序壓入棧內*/
i-- ;
}
}
else
{
printf(" error(1) !!\n"); /**//*若預測分析表M[A,a]不存在產生式,說明語法錯誤*/
return 0;
}
}
}
else /**//*說明X為終結符*/
{
if( X==inputString[firstCharIntex] ) /**//*如果X等於a,說明a匹配*/
{
firstCharIntex++; /**//*輸入串的第一個元素被約去,下一個元素成為新的頭元素*/
}
else
{
printf(" error(2) !! \n");
return 0;
}
}
counter++;
}
}
void init()
{
int i;
for(i=0;i<10;i++)
{
inputString[i]=NULL; /**//*初始化數組inputString[10] */
stack[i]=NULL; /**//*初始化棧stack[10] */
chanShengShi[i]=NULL; /**//*初始化數組chanShengShi[10]*/
}
}
int M(char A, char a) /**//*文法定義因實際情況而定,該文法為課本例題的文法*/
{ /**//*該函數模擬預測分析表中的二維數組 */
if( A=='S'&& a=='a' ) { strcpy(&chanShengShi[0],"aH$"); return 1; }
if( A=='H'&& a=='a' ) { strcpy(&chanShengShi[0],"aMd$"); return 1; }
if( A=='H'&& a=='d' ) { strcpy(&chanShengShi[0],"d$"); return 1; }
if( A=='M'&& a=='a' ) { strcpy(&chanShengShi[0],"Ab$"); return 1; }
if( A=='M'&& a=='d' ) { strcpy(&chanShengShi[0],"$"); return 1; }
if( A=='M'&& a=='b' ) { strcpy(&chanShengShi[0],"$"); return 1; }
if( A=='M'&& a=='e' ) { strcpy(&chanShengShi[0],"Ab$"); return 1; }
if( A=='A'&& a=='a' ) { strcpy(&chanShengShi[0],"aM$"); return 1; }
if( A=='A'&& a=='e' ) { strcpy(&chanShengShi[0],"e$"); return 1; }
else return 0; /**//*沒有定義產生式則返回0*/
}
char pop() /**//*彈出棧頂元素,用topChar返回*/
{
char topChar;
topChar=stack[--top];
return topChar;
}
int push(char ch)
{
if( top>9 )
{
printf(" error : stack overflow "); /**//*棧空間溢出*/
return 0;
}
else
{
stack[top]=ch; /**//*給棧頂空間賦值*/
top++;
return 1;
}
}
int search(char temp)
{
int i,flag=0; /**//*flag變數做為標志,若找到temp則賦1,否則賦0*/
for(i=0;i<4;i++)
{
if( temp==VT[i] ) /**//*終結符集合中存在temp*/
{
flag=1;
break;
}
}
if(flag==1) return 1; /**//*flag==1說明已找到等於temp的元素*/
else return 0;
}
void printStack() /**//*輸出棧內內容*/
{
int temp;
for(temp=1;temp<top;temp++)
{
printf("%c",stack[temp]);
}
}
void printinputString() /**//*輸出用戶輸入的字元串*/
{
int temp=firstCharIntex ;
printf(" "); /**//*該句控制輸出格式*/
do{
printf("%c",inputString[temp]);
temp++;
}while(inputString[temp-1]!='#');
printf(" \n");
}
2. 請問編譯原理中a(a|b)*a和aa*b*a有什麼區別,謝謝。
涉及到一個優先序問題,前一個正則式接受兩個a之間有0長度或任意長度的{a,b}字元串序列,而後一個正則式則只允許兩個a之間有的{a,b}序列必須滿足:如果a、b同時存在,則a必須在b前面,也就是只接受左右兩端全是a,只有中間是b這種夾心餅乾的形式。舉個栗子你就明白了:
a(a|b)*a可以接受的輸入序列有:aa aaa aba abba aaba abaa
aa*b*a 可以接受的輸入序列有:aa aaa aaba aba aaabba 不能接受abaa
3. C語言編譯原理是什麼
編譯共分為四個階段:預處理階段、編譯階段、匯編階段、鏈接階段。
1、預處理階段:
主要工作是將頭文件插入到所寫的代碼中,生成擴展名為「.i」的文件替換原來的擴展名為「.c」的文件,但是原來的文件仍然保留,只是執行過程中的實際文件發生了改變。(這里所說的替換並不是指原來的文件被刪除)
2、匯編階段:
插入匯編語言程序,將代碼翻譯成匯編語言。編譯器首先要檢查代碼的規范性、是否有語法錯誤等,以確定代碼的實際要做的工作,在檢查無誤後,編譯器把代碼翻譯成匯編語言,同時將擴展名為「.i」的文件翻譯成擴展名為「.s」的文件。
3、編譯階段:
將匯編語言翻譯成機器語言指令,並將指令打包封存成可重定位目標程序的格式,將擴展名為「.s」的文件翻譯成擴展名為「.o」的二進制文件。
4、鏈接階段:
在示例代碼中,改代碼文件調用了標准庫中printf函數。而printf函數的實際存儲位置是一個單獨編譯的目標文件(編譯的結果也是擴展名為「.o」的文件),所以此時主函數調用的時候,需要將該文件(即printf函數所在的編譯文件)與hello
world文件整合到一起,此時鏈接器就可以大顯神通了,將兩個文件合並後生成一個可執行目標文件。
4. 【編譯原理】詞法分析
詞法分析是編譯原理中的一個重要步驟,其主要目的是將源代碼中的字元序列轉換成有意義的詞法單元序列。以下是關於詞法分析的一些關鍵點:
正則表達式:
- 定義:正則表達式是用於描述字元串集合的一種簡潔工具,特別適用於表示編程語言中的詞法規則。
- 作用:在詞法分析中,正則表達式用於定義詞法單元的模式,例如標識符、關鍵字、運算符等。
自動機:
- NFA:一個狀態可以通過一個輸入符號有多條路徑到達另一個狀態。在詞法分析中,NFA可以用於表示正則表達式的匹配過程。
- DFA:DFA是NFA的一種特例,其中每個狀態對於每個輸入符號都有唯一的轉移規則。DFA通常用於編譯器的詞法分析,因為它可以更有效地進行字元串匹配。
從正則表達式到自動機的轉換:
- 過程:詞法分析器通常需要將正則表達式轉換為自動機,以便高效地解析輸入字元串。
- 實現:這個過程可能涉及將正則表達式轉換為NFA,然後通過合並等價狀態將NFA轉換為DFA。
字元串匹配:
- 目的:在詞法分析中,字元串匹配是指將輸入字元串與自動機中的狀態進行匹配,以確定輸入字元串是否符合定義的詞法規則。
- 演算法:KMP演算法是一種高效的字元串匹配演算法,它結合了自動機的復雜結構與字元串匹配演算法的優點,通過預計算的NEXT數組優化了匹配過程。
詞法分析器的實現:
- 數據結構:詞法分析器的實現可能涉及使用數據結構來保存狀態轉換信息。
- 復雜度分析:詞法分析器的性能通常與輸入字元串的長度和自動機的狀態數相關,因此需要進行復雜度分析以確保其效率。
綜上所述,詞法分析是編譯原理中的一個關鍵步驟,它涉及正則表達式的定義、自動機的轉換、字元串匹配以及詞法分析器的實現等多個方面。