C指针原理(41)-递归
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C指针原理(41)-递归相关的知识,希望对你有一定的参考价值。
编译:
[email protected]:~?%?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‘
[email protected]:~?%?
下面的hello.b输出经典的hello,world:
+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]
<.#>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[
<++++>-]<+.[-]++++++++++.
用刚生成的bf语言解释器运行它:
[email protected]:~?%?./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语言解释器运行它:
[email protected]:~?%?./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("<>+-,.[] ",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)-递归的主要内容,如果未能解决你的问题,请参考以下文章