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輸出經(jīng)典的hello,world:
+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]<.#>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[
<++++>-]<+.[-]++++++++++.
用剛生成的bf語言解釋器運行它:
dp@dp:~ % ./bfi hello.b
Hello World!
prime.b完成指定整數(shù)內(nèi)質(zhì)數(shù)的計算:
===================================================================
======================== 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函數(shù)以只讀方式打開BF語言的源代碼文件,然后,將BF源文件按字節(jié)逐個拷入數(shù)組f中,并在最后加上字符串的結(jié)束標志0,最后,以數(shù)組f為參數(shù),調(diào)用interpret函數(shù)解釋執(zhí)行BF語言源代碼。
if((z=fopen(argv[1],“r”))) {
while( (b=getc(z))>0 )
*s++=b;
*s=0;
interpret(f);
}
2、BF語言的解釋器以數(shù)組為數(shù)據(jù)中心進行計算,在它的計算模型中,需要一個指向數(shù)組的指針,通過這個指針的移動以及對指針指向內(nèi)容的操作完成所有的計算。因此,程序在開頭處聲明了解釋器的核心:數(shù)組a與f,數(shù)據(jù)a存放BF指令所操作的數(shù)據(jù),數(shù)組f存放BF語言代碼文件,同時聲明指針變量s指向f數(shù)組的第一個元素。
char a[5000], f[5000], b, o, *s=f;
3、interpret函數(shù)解析
這個函數(shù)是實現(xiàn)BF語言解釋執(zhí)行的關(guān)鍵。interpret函數(shù)接受數(shù)組指針c(指存放向BF語言源代碼的數(shù)組),然后通過while語句逐個字符提取BF源代碼(因為BF源代碼中每個字符就是一條指令),通過swith…case…語句塊判斷BF指令(<、>、+、-、.、,、[、]),執(zhí)行BF指令。
這些指令分為非跳轉(zhuǎn)指令與跳轉(zhuǎn)指令:
(1)非跳轉(zhuǎn)指令完成了除循環(huán)外的其它功能。比如移動指針(指針指變量p,比如代碼中的“ p–”以及“p++”)、對數(shù)組(數(shù)組指變量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)跳轉(zhuǎn)指令完成了循環(huán)功能。在循環(huán)指令的解釋執(zhí)行過程中,使用了遞歸機制完成了BF語言的“[”與”]” 指令的解釋,“[”標示著一段循環(huán)的開始,而“]”標示著一段循環(huán)的結(jié)束,這意味著循環(huán)可以嵌套,可以由多個“[”與”]” 指令組成多層循環(huán)。
[
如果指針指向的單元值為零,向后跳轉(zhuǎn)到對應(yīng)的]指令的次一指令處
]
如果指針指向的單元值不為零,向前跳轉(zhuǎn)到對應(yīng)的[指令的次一指令處
因為可能存在多種循環(huán),所以必須找到本次循環(huán)開始的“[”對應(yīng)的“]”處,循環(huán)的條件通過指針指向的單元值來決定,只要指針指向的內(nèi)容為0,則循環(huán)結(jié)束,否則循環(huán)繼續(xù)。
通過下面這段語句,完成對應(yīng)“[”的“]”的查找,尋找的過程中,更新下一步要執(zhí)行的BF指令指針(for循環(huán)語句中的“c++”):
for( b=1,d=c; b && *c; c++ )
b+=c==’[’, b-=c==’]’;
找到循環(huán)的結(jié)束處后,對指針指向的單元值( 下面代碼中的“a[p]”)進行判斷,只要單元值不為0,則遞歸調(diào)用interpret函數(shù)進行下一條指令的解釋:
while( a[p] )
interpret(d);
為防止循環(huán)的符號不對應(yīng),比如說,最后多了循環(huán)結(jié)束標志”]”,則出現(xiàn)了異常,程序非正常退出,如下面代碼所示:
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);
.................................總結(jié)
以上是生活随笔為你收集整理的C指针原理(41)-递归(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Websocket判断逻辑Bug
- 下一篇: mockjs语法规范、设置mockjs拦