




已阅读5页,还剩44页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第六章函数和子程序,独立模块的子程序独立模块的函数局部变量与全局变量STATIC选项和说明过程的递归调用块内子程序和块内函数,模块化程序实际的思想,根据软件工程学的原理和结构化程序设计的要求,应该将程序分成若干个模块,每一个模块完成一个或几个功能,并给它定义一个唯一的名字,以便调用,这就是所谓的“模块化”。一个程序就包含一个主模块和若干个子模块。程序的每一个模块可以是子程序或函数。模块又称过程,“执行一个过程”就是调有一个子程序或函数模块。这种做法使程序结构清晰,具有良好的可读性和易维护性。,独立模块的子程序(引例),DECLARESUBstar(nASINTEGER)说明在程序中要调用一个名为Star的子程序REMmainprogramDIMIASINTEGERFORI=1TO3CALLStar(I)调用子程序,并将I的值传递给nNEXTIPRINTEND,SUBStar(nASINTEGER)DIMIASINTEGERFORI=1TOnPRINT“*”NEXTIPRINTENDSUB,独立模块的子程序,QBASIC提供独立模块的子程序和函数,这种子程序和主程序不在同一个模块中。它以SUB语句开头,以ENDSUB结束;SUB子程序名(形式参数)子程序体ENDSUB子程序名最长可为40个字符。我们约定子程序名第一个字母用大写,子程序后可以没有形参,此时必须省略括号,变为:SUB子程序名形参的类型说明如下:变量名1AS类型名,变量名2AS类型名,注:如果形参是实型,则AS语可以省略。SUB和ENDSUB之间的语句行称为子程序体,在子程序体内不可出现DATA语句,子程序体中的READ语句会到主程序体中的DATA语句中读取数据;子程序不能嵌套定义,即在子程序体内不能再出现SUB语句。,子程序的调用(CALL语句),子程序调用的两种形式:CALL子程序名(实际参数)子程序名实际参数实参的个数必须与所调用子程序中形参个数相同,实参和形参的类型必须按位置一一对应匹配,如果调用的子程序没有形参,则调用时子程序后面的一对括号必须省略,格式为:CALL子程序名或子程序名;实参可以是变量、常量、表达式;主程序DECLARE语句表示本程序中将用子程序,如果在主程序中要调用两个子程序,则应有两个DECLARE语句。如果调用的子程序没有形参,但DECLARE语句中子程序后的括号却不能少。DECLARE放在程序中所有可执行语句的前面。如果程序设计者未写DECLARE语句,则QBASIC会根据SUB语句所定义的子程序名和参数自动加上;DECLARE语句中括弧内参数的个数和类型与子程序形参的个数和类型一致。在子程序中还可以调用子程序,也可以调用它自身(递归调用)。,子程序的输入,在QBASIC环境下,无论在哪个编辑窗口,只要在新一行键入子程序的初始行,如:SUBStar(nASINTEGER),按回车键;如果已经输入主程序,将窗口Split,在其中的一个窗口中的主程序后键入子程序(该窗口中的主程序会自动清除,而且存盘后另一窗口主程序的前面加DECLARESUB子程序名);通过View菜单的SUBs菜单项选择或激活要编辑的子菜单或主程序。,模块之间数据传递-虚实结合,主程序或其它调用子程序的程序块称为“调用程序”。在调用子程序时调用程序的实参和被调用的子程序的形参之间的数据传递,称为“虚实结合”。在高级语言中,虚实结合有两种方式。(1)值传递方式:即实参把其值传递给形参,这种传递是“单向的”。(2)地址传递方式:这种方式是半实参的地址传递形参,实参与形象共占同一存储单元。,定义自定义函数、独立模块的函数和子程序时的自变量称为“形式参数”或“虚拟参数”,简称“形参或“虚参”。之所以称它为“形式参数”,是因为所用的自变量并不是一个实际存在的变量,在未调用函数时它并不具有确定的值。它只是在形式上存在的一个变量。在函数时被调用时它将被一个确定的值所代替。形式参数的名字叫什么并不重要。重要的是表达式所表示的函数关系和调用时所给定的实际参数。调用函数时函数名后面括弧中的参数称为“实际参数”。它应该是一个确定的值,它可以是常量或表达式。如果自定义函数的形象与程序中的变量名相同,它们并不代表同一对象。,“形参”和“实参”,按地址传递参数,若实参使变量,则调用子程序时,系统不为对应的形参另外开辟存储单元,而是把实参所占的存储单元的地址传送给子程序,使对应的形参具有相同的地址,也就是说,形参将与对应的实参共用存储单元。(参见samp6-2.bas),DECLARESUBabc(aa!,bb!,xx!,yy!)REMmaimprograma=21.2:b=12.1CALLabc(a,b,x,y)PRINT“a=”;a,”b=”;bPRINT“x=”;x,”y=”;yENDSUBabc(aa,bb,xx,yy)xx=aa+bbyy=aa-bbENDSUB,aa,bb,xx,yy,aa,bb,xx,yy,按值传递参数,如果实参是表达式,在调用子程序时,系统将为对应形参开辟存储单元,实参的值赋给形参变量,如果实参和对应的形参数据类型不一致,将按不同类型赋值的规则处理,如果超出范围,系统将报错。(参见samp6-3.bas),DECLARESUBxyz(aASINTEGER,bASINTEGER)REMmainprogramDIMaASINTEGER,bASINTEGERa=10:b=1CALLxyz(20.3432#,8.6)PRINTmain:,a=;a,b=;bENDSUBxyz(aASINTEGER,bASINTEGER)a=b+aPRINTSubxyz:,a=;a,b=;bENDSUB,独立模块子程序举例,(参见samp6-4.bas)DECLARESUBMyswap(xASINTEGER,yASINTEGER)REMmainprogramDIMaASINTEGER,bASINTEGERa=10:b=20PRINT(1)a=;a,b=;bCALLMyswap(a,b)PRINT(2)a=;a,b=;bENDSUBMyswap(xASINTEGER,yASINTEGER)z=x:x=y:y=zENDSUB,例1编写子程序myswap,其作用是对输入的两个整数进行对调。,独立模块子程序举例,(参见samp6-5.bas),例2编写子程序order,其作用是对通过实参变量传递到子程序的任意3个数由小到大进行排序后传回主程序。,DECLARESUBMyswap(mASINTEGER,nASINTEGER)DECLARESUBOrder(xASINTEGER,yASINTEGER,zASINTEGER)REMmainprogramDIMaASINTEGER,bASINTEGER,cASINTEGERINPUTa,b,c=,a,b,cPRINT(1)a=;a,b=;b,c=;cOrdera,b,cPRINT(2)a=;a,b=;b,c=;cENDSUBMyswap(xASINTEGER,yASINTEGER)z=x:x=y:y=zENDSUBSUBOrder(xASINTEGER,yASINTEGER,zASINTEGER)IFxyTHENCALLMyswap(x,y)IFxxTHENCALLMyswap(x,z)IFyzTHENCALLMyswap(y,z)ENDSUB,独立模块子程序举例,(参见samp6-6.bas),例3编写子程序用于分解某个数的所有因子,并输出分解的结果。,DECLARESUBfac(kASINTEGER)REMmainprogramDIMnASINTEGERINPUTPleaseinputn=;nIFn=0THENPRINT*Error:n=0ENDELSEPRINTSGN(n);ENDIFCALLfac(n)PRINT=;nENDSUBfac(kASINTEGER)DIMiASINTEGERk=ABS(k)FORi=2TOk2WHILE(kMODi)=0)PRINT*;i;k=kiWENDNEXTiIFk1THENPRINT*;k;ENDSUB,独立模块子程序举例,(参见samp6-7.bas),例2编写子程序用于打印指定区间的正弦曲线,要求每隔10度打印一个点。,DECLARESUBsincurve(aASSINGLE,bASSINGLE)REMmainprogramINPUTPleaseinputa,b(degree):,a,bIF(ab)THENSWAPa,bCALLsincurve(a,b)ENDSUBsincurve(aASSINGLE,bASSINGLE)DIMxASINTEGERFORx=aTObSTEP10PRINTx;PRINTTAB(32+20*SIN(x*3.14159/180);*NEXTxENDSUB,基本要求,掌握模块化子程序的定义和调用方法;掌握模块之间数据的传递形式,独立模块的函数引例,DECLAREFUNCTIONfmax%(xASINTEGER,yASINTEGER)REMmainprogramDIMaASINTEGER,bASINTEGER,maxASINTEGERINPUTPleseinputa,b=;a,bPRINTa=;a,b=;bmax=fmax%(a,b)PRINTThemaxis:;maxENDFUNCTIONfmax%(xASINTEGER,yASINTEGER)IF(xy)THENfmax%=x:EXITFUNCTIONELSEfmax%=y:EXITFUNCTIONENDIFENDFUNCTION,模块化的函数,FUNCTION函数的结构形式如下:FUNCTION函数名形参表列STATICLET函数名=表达式ENDFUNCTION在函数语句体中,函数名应至少被赋值一次;在函数体中函数名可以被赋值,但不能参加运算或用作输出;函数名具有类型的属性,它可以是整型、实型、双精度型、长整型或字符串型;函数以FUNCTION语句作为开头的标志,以ENDFUNCTION作为终止标志;STATIC是一个可选项,用它指定函数中的变量为“静态”变量;建立一个函数的操作与建立子程序的操作相似;在函数体中不可以再定义独立模块的子程序或函数。,函数的调用,如果在主程序(或其它调用程序中)想调用一个函数,只需写出函数名和相应的参数即可,如:函数名(实际参数)或函数名。调用函数时应注意:在调用程序的开头要加DECLARE语句。一般形式为:DECLAREFUNCTION函数名(参数表列)如果是无参函数,DECLARE语句中不写参数,但括弧不能少。这时一般形式为:DECLAREFUNCTION函数名()实参的个数与类型与形参一一对应,实参可以是常量、表达式或变量;FUNCTION函数的虚实结合与子程序的相同。调用函数时,通常是为了得到一个函数值,并不希望改变实参的值,这是可以按值的方式来调用函数,即用括号把实参变量括起来;函数的调用不可以作为一条独立语句,它总是出现再允许表达式出现的地方,函数名指定要调用的函数,并由函数名返回一个函数值。,编写函数用于判断函数的自变量是否是素数,如果是素数,函数值为1,则打印YES;否则,函数值为0,打印NO。按照证歌德巴赫猜想,一个大于5的偶数可以表示为两个素数的和。编写程序判断任意输入的两个数之间的所有偶数都可用两个素数的和表示。子程序1:规范任意输入的数,使之符合歌德巴赫猜想的条件;子程序2:利用循环结构,将每一个偶数表示为两个素数的和;函数1:判断是否为偶数,如果是奇数,其值为1;函数2:判断一个数是否为素数,如果是素数,其值为1;,独立模块的函数举例,局部变量引例,a为局部变量。分别输出主程序中a和子程序中a的值。DECLATRSUBTry(n!)a=4PRINTainmainprogramis:;aCALLTry(4)ENDSUBTry(n)PRINTainsubprogramis:;aFORi=1TOnPRINTNEXTiENDSUB,运行结果如下:ainmainprogramis:4ainsubprogramis:0,每一个模块,例如主程序、子程序和FUNCTION函数,如果不加以特别说明,它们各自中的变量都只在本模块中有效,或者说它们的作用域只限于本模块。例如主程序中变量a的值为4,想直接在子程序输出a的值4,是做不到的。可以看出:由于未加特别说明,主程序中的变量a只在主程序中有效。子程序中变量a与主程序中的a不是同一个变量,各自有其存储单元。由于子程序中的a未被赋值,故输出初始化时的值0。这种只在本模块中有效的变量,称为局部变量。未加特别说明,在主程序中使用的变量也是局部变量,只限于主程序内有效,不要以为主程序中的变量在整个程序各模块中都有效。一些BASIC版本如BASICA和GW-BASIC中,由于不提供局部变量,所有子程序和自定义函数都和主程序处在同一模块中,而不是分别组织在不同模块中,所以它们都是全局变量。,局部变量,全局变量是指在程序所有模块中都有效的变量,即其作用域为整个程序的变量。QBASIC规定可以用COMMONSHARED和DIMSHARED语句对变量或数组作全局申明。其格式分别为:COMMONSHARED变量表列DIMSHARED变量表列例如:COMMONSHAREDx!,y#,z%,w$指出实型变量x!、双精度整型变量y#、整型变量Z%、字符串变量w$为全局变量。DIMSHAREDa1(15),b2(5,12),c3(4,5,6)指出一维数组a1、二维数组b2、三维数组c3为全局数组。COMMONSHARED和DIMSHARED语句应写在主程序的开头位置,在所有执行语句之前。,全局变量,DECLARESUBtry()DIMSHAREDkASINTEGERk=99PRINTInmain(1)k=;kCALLtryPRINTInmain(4)k=;kENDSUBtryPRINTInsub(2)k=;kk=77PRINTInsub(3)k=;kENDSUB,全局变量举例,运行结果如下:Inmain(1)k=99Insub(2)k=99Insub(3)k=77Inmain(4)k=77,过程定义行中的STATIC选项,每当调用子程序或函数时,系统将为过程中用到的变量开辟存储单元,并对数值变量赋值0。当调用结束后,过程中的变量不再存在,即不在占有内存。当指定STATIC选项后,过程中的所有变量将占有永久性的存储单元,但第一次调用时,系统为过程中的变量开辟存储单元,并对数值变量赋初值0,调用结束后,这些变量仍然存在,当第二次调用时,系统仍然使用原来的存储单元,上一次保存的值就是它的初值。,STATIC选项举例,运行结果:try1:n=0m=0n=0m=0n=0m=0n=0m=0try2:n=0m=0n=1m=2n=2m=4n=3m=6,DECLARESUBtry1()DECLARESUBtry2()REMmainprogramDIMiASINTEGERPRINTtry1:FORi=1TO4:CALLtry1:NEXTiPRINTPRINTtry2:FORi=1TO4:CALLtry2:NEXTiPRINTENDSUBtry1PRINTn=;n,m=;mn=n+1:m=m+2ENDSUBSUBtry2STATICPRINTn=;n,m=;mn=n+1:m=m+2ENDSUB,过程体中的STATIC选项,再过程体中可以使用STATIC语句指定过程体中的某些变量占有占有永久性的存储单元。,运行结果:sub(1):a=0sub(2):a=3main(1):a=100sub(1):a=3sub(2):a=7main(2):a=100,DECLARESUBss(nASINTEGER)REMmainprogramDIMSHAREDaASINTEGERa=100CALLss(3)PRINTmain(1):a=;aCALLss(4)PRINTmain(2):a=;aPRINTEND,SUBss(nASINTEGER)STATICaASINTEGERPRINTsub(1):a=;aa=a+nPRINTsub(2):a=;aENDSUB,基本要求,掌握模块化函数的定义和调用方法;掌握模块之间数据传递方式;了解局部变量的概念。,在调用一个子程序或函数的过程中又出现直接或间接调用该子程序或函数本身,称为过程的递归调用。程序中不应出现无终止调用,而只应是有限次数的、有终止的递归调用,这可以用IF条件来控制,只在某一条件成立时才继续执行递归调用,否则就不再继续。下面举一个例子来作说明。,过程的递归调用,例1有5个人坐在一起,问第5个人多少岁?他说比第4个人大2岁。问第4个人的岁数,他说比第3个人大2岁。问第3个人,又说比第2个人大2岁。问第2个人,说比第1个人大2岁。最后问第1个人,他说是10岁。请问第5个人多大?,运行结果如下:18Age函数共被调用5次,其中Age(5)是主程序调用的,其余4次是在Age函数中调用的,即递归调用4次。(参见age.bas),DECLAREFUNCTIONage(nASINTEGER)PRINTage(5)ENDFUNCTIONage(nASINTEGER)IFn=1THENage=10EXITFUNCTIONELSEage=age(n-1)+2ENDIFENDFUNCTION,DECLAREFUNCTIONage(nASINTEGER)PRINTage(5)ENDFUNCTIONAge(nASINTEGER)IFn=1THENAge=10EXITFUNCTIONELSEAge=Age(n-1)+2ENDIFENDFUNCTION,12,14,16,18,例2利用递归调用求解n!,求n!的问题可以转化为求n(n-1)!的新问题,而求(n-1)!与求n!的解法完全相同,只是运算对象由n变成了n1,这时求n(n-1)!的问题由转化为求n(n-1)(n-2)!的新问题,每次转化为新问题时,运算对象都减1,照此一直递归下去,直到n=1结束调用。,DECLAREFUNCTIONfacyENDIFENDFUNCTIONfacnPRINTfntotal(n)END运行结果如下:n=?1002500,(1)定义自定义函数的语句可以放在程序中的任何位置,但必须先定义才能调用它。习惯上把它放在程序的开头。程序如果写成下面这样是错误的。INPUTn=;nPRINTfntotal(n)DEFfntotal(n)total=0FORk=1TOnSTEP2total=total+kNEXTkfntotal=totalENDDEFEND因为在PRINT语句中出现fntotal函数名,而事先并未定义过此函数,程序无法辩别它,如果把PRINT语句调到END语句之前就对了。此时INPUT语句可以仍然在DEF语句之前。(2)函数的定义可以嵌套,即在定义一个函数时可以出现另一个已定义的函数。,使用自定义函数时应注意的问题,GOSUB-RETURN语句GOSUB是GOtoSUBroutine的缩写,意为:转到“子例行程序”去执行,routine是“例行”的意思,执行一个子程序如同改造一件“例行公事”一样。Subroutine译为子例行程序简称“子例程”。QBASIC把块内子程序称为“子例程”(Subroutine),而把模块子程序称为子程序(Subprogram)。GOSUB语句(也称为“转子语句”)将流程转到内子程序(即子例程)的第
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- IT技术支持与维护服务协议规本
- 个人图书出版合同
- 专业软件安装与维护协议
- 软件定制化开发合同协议
- 转让棋牌茶室协议书范本
- 邮轮乘务员派遣合同协议
- 造纸配件采购合同协议
- 路牙石订购合同协议
- 进修赔款协议书模板
- 进口国际贸易合同协议
- 混凝土氯离子含量试验检测记录表(选择性电极法)
- 纳税实务(第三版)项目一纳税基础知识
- 新教材人教版高中数学必修第二册全册教案(教学设计)
- DB23∕T 440-1996 柞蚕生产技术规程
- 药物溶解与溶出及释放-精品医学课件
- 汇源果汁生产废水处理工程设计
- TIG焊充氩仓的应用
- 魔方基础教程 三阶魔方简化教程
- 安徽高中毕业生登记表(共7页)
- 《小数加减混合运算(例3)》配套教学任务单
- 转化后进生记录4篇
评论
0/150
提交评论