地址单元。当执行到CALL语句时,就调用子程序prod(),并把变量a、b、c的值传给变量x、y、z。在子程序prod()中如果变量的z值发生变化,则返回主程序中,变量c的值随之改变。
传值调用是把实际参数的值传递给对应的形式参数。它是把需要传送的实际参数的值复制到一个临时内存单元中,然后把该临时单元的地址传送给子程序。由于子程序没有访问实际参数的原始地址,因而不会改主原来参数的值,所有的变化都是在变量的副本上进行的。因此,在过程中无论形式参数如何改变,主程序中的实际参数不会受到影响。
当要求用变量按值传送时,可以先把变量变成一个表达式,例如把变量用括号括起来,如(a%)是一个表达式。
传值调用子程序的工作过程:
(1)计算出实际参数的值。
(2)子程序内使用的变量被定义为局部变量,在退出该子程序时即消失。与形式参数相对应的各变量按特殊的局部变量来处理。
(3)实际参数的值复制给子程序中对应的形式参数。
(4)继续执行子程序体中的语句。
(5)退出子程序,子程序中所有局部变量消失。返回到主程序中执行子程序调用语句的下一语句。
[例9-14] 阅读下面的程序,分析运行结果,理解传值调用。
主程序为:
EXAMPLE 14
DECLARE SUB prod(a!,b!,c!)
CLS
a=5:b=3
PRINT"主程序调用前的变量值a,b,c:",a,b,c
CALL prod((a),(b),(c))
PRINT "主程序调用后的变量值a,b,c",a,b,c
END
子程序为:
SUB prod(a,b,c)
PRINT "子程序中运算前的变量值a,b,c:",a,b,c
a=6:b=8
c=a*b
PRINT "子程序中运算后的变量值a,b,c:",a,b,c
END SUB
程序的运行结果为:
主程序调用前的变量值a,b,c: 5 3 0
子程序中运算前的变量值a,b,c: 5 3 0
子程序中运算后的变量值a,b,c: 6 8 48
主程序调用后的变量值a,b,c: 5 3 0
在子程序中即使与主程序中使用的变量名相同,但在内存中仍表示不同的内存单元地址。即执行子程序时使其变量内容发生变化,主程序中的变量内容并举随之改变。
在过程中以传值调用为主,如果希望把过程中的变量值返回主程序,才使用传址调用。
用传值调用这种传递参数的方法只能传递计算值,如数值、字符串、数值数组的值。
Quick BASIC的过程定义都是互相平行和孤立的,也就是说在定义过程时,一个过程内不能包含另一个过程。Quick BASIC虽然不能嵌套定义过程,但可以嵌套调用过程,也就是主程序可以调用子过程,在子过程中还可以调用另外的子过程,这种程序结构称为过程的嵌套。
[例9-15] 求组合数Cmn=
在程序中我们把求阶乘与求组合数公式分别定义为函数。
主程序为:
'EXAMPLE 15
DECLARE FUNCTIONcomb!(n!,m!)
DECLARE FUNCTION fact!(x!)
CLS
INPUT"n,m=";n,m
PRINT"C(";n;",";m;")=";comb(n,m)
END
自定义函数为(求组合数)
FUNCTION comb(n,m)
comb=fact(n)/(fact(m)*fact(n-m))
END FUNCTION
自定义函数为(求阶乘)
FUNCTION fact(x)
==1
FOR i=1 TO x
==p*i
NEXT i
fact=p
END FUNCTION
程序的运行结果为:
C(10,6)=210
在FUNCTION子过程comb中调用了FUNCTION子过程fact,从而形成过程的嵌套。
递归调用是指一个过程直接或间接调用自己本身即自己调用自己。在递归调用中,一个过程执行的某一步要用到它自身的上一步(或上几步)的结果。
Quick BASIC过程具有递归调用功能,递归调用在处理阶乘运算、级数运算、幂指数运算等方面特别有效。
[例9-16] 计算n!
根据数学知识,负数没有阶乘,0的阶乘为1,正整数n的阶乘为:
n×(n-1)×(n-2)×…×2×1
则可以用下式表示:

