C指针原理(41)-递归(2)
編譯:
dp@dp:~ % gcc bfi.c -o bfi
bfi.c: In function ‘interpret’:
bfi.c:35: warning: incompatible implicit declaration of built-in function ‘exit’
bfi.c:40: warning: incompatible implicit declaration of built-in function ‘exit’
dp@dp:~ %
下面的hello.b輸出經典的hello,world:
+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]<.#>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[
<++++>-]<+.[-]++++++++++.
用剛生成的bf語言解釋器運行它:
dp@dp:~ % ./bfi hello.b
Hello World!
prime.b完成指定整數內質數的計算:
===================================================================
======================== OUTPUT STRING ============================
===================================================================
++++++++[<++++++++>-]<++++++++++++++++.[-]++++++++++[<++++++++++>-]<++++++++++++++.[-]++++++++++[<++++++++++>-]<+++++.[-]++++++++++[<++++++++++>-]<+++++++++.[-]++++++++++[<++++++++++>-]<+.[-]++++++++++[<++++++++++>-]<+++++++++++++++.[-]+++++[<+++++>-]<+++++++.[-]++++++++++[<++++++++++>-]<+++++++++++++++++.[-]++++++++++[<++++++++++>-]<++++++++++++.[-]+++++[<+++++>-]<+++++++.[-]++++++++++[<++++++++++>-]<++++++++++++++++.[-]++++++++++[<++++++++++>-]<+++++++++++.[-]+++++++[<+++++++>-]<+++++++++.[-]+++++[<+++++>-]<+++++++.[-]===================================================================
======================== INPUT NUMBER ============================
===================================================================
- cont=1
[
- cont=0
,
SUB10
[ not 10
<+> cont=1
=SUB38==
=MUL10===
[>+>+<<-]>>[<<+>>-]< dup
+++++++++
[
<<<
[>+>+<<-]>>[<<+>>-]< dup
[<<+>>-]
]
<<<[-]<
RMOVE1
<
[>+<-]
]
<
]
[<<+>>-]<<===================================================================
======================= PROCESS NUMBER ===========================
===================================================================
==== ==== ==== ====
numd numu teid teiu
==== ==== ==== ====
+<-[
DUP
[>+>+<<-]>>[<<+>>-]<
+<–
+<<<<<<<< isprime=1
[
<-
=DUP3=
<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<<<
=DUP2=
[>>+>+<<<-]>>>[<<<+>>>-]<<< <
DIVIDES===
[>+>+<<-]>>[<<+>>-]< DUP i=div
<<
[
>>>>>+ bool=1<<<[>+>+<<-]>>[<<+>>-]< DUP[>>[-]<<-] IF i THEN bool=0>>[ IF i=0<<<<[>+>+<<-]>>[<<+>>-]< i=div>>>- bool=0]<<<- DEC i<<-]
+>>[<<[-]>>-]<<
[-]< CLR div
=END DIVIDES
[>>>>>>[-]<<<<<<-] if divides then isprime=0
<<
[-]>[-]<<<
]
[
<<<<<<<[-]<<
[>>+>+<<<-]>>>[<<<+>>>-]<<<
===================================================================
======================== OUTPUT NUMBER ===========================
===================================================================
[>+<-]>
[
DUP
[>+>+<<-]>>[<<+>>-]<
==MOD10
+++++++++<
[
>>>+<< bool= 1[>+>[-]<<-] bool= ten==0>[<+>-] ten = tmp>[<<++++++++++>>-] if ten=0 ten=10<<- dec ten <- dec num]
+++++++++ num=9
[<->-]< dec num by ten
=RROT
[>+<-]< [>+<-]
< [>+<-]
[<<<+>>>-]
<
=DIV10==
+++++++++<
[
>>>+<< bool= 1[>+>[-]<<-] bool= ten==0>[<+>-] ten = tmp>[<<++++++++++>>>+<-] if ten=0 ten=10 inc div<<- dec ten <- dec num]
[<<<<+>>>>-]<<<< copy div to num
[-]< clear ten
=INC1===
<+>
]
<
[
=MOVER===
[>+<-]
=ADD48==
+++++++[<+++++++>-]<->
=PUTC=
<.[-]>
MOVEL2==
[<<+>>-]<
<-
]
++++[<++++++++>-]<.[-]
===================================================================
=========================== END FOR ===============================
===================================================================
]
<<<<<<<<
[-]<
[-]
<<-
]
LF==
++++++++++.[-]
用剛編譯生成的bf語言解釋器運行它:
dp@dp:~ % ./bfi prime.b
Primes up to: 20
2 3 5 7 11 13 17 19
BF解釋器分析:
1、main函數以只讀方式打開BF語言的源代碼文件,然后,將BF源文件按字節逐個拷入數組f中,并在最后加上字符串的結束標志0,最后,以數組f為參數,調用interpret函數解釋執行BF語言源代碼。
if((z=fopen(argv[1],“r”))) {
while( (b=getc(z))>0 )
*s++=b;
*s=0;
interpret(f);
}
2、BF語言的解釋器以數組為數據中心進行計算,在它的計算模型中,需要一個指向數組的指針,通過這個指針的移動以及對指針指向內容的操作完成所有的計算。因此,程序在開頭處聲明了解釋器的核心:數組a與f,數據a存放BF指令所操作的數據,數組f存放BF語言代碼文件,同時聲明指針變量s指向f數組的第一個元素。
char a[5000], f[5000], b, o, *s=f;
3、interpret函數解析
這個函數是實現BF語言解釋執行的關鍵。interpret函數接受數組指針c(指存放向BF語言源代碼的數組),然后通過while語句逐個字符提取BF源代碼(因為BF源代碼中每個字符就是一條指令),通過swith…case…語句塊判斷BF指令(<、>、+、-、.、,、[、]),執行BF指令。
這些指令分為非跳轉指令與跳轉指令:
(1)非跳轉指令完成了除循環外的其它功能。比如移動指針(指針指變量p,比如代碼中的“ p–”以及“p++”)、對數組(數組指變量a,比如代碼中的“a[p]++”以及“a[p]–”)的操作、輸出(代碼中的“putchar(a[p]); fflush(stdout); break;”)和輸入(代碼中的“case ‘,’”標示的語句塊)。
void interpret(char *c)
{
char *d; int tmp;
r++;
while( *c ) {
//if(strchr("<>+-,.[]\n",c))printf("%c",c);switch(o=1,*c++) {case '<': p--; break;case '>': p++; break;case '+': a[p]++; break;case '-': a[p]--; break;case '.': putchar(a[p]); fflush(stdout); break;case ',': tmp=getchar();if (tmp == EOF) a[p]=0; else a[p]=tmp;…
.................}
r–;
}
(2)跳轉指令完成了循環功能。在循環指令的解釋執行過程中,使用了遞歸機制完成了BF語言的“[”與”]” 指令的解釋,“[”標示著一段循環的開始,而“]”標示著一段循環的結束,這意味著循環可以嵌套,可以由多個“[”與”]” 指令組成多層循環。
[
如果指針指向的單元值為零,向后跳轉到對應的]指令的次一指令處
]
如果指針指向的單元值不為零,向前跳轉到對應的[指令的次一指令處
因為可能存在多種循環,所以必須找到本次循環開始的“[”對應的“]”處,循環的條件通過指針指向的單元值來決定,只要指針指向的內容為0,則循環結束,否則循環繼續。
通過下面這段語句,完成對應“[”的“]”的查找,尋找的過程中,更新下一步要執行的BF指令指針(for循環語句中的“c++”):
for( b=1,d=c; b && *c; c++ )
b+=c==’[’, b-=c==’]’;
找到循環的結束處后,對指針指向的單元值( 下面代碼中的“a[p]”)進行判斷,只要單元值不為0,則遞歸調用interpret函數進行下一條指令的解釋:
while( a[p] )
interpret(d);
為防止循環的符號不對應,比如說,最后多了循環結束標志”]”,則出現了異常,程序非正常退出,如下面代碼所示:
case ‘]’:
puts(“UNBALANCED BRACKETS”), exit(0);
對這2個指令的解釋的全部代碼如下:
void interpret(char *c)
{
char *d; int tmp;
r++;
while( *c ) {
............case '[':for( b=1,d=c; b && *c; c++ )
b+=c==’[’, b-=c==’]’;
if(!b) {
c[-1]=0;
while( a[p] )
interpret(d);
c[-1]=’]’;
break;
}
case ‘]’:
puts(“UNBALANCED BRACKETS”), exit(0);
.................................總結
以上是生活随笔為你收集整理的C指针原理(41)-递归(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Websocket判断逻辑Bug
- 下一篇: mockjs语法规范、设置mockjs拦