利用上式,把求n!转换为求n×(n-1)!。
上面的公式说明了每一循环的结果都有赖于上一循环的结果递归总有一个“结束条件”,如n!的结束条件为n=0。
在Quick BASIC中用递归过程实现这种运算的程序如下。
主程序
'EXAMPLE 16
DECLARE FUNCTION factorial#(n%)
CLS
DO
INPUT"请输入一个0~20之间的整数(-1结束):",num%
IF num%>=0 AND num%<=20 THEN
PRINT num%,factorial#(num%)
END IF
LOOP WHILE num%>=0
END
自定义函数为:
FUNCTION factorial#(n%)STATIC
IF n%>0 THEN
factorial#=1
END IF
END FUNCTION
当n%>0时,在过程factorial#中调factorial#过程,参数为n%-1,这种操作一直持续到n%=1为止。
例如,当n%=5时,求factorial#(5)的值变为求5×factorial#(4);求factorial#(4)的值又变为求4×factorial#(3),…,当n%=0时,factorial#的值为1,递归结束,其结果为5×4×3×2×1。如果把第一次调用过程factorial#叫做0级调用,以后每调用一次级别增加1,过程参数n%减1,则递归调用的过程如下:
递归级别 执行操作
0 factorial#(5)
1 factorial#(4)
2 factorial#(3)
3 factorial#(2)
4 factorial#(1)
4 返回1 factorial#(1)
3 返回2 factorial#(2)
2 返回6 factorial#(3)
1 返回24 factorial#(4)
0 返回120 factorial#(5)
当所编写的程序越来越长时,程序中所使用的变量也会越来越多。为了帮助用户管理大量的变量,Quick BASIC规定了一些特殊的规则处理过程中的变量。Quick BASIC将变量分为全程变量、局部变量和共享变量3类,这3类变量的作用域也各不相同。
在Quick BASIC中使用的变量,凡未经特殊说明的变量均属于局部变量(Local Verable),局部变量在主程序、子程序或函数中建立,但是只能在建立的过程内有效,即便是在主程序中建立的变量,也不能在子过程中使用。
局部变量不用任何语句说明。它的作用域仅限于它自己所在的过程,使用局部变量的程序比仅使用全程变量的程序更具有通用性。
[例9-17] 未经说明的局部变量示例。
主程序为:
'EXAMPLE 17
DECLARE SUB prod()
DECLARE SUB sum()
CLS
a=5:b=3
PRINT TAB(16);"a";TAB(30);"b";TAB(42);"c=a*6"
PRINT "调用prod前",a,b,c
CALL prod
PRINT"调用prod后",a,b,c
PRINT"调用sum前",a,b,c
CALL sum
PRINT"调用sum后",a,b,c
END
子程序为:
SUB prod
c=a*b
PRINT"prod子程序",a,b,c
END SUB
子程序为:
SUB sum
c=a+b
PRINT "sum子程序",a,b,c
END SUB
程序的运行结果为:
a b c=a*b
调用prod前 5 3 0
prod子程序 0 0 0
调用prod后 5 3 0
调用sum前 5 3 0
sum子程序 0 0 0
调用sum后 5 3 0
从上面程序的运行结果可以看出,主程序中的变量没有带到子程序中。
全程变量(Global Variable)是指在所有程序(包括主程序和过程)中都可以使用的内存变量。全程变量只能在主程序中定义,在主程序中用DIM、REDIM或COMMON语句中的SHARED短语定义全程变量属性;全程变量就像在一个程序中定义的变量一样,可以任意改变和调用,当过程执行完后,其值仍然保留,并带回主程序。
把变量定义为全程变量虽然很方便,但这样会增加变量在程序中被无意修改的机会,因此许多程序员不赞成在程序中使用全程变量。
另外,在主程序中用CONST语句定义的符号常量也是全程的,即在各过程中可以引用该符号常量。过程中用CONST定义的符号常量都是局部的,只能在该一个过程内引用。
在主程序中,可用DIM SHARED或REDIM SHARED语句把某些变量或数组定义为全程变量,使该变量在主程序及各过程中到处可以使用和修改。用DIM SHARED或REDIM SHARED语句说明变量后,要在后面程序或过程中对变量用赋值语句赋值。
[例9-18] 在主程序中用DIM SHARED语句来定义全程变量。
主程序为:
'EXAMPLE 18
DECLARE SUB prod()
DECLARE SUB sum()
CLS
DIM SHARED a,b,c
a=5:b=3
PRINT TAB(16);"a";TAB(30);"b";TAB(42);"c=a*b"
PRINT"调用prod前",a,b,c
CALL prod
PRINT"调用prod后",a,b,c
PRINT"调用sum前",a,b,c
CALL sum
PRINT"调用sum后",a,b,c
END
子程序为:
SUB prod
c=a*b
PRINT "prod子程序",a,b,c
END SUB
子程序为:
SUB sum
c=a+b
PRINT"sum子程序",a,b,c
END SUB
程序的运行结果为:
a b c=a*b
调用prod前 5 3 0
prod子程序 5 3 15
调用prod后 5 3 15
调用sum前 5 3 15
sum子程序 5 3 8
调用sum后 5 3 8
从程序的运行结果可以看出,在主程序中用DIM SHARED语句定义的全程变量a、b、c,把值带到了子程序中;返回主程序时,把修改后的值又带回了主程序。
在Quick BASIC中还有一种特殊的使用变量的方式,就是在主程序中不用DIM、REDIM或COMMON语句中的SHARED短语定义全程变量而在子程序中用SHARED语句来定义调用主程序中的同名变量,这种变量称共享变量(Sharing Variable)。用SHARED定义的变量可以在子过程中引用主程序中的变量,子过程中修改后的变量值也将带回主程序。
格式:
SHARED〈变量1〉[()][AS〈类型〉][,〈变量2〉[()][AS〈类型〉]]…
功能:定义过程中可以访问主程序中的变量。
说明:
(1)〈变量〉是主程序中的变量名,也就是本子过程与主程序共用的变量名,可以是简单变量或数组变量。
(2)〈类型〉用来定义对应〈变量〉的数据类型(INTEGER、LONG、SINGLE、DOUBLE、STRING或用户定义类型)。
(3)SHARED语句只能在SUB或FUNCTION过程使用。SHARED后面列出的变量必须是主程序中存在的变量。
[例9-19] 在子程序中用SHARED语句来定义共享变量。
主程序为:
'EXAMPLE 19
DECLARE SUB prod()
DECLARE SUB sum()
CLS
a=5:b=3
PRINT TAB(16);"a";TAB(30);"b";TAB(42);"c=a*b"
PRINT"调用prod前",a,b,c
CALL prod
PRINT"调用prod后",a,b,c
PRINT"调用sum前",a,b,c
CALL sum
PRINT"调用sum后",a,b,c
END
子程序为:
SUB prod
SHARED a,b,c
c=a*b
PRINT"prod子程序",a,b,c
END SUB
子程序为:
SUB sum
c=a+b
PRINT"sum子程序",a,b,c
END SUB
程序的运行结果为:
a b c=a*b
调用prod前 5 3 0
prod子程序 5 3 15
调用prod后 5 3 15
调用sum前 5 3 15
sum子程序 0 0 0
调用sum后 5 3 15
从程序的运行结果可以看出,在子程序prod中定义了共享主程序中的a、b、c变量,因此在子程序prod中可以引用和修改,返回主程序时也把修改后的变量值带回了主程序。子程序sum中的a、b、c没有特别说明,都是局部变量,也就无法引用主程序中的变量。
Quick BASIC的变量作用域规则:
(1)主程序中用DIM、REDIM或COMMON语句中的SHARED短语说明的变量是全程变量,任何SUB或FUNCTION都能调用这些变量。
(2)主程序中用CONST语句说明的符号常量全程符号常量。在SUB或FUNCTION中说明的符号常量是局部符号常量。
(3)如果一个变量未经任何说明,则这个变量是局部变量 ,它只能在建立这个变量的主程序或过程内使用。
(4)如果在一个过程内用STATIC语句说明一个全程变量名或者在一个过程内把全程变量当作形式参数,则这个全程变量名在这外过程中就作为局部变量。
(5)SHARED语句使主程序和子过程中同名变量成为共享变量。
比如子程序内部有一个变量,当程序运行进入该程序时,要分配给该变量一定的内存单元,一旦程序退出该过程,变量占有的内存单元是释放还是不释放?根据变量在程序运行期间的生命周期,Quick BASIC把变量分为静态变量(Static)和动态变量(Dynamic)。静态变量不释放内存单元,动态变量释放内存单元,因此有时就需要某些局部变量是静态变量,而其他变量仍然为动态变量。
所谓静态存储方式是指在程序运行期间分配固定的存储空间的方式。而动态存储方式则是在程序运行期间根据需要进行动态的分配存储空间的方式。
静态变量是指程序运行进入该变量所在的子程序,修改变量的值后,退出该子程序其值仍被保留,即变量所占内存单元没有释放。当以后再次进入该子程序,原来变量的值可以继