第六章过程与函数.doc_第1页
第六章过程与函数.doc_第2页
第六章过程与函数.doc_第3页
第六章过程与函数.doc_第4页
第六章过程与函数.doc_第5页
已阅读5页,还剩48页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

6.1 过程Delphi的过程分为标准过程与自定义过程两种。 标准过程是指系统内部定义的过程,无须编写代码,即可直接使用。如第2章介绍的Delphi常用函数与过程 用户自定义过程则由用户自行编写代码以完成指定的操作,包括事件过程与通用过程两类。 事件过程依附于对象,是Delphi应用程序的主体,当该对象响应指定事件时被执行,事件过程也可以由其他过程调用而被执行。 通用过程告诉应用程序如何完成一项指定的任务。通用过程不与任何特定的事件相联系,只能由别的过程来调用。 建立通用过程的理由之一是,几个不同的事件过程也许要执行同样的动作。将公共语句放入分离开的过程(通用过程)并由事件过程来调用它,这样一来就不必重复代码,也容易维护应用程序。本节主要讲授:事件过程的创建与调用通用过程的语法格式通用过程的创建与调用6.1.1 事件过程的创建与调用1 事件过程的创建2 事件过程的调用【例6-1】:在一个窗口中包含3个按钮,当用户单击其中一个时,要求其它个别按钮不能使用1 事件过程的创建在对象观察器(Object Inspector)中选择指定的对象,然后在事件(Events)选项卡中选择指定的事件名称,并用鼠标双击其右边的空白区域,Delphi将自动产生一个默认的事件过程。事件过程的名称是控件名加上事件类型名,如Button1控件的Onclick事件的默认事件过程名是Button1Click。 当用户对某一个对象发出一个动作时,Windows会通知Delphi产生一个事件,将自动到调用该对象与该事件相关的事件过程。即当对象对一个事件的发生作出认可时,Delphi便自动用相应于控件与事件的名字调用该事件过程。因为名字在对象和代码之间建立了联系,所以说事件过程上依附于对象上的。 另外,一个事件过程也可以被多个对象、多个事件共享。其方法为:首先为其中一个对象建立事件过程,然后在创建其它对象的事件过程时,从事件名称右边的下拉列表中选择已经建立的事件过程名即可。 共享了事件过程后,当其中任何一个事件发生时,事件过程都会被调用,这时可以根据Sender参数和TComponent类的Tag属性值来区分事件发生者,从而作出相应的处理。【例6-1】:在一个窗口中包含3个按钮,当用户单击其中一个时,要求其它个别按钮不能使用,如下图:单击Button1单击Button2单击Button3分析:本例可以分别建立3个按钮的单击事件过程,也可以使用同一个事件过程来处理3个按钮的单击事件。假设:单击Button1使Button2不可用;单击Button2使Button1不可用;单击Button3使Button1和Button2都可用。设计步骤如下:(1) 应用程序用户界面的建立与对象属性参见上图,注意三个按钮Button1,Button2,Button3的Tag属性分别为:0,1,2。(2) 双击按钮Button1,系统自动声明默认的事件过程:Button1Click, 并同时打开代码编辑窗口。(3) 编写Button1的OnClick事件过程代码:procedure TForm1.Button1Click(Sender: TObject);begin Case (Sender as TButton).Tag of 0: Button2.Enabled:= False; 1: Button1.Enabled:= False; 2: begin Button1.Enabled:= True; Button2.Enabled:= True; end; end;end;(4) 在对象观察器中依次选择Button2和Button3,并在事件选项卡中选择事件OnClick,从事件名称右边的下拉列表中选择已建立的事件过程名Button1Click。(5) 单击标准工具栏中的“Run”按钮或按键,运行工程。程序下载2 事件过程的调用 可以在过程代码中调用已经创建的事件过程。如在例6-1中,为Button3按钮创建独立的OnClick事件过程来调用已经存在的Button1Click事件过程:procedure TForm1.Button3Click(Sender: TObject);begin Button1Click(Sender);end;上述调用语句中的实际参数Sender还可以改为Button3,即:Button1Click(Button3);6.1.2 通用过程的语法格式通用过程在调用之前必须首先定义,定义一个通用过程也称为过程声明。过程声明要按照Delphi的语法,通用过程的语法格式与事件过程相似,由过程首部、过程体组成,过程中可包含说明部分和语句部分。 过程定义的一般形式是: Procedure (); 过程首部局部声明Begin 语句列; 语句列;End; 以保留字Procedure开头的第一行,称为过程首部,其余部分称为过程体。 语法图: 1 过程首部 过程名使用与变量名相同的命名规则。一个过程只能有唯一的过程名。 形式参数表由若干个形式参数组成,它指明了从调用过程传递给过程的实参个数和类型。所有的形式参数必须说明类型,相同类型的形参之间用逗号隔开,不同类型的形参之间用分号隔开。 形参说明格式为: Var |Const形参名:类型 保留字Var表示实参按传址方式传递到形参,形参在过程中所做的改变,退出过程后将影响实参的值,因此又称为变参。 保留字Const表示该形参在过程中的值被当作常量而不能改变。如果省略这两个保留字,则实参按传值方式传递到形参,形参在过程中所做的改变,退出过程后将不影响实参的值,因此又称为值参。 形参名可以是任何合法的标志符 类型则是Delphi中的数据类型。 中,如果某些形参的数据类型相同,可以列出这些形参名,然后再统一说明类型,参数名之间用逗号隔开。如: (HWnd: integer; Text,Caption: Pchar; Flags: integer) 2 过程体 过程体是一个程序段,由局部声明部分与可执行部分组成。局部声明部分用于声明该过程中使用的类型、常量、变量,这些类型、常量、变量的作用范围只局限于该过程内部,与过程体外的同名对象无关。在局部声明部分还可以包含另一个过程或函数声明(称为内嵌的过程或函数)。可执行部分由Begin开始,以End结束,End后面要紧跟一个分号。6.1.3 通用过程的创建与调用通过过程与事件过程不同,通用过程并不是由对象的某种事件激活,也不依附于某一对象,故其创建的方法略有不同。 在“代码”编辑窗口中,把光标定位在已有过程的外面。即可输入通用过程的声明。 通用过程调用是作为一条完整的独立语句,称之为过程语句。不能出现在表达式中。过程说明是静态的,不具备有执行的含义。如果一个过程说明之后未被调用,该过程永远不会被执行。过程语句的一般形式是:过程名(实在参数表);实在参数表中各个参数之间用逗号分隔。实在参数的个数必须和形式参数的个数相等,位置一一对应,类型相容。如果过程没有形参时,过程语句的格式如下 过程名; 或 过程名();通用过程只能在其作用域内进行调用,通用过程的作用域在其声明之后。【例6-2】:修改例6-1,建立一个通用过程来处理3个按钮的单击事件【例6-3】:计算阶乘5!、7!、15!,以及阶乘的和5!+7!+15!。【例6-2】:修改例6-1,建立一个通用过程来处理3个按钮的单击事件。上图说明了通用过程的使用,各个按钮的OnClick事件过程调用通用过程,通用过程运行自身的代码,然后将控制返回设计步骤如下:应用程序用户界面的建立与对象属性的设置与例6-1相同,下面介绍过程代码的编写:(1) 在$R *.dfm行的下一行,输入通用过程的代码:procedure Button(Sender: TObject);begin Case (Sender as TButton).Tag of 0: Form1.Button2.Enabled:= False; 1: Form1.Button1.Enabled:= False; 2: begin Form1.Button1.Enabled:= True; Form1.Button2.Enabled:= True; end; end;end;(2) 分别双击3个按钮,依次编写3个按钮的OnClick事件过程:Procedure Tform1.Button1Click(Sender:TObject);Begin Button(Sender);End;Procedure Tform1.Button2Click(Sender:TObject);Begin Button(Sender);End;Procedure Tform1.Button3Click(Sender:TObject);Begin Button(Sender);End;程序下载【例6-3】:计算阶乘5!、7!、15!,以及阶乘的和5!+7!+15!。 分析:可以用通用过程Factorial来计算任意阶乘n!,每次调用过程前给nValue一个值,在过程Factorial中将所求结果放入到Total变量中,返回主程序后Fact变量接受Total的值 设计步骤如下:应用程序用户界面的建立与对象属性达到设置参见上图,下面给出通用过程以及事件过程代码:Factorial通用过程为: procedure Factorial(n: integer; var Total: Int64);vari: integer;beginTotal:= 1;for i:= 1 to n do Total:= Total*i;end; 按钮Button1的OnClick事件代码为: procedure TForm1.Button1Click(Sender: TObject);vara: integer;Fact: Int64;begina:= 5;Factorial(a, Fact);panel1.Caption:= format(%d! = %d, a, fact);end; 按钮Button2的OnClick事件代码为: procedure TForm.Button1Click(Sender: TObject);var a: integer; Fact: Int64;begin a:= ;Factorial(a, Fact); panel1.Caption:= format(%d! = %d, a, fact);end; 按钮Button3的OnClick事件代码为: procedure TForm1.ButtonClick(Sender: TObject);var a: integer; Fact: Int64;begin a:= 5;Factorial(a, Fact); panel1.Caption:= format(%d! = %d, a, fact);end; 按钮Button4的OnClick事件代码为: procedure TForm1.Button4Click(Sender: TObject);vara: integer;Fact, Sum: Int64;beginSum:= 0;a:= 5;Factorial(a, Fact);Sum:= Sum + Fact;a:= 7;Factorial(a, Fact);Sum:= Sum + Fact;a:= 15;Factorial(a, Fact);Sum:= Sum + Fact;panel1.Caption:= format(5!+7!+15! = %d, Sum);end;说明:通用过程的代码部分必须位于4个按钮的事件代码之前才能被调用。 6.2 函数函数是子程序的另一种形式,当子程序的执行返回一个值时,使用函数就比较简单。Delphi语言系统提供了许多内部函数,如sin(正弦)、cos(余弦)、sqrt(开方)、abs(绝对值)、ln(对数)等。在表达式中引用这些标准函数是相当简单的,只要写出函数名并将自变量写在函数名后的圆括号中即可。自变量可以是表达式。当程序中碰到函数调用时,控制从调用程序转到被调用函数,函数处理自变量、完成函数计算,并回送结果,然后控制再返回到调用程序的调用点(即调用点的下一步操作)。 可以对不同的自变量重复多次调用某一函数,下面程序段包括了对于标准函数sqrt的两次调用y:=24.0;z:=25.0;x:=sqrt(z)+15.0;w:=sqrt(x + y + 5.0);在第一次调用中,自变量z的值是25.0回送的结果值,是5.0,它与15.0相加,赋给x的值是20.0,在第二次调用中,求自变量表达式有值20.0+24.0+5.0为49.0传给函数,函数返回的值是7.0,并赋给w。Delphi允许编写用户自定义的函数。6.2.1 函数的语法格式与过程一样,函数也是一个独立的程序段,可读取参数,执行一系列语句并改变其参数的值。与过程不同的是,函数具有返回值。函数的语法格式为:Function函数名(形参表):返回类型;局部声明Begin语句列End;以Function保留字开头的第一行,称为函数首部,其余部分为函数体。1 函数首部函数首部与过程首部相仿,只是多了一项返回类型,表示函数返回值的类型。函数的返回值通过函数名或预定义的Result(隐含变量)带回。2 函数体函数体与过程体相仿,也是一个程序段,由局部声明部分与可执行部分组成。在可执行部分中至少要给函数名或预定义的Result赋值一次,以便在函数执行结束后把函数值带回到调用过程。注意:Result并不完全等同于函数名。当函数名出现在赋值语句的左侧时,编译器认为是给函数赋返回值等同于Result;当函数名出现在其它地方时,则编译器认为是递归调用,而Result总是一个隐含的局部变量,不会被认为是递归调用。【例6-4】:计算任意整数n的阶乘的函数Factorial。function Factorial(n: integer): Int64;vari: integer; Total: Int64;beginTotal:= 1;for i:= 1 to n do Total:= Total*i; Factorial:= Total;end;6.2.2 函数的创建与调用 在“代码”编辑窗口中,把光标定位在已有过程或函数的前面,即可输入函数的声明。 函数的调用比较简单,可以像使用Delphi内部函数一样来调用函数,即在与函数返回值兼容的表达式中按下述格式调用:函数名(实参表)与通用过程相同,函数只能在其作用域内进行调用,函数的作用域在其声明之后。【例6-7】:编写求三数最大公约数的函数。在主程序中输入3个整数,调用函数求出3个证书的最大公约数,如下图分析:在第五章中利用“辗转相除”,采用Repeat循环求两个整数最大公约数的算法。根据此算法,设计一个求两数最大公约数的函数CommonDivisor,然后在主程序中调用设计步骤如下:应用程序用户界面的建立与对象参数的设置参见上图(左边)。编写代码:(1) 在$R *.dfm行的下一行,输入函数的代码:function CommonDivisor(M, N: int64): int64;var R,C: int64;begin if M N then begin C:= M; M:= N; N:= C; end; R:= M mod N; while R0 do begin M:= N; N:= R; R:= M mod N; end; CommonDivisor:= N;end;(2) 编写按钮Button1的OnClick事件代码:procedure TForm1.Button1Click(Sender: TObject);var L,M,N,T: int64;begin L:= Strtoint(Edit1.Text); M:= Strtoint(Edit2.Text); N:= Strtoint(Edit3.Text); if L*M*N 0 then T:= CommonDivisor(CommonDivisor(L,M),N); Panel1.Caption:= format(3个数的最大公约数是:%d, T);end;注意:自定义函数CommonDivisor的代码部分必须位于按钮的事件代码之前,才能被事件代码调用。6.3 向子程序传递参数调用子程序的目的,就是在一定的条件下完成某一工作或计算某一函数的值。外界要把条件告诉子程序,或反过来,子程序要把某些结果报告给外界,这就是子程序与外界的通讯。 调用子程序时可以把函数传递给子程序,也可以把子程序中的数据传回来。通常在编制一个子程序时,要考虑它需要输入哪些变量,进行处理后输出那些变量。正确地提供一个子程序的输入数据和正确到引用其输出数据,也就是调用过程和被调用子程序之间的数据传递问题,是使用子程序的关键问题。本节主要讲授:形式参数与实际参数参数传递方式缺省参数的使用函数与过程的重载6.3.1 形式参数与实际参数形式参数是指在定义过程或函数时,出现在过程或函数首部中的变量名,表示用于接受数据的变量。 实际参数是指在调用过程或函数时,传递给过程或函数的常量,变量或表达式。以过程为例,形式参数与实际参数的对应关系为: 在定义过程时,形式参数为实际参数保留位置。在调用过程时,实际参数被插入形式参数中的各变量处,第一个形式参数接收第一个实际参数的值,依次类推。 实参表和形参表中对应的变量名不必相同,但是变量的个数必须相等,而且各实际参数的书写顺序必须与相应的形式参数的类型相符。所谓类型相符,就是对于变量参数类型相同;对于值参数则要求实际参数对形式参数赋值相容。 在调用一个过程时,必须完成形式参数与实际参数的结合,即把实际参数传送给形式参数,然后按实际参数执行调用过程。6.3.2 参数的传递方式按照参数传递方式不同,Delphi中函数或过程的参数可分为变量参数、常量参数、值参数和外部参数(out)。 1 变量参数 在过程或函数首部形参表中的参数前面如果使用保留字var,则表示该参数为变量参数。 变量参数的传递方式为“按地址传递”,即将实参变量的地址传递给形参,这样形参与实参表示同一个存储单元。如果杂过程或函数中改变形参变量的值,将同时影响实参变量的值。 例6-8:编写一个交换real型变量数据的过程。Procedure Swap(var a,b:real);Var C: real;Begin C:= a;a:= b;a:= C;End;2 常量参数 在过程或函数首部形参表中参数前面如果使用保留字Const,则表示该参数为常量参数。 无论实参是否变量,常量参数在过程中总是被当作常量,其值不能改变。3 值参数 在过程或函数首部形参表中参数前面如果没有保留字,则表示该参数为值参数。 值参数的传递方式是“按值传递”,即将实参的值传递给形参,如果过程或函数中改变形参变量的值,则所做变动不会影响实参变量。例如在例6-7中,求两最大公约数的函数Hcf,其中M,N都是值参数:Function Hcf(M,N:int64):int64; 4 外部参数 在过程或函数首部形参表中参数前面如果使用保留字out,则表示该参数为外部参数。 外部参数与变量参数一样,其传递方式为“按地址传递”,但在使用时与变量参数有很大区别。当调用含有外部参数的过程或函数时,所引用的实参变量的值将被舍弃,形参变量仅被用做一个容器来储存过程或函数执行的中间结果。 上述4种参数中,常量参数与值参数属于按值传递的参数,变量参数与外部参数属于按值传递的参数。采用按值传递的参数只能从外界向过程或函数输入信息,不能传出;而采用按地址传递参数则既能传入,又能传出。 按值传递的参数与按地址传递的参数的一种重要区别是,按值传递对应的实参是表达式,而按地址传递对应的实参只能是变量。6.3.3 使用缺省参数在声明过程或函数时,可以给形参指定一个缺省值,指定缺省值的方法是:在形参的类型后面使用“=”,并给出一个具体的值。如: Procedure MyProcedure(x:real; y:real=10);Begin End; 对上述过程,下面的两个调用语句是等效的:MyProcedure(a,10);MyProcedure(a); 注意:在过程或函数定义中,不能让前面的形参有缺省值,而后面的参数没有。即不能如下声明:Procedure MyProcedure(x:real=10;y:real);【例6-9】:两个命令按钮的事件代码调用同一个过程,一个传递两个参数,一个传递一个参数,如下图:函数ListText返回一个字符串,其中第二个参数使用缺省值参数:Function ListText(X: string; Y: string = Delphi): string;Begin Result:= format(%-7s %7s, X,Y);End; 传递2个参数的Button1按钮的OnClick事件代码:procedure TForm1.Button1Click(Sender: TObject);var x, y: string;begin x:= InputBox(请输入, 第一个参数11, ); x:= Copy(x, 1, 7); y:= InputBox(请输入, 第二个参数22, ); y:= Copy(y, 1, 7); ListBox1.Items.Add(ListText(x, y);end; 传递1个参数的Button2按钮的OnClick事件代码:procedure TForm1.Button2Click(Sender: TObject);var x: string;begin x:= InputBox(请输入, 第一个参数11, ); x:= Copy(x, 1, 7); ListBox1.Items.Add(ListText(x);end;说明:自定义函数ListText的代码部分必须放于按钮的事件代码之前,才能被事件代码调用。6.3.4 函数与过程的重载在Delphi中,允许有名字相同而参数性同的过程或函数,这就是过程和函数的重载。例如:定义了两个同名函数: Function Divide( A,B: integer): integer; overload;Begin Result:= A div B;End;Function Divide(A,B: integer): real; overload;Begin Result:= A/B;End; 则在程序中的下述两条语句都将正常执行: I:= Divide(5,2);I:= Divide(5.0,2.1); 注意:在定义有默认参数的重载函数或过程时,必须让系统能从参数中区分出应该调用哪一个函数或过程,否则该定义为非法。如下面两个过程的定义是非法的:Procedure Proc(a:real);overload;Procedure Proc(a:real;b:real=3.14);overload;因为当Proc(3.1)使用时无法决定调用哪一个过程。6.4 子程序的嵌套和递归在一个子程序中(过程或函数)中包含另外一个子程序,称为子程序的嵌套。 在Delphi中,子程序不仅可以调用其它的子程序,还可以调用其自身(递归调用)。子程序直接调用自身称为直接调用,子程序间接到调用其自身,称为子程序的间接调用。 本节主要讲授:子程序的嵌套层次和调用规则子程序的递归6.4.1 子程序的嵌套1、子程序的嵌套层次 2、调用规则【例6 -10】输入参数N,M,求组合数 1、子程序的嵌套层次 在Delphi中,程序具有一定的层次结构。允许子程序的内部再定义新的子程序,即子程序可以嵌套定义。为了准确到表达嵌套层次,通常将嵌套从外向内进行编号,并把相应子程序的层号称为子程序的嵌套深度。一般将单元文件定为0层,其中的子程序从外向内依次为1层,2层,3层。有嵌套关系的子程序,若层号相差为1,称为相邻层,并称层号小的为外层子程序,层号大的为内层子程序;若层号相差大于1,则称为隔层。 子程序的嵌套要求外层子程序能够完全包含内层子程序,不允许局部包含。【例6-10】输入参数N,M,求组合数 分析: 把求阶乘和求组合数公式分别定义为函数:求组合数用一个函数Comb来实现。其中多次甬道求阶乘N!的工作则由另一个函数fact来实现。在Comb函数中定义Fact函数,这就是函数的嵌套。设计步骤如下:应用程序用户界面的建立与对象参数的设置参见上图(左边)。编写代码:(1) 求组合数函数Comb的代码:function Comb(N1,M1:int64):Real;var S,T,U:Real; function Fact(X: int64): Real; var I: integer; P: real; begin P:=1; for I:=1 to X do P:=P*I; Fact:=P; end;begin S:= Fact(N1); T:= Fact(M1); U:= Fact(N1-M1); Comb:= S/(T*U);end;(2) 等号按钮Button1的OnClick事件过程代码:procedure TForm1.Button1Click(Sender: TObject);var N,M,C: int64;begin M:= StrToInt(Edit1.Text); N:= StrToInt(Edit2.Text); if M N then ShowMessage(请保证参数的正确输入!) else Edit3.Text:= Format(%-10.0f, Comb(N, M);end;(3) 为了保证编辑框中只能输入数字参数,两个编辑框合用如下事件过程:procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);var L:Boolean;begin L:=(Key#8)and(Key#46)and (Key#57); if L then Key:=#0;end;(4) 为了保证Edit1中的值小于Edit2中的值,分别编写如下事件代码:procedure TForm1.Edit1Exit(Sender: TObject); /当焦点离开Edit1时发生begin if StrToInt(Edit2.Text) StrToInt(Edit1.Text) then Edit2.Text:= Edit1.Text;end;procedure TForm2.Edit1Exit(Sender: TObject); /当焦点离开Edit2时发生begin if StrToInt(Edit2.Text) StrToInt(Edit1.Text) then Edit1.Text:= Edit2.Text;end;说明:(1)为了避免整数运算产生溢出,这里将内部函数Fact声明为Real型。(2)自定义函数Comb的代码部分必须位于按钮事件之前,才能被事件代码调用。程序下载2、 调用规则在Delphi中,子程序的调用必须遵循如下规则:(1) 子程序可以调用其相邻内层的子程序,不能隔层调用。(2) 内层子程序可以调用外层子程序,而且允许隔层调用(属于间接递归)。(3) 同一层的子程序,允许后定义的子程序调用先定义的子程序。(4) 如果需要调用同层中后定义的子程序,必须用保留字Forward(超前引用)对后面的子程序提前说明。例如上例中的嵌套函数可以改为:Function Fact(X:int64):Real;Forward; /超前引用function Comb(N1,M1:int64):Real;var S,T,U:Real;begin S:= Fact(N1); T:= Fact(M1); U:= Fact(N1-M1); Comb:= S/(T*U);end; function Fact(X: int64): Real; var I: integer; P: real; begin P:=1; for I:=1 to X do P:=P*I; Fact:=P; end;说明:超前引用的子程序首部必须是完整的,而在后面的定义中,首部可以不带形参: function Fact; var I: integer; P: real; begin P:=1; for I:=1 to X do P:=P*I; Fact:=P; end;6.4.2 子程序的嵌套若过程A直接调用A本身,称为直接递归, 过程A调用过程B,而B又调用A,称间接递归。 递归过程在解决某些问题中十分有用,它可以使某些看起来不易解决的问题变得易于解决,而且写出的程序比较简单。 递归函数论是现代数学的一个重要分支,数学上常常采用递归的办法来定义一些概念,例如递归函数实现K!的计算。 此时求k!就可能转换为求(n-1)!,直到n=0为止,现在可以用递归函数来实现k!的计算.function fact (k:integer) :integer; begin if K = 0 then fact:= 1 else fact:= k * fact(k-1) end; 递归在算法中有着不可替代的作用,在处理阶乘运算、级数运算、幂指数运算中特别有效。在间接递归调用中,子程序必须进行超前引用,即在子程序的首部后面加上保留字。【例6-11】:契比雪夫多项式定义如下: 设计步骤如下:应用程序用户界面的建立与对象参数的设置参见上图(左边)。函数与事件过程的代码如下:求契比雪夫多项式的递归函数Fnt的代码: function Fnt(N:integer;X:single):single;begin Case N of 0: Fnt:= 1; 1: Fnt:= X; else Fnt:= 2*X*Fnt(N-1,X)-Fnt(N-2,X); end;end; 计算按钮Button1的OnClick事件代码: procedure TForm1.Button1Click(Sender: TObject);var M: integer; Y: single;begin M:= StrToInt(Edit1.Text); Y:= StrToFloat(Edit2.Text); Edit3.Text:= Format(%f, Fnt(M,Y);end; 注意: 利用递归算法能简单有效地解决一些特殊问题。但是由于递归调用需要保留大量的中间状态,所以执行效率很低,在选择递归时要慎重。 6.5 变量的作用域变量的作用域是指变量能被某一子程序识别的范围。当一个应用程序中出现多个过程或函数时,在它们各自的子程序中都可以定义自己的常量、变量。这样,自然会提出一个问题,这些常量或变量是否在程序中到处可用?回答是否定的。本节主要讲授:公有变量与私有变量全程变量与局部变量 全程变量的声明 6.5.1 公有变量与私有变量在单元的接口部分Interface声明的变量属于公有变量,可以被其他单元引用。单元的接口Interface决定了本单元对其它任何单元或程序的可见部分,在Interface中的声明对要使用这些声明的单元或应用程序是可见的。一个单元在需要引用其他单元的变量时,只要在Uses语句中指明该单元即可。在单元的实现部分Implementation声明的变量属于私有变量,不能被其他单元引用。6.5.2 全程变量与局部变量在单元中的过程或函数中声明的变量,其有效范围仅限于该子程序本身,属于局部变量。 而在子程序之前,Implementation之后声明的变量可以为本单元中的所有子程序引用,因此,又属于全程变量。在Interface中声明的公有变量也属于全程变量。 全程变量的作用域是整个程序,即在整个程序是可见的,有定义的,可以对其进行操作或引用。而局部变量的作用域是定义它的子程序,在子程序中有定义,可以被其操作或引用。一旦离开了子程序,局部变量就变得无定义,不能在对其进行操作或引用了。 从物理意义讲,全程变量在程序编译时,系统就在内存数据区中为其分配了所需的存储空间,并且在整个程序的运行阶段始终占有它。而局部变量仅当程序运行到子程序时,系统才在内存的栈区为其分配相应的存储空间,子程序运行结束后,局部变量占有的存储空间立即被释放。6.5.3 全程变量的声明下面介绍Implementation之后声明全程变量的方法。(1) 按F12键切换到代码编辑器窗口。将光标移到Implementation的下一行,$R*.DFM的上一行。(2) 输入如下变量声明的代码: var iSum: integer;即可声明在本单元使用的整数类型达到全程变量iSum。【例6-12】: 简易计算器分析:程序中的按钮分两类:数字类和运算符类,可以使用快速按钮(SpeedButton)使之分组工作,设计步骤如下:(1)应用程序用户界面的建立与对象参数的设置参见上图(左边)。主要特有的属性见表:属性名属性类型意义SpeedButton1 SpeedButton11Caption1,2,3,4,5,6,7,8,9, 0, .Tag1,2,3,4,5,6,7,8,9,0,10GroupIndex0SpeedButton12 SpeedButton16Caption+, -, *, /, =Tag0, 1, 2, 3, 4GroupIndex 1(2)声明全程变量: 按F12键切换到代码编辑器窗口。将光标移到Implementation的下一行,$R*.DFM的上一行,输入如下变量声明的代码:(3)函数与事件过程的代码如下:1) 编写窗体Form1的OnCreate事件代码,为全程变量赋初值:procedure TForm1.FormCreate(Sender: TObject);begin s:= 0; x:= 0; y:= 0; v:= False;end;2) 编写数字类按钮SpeedButton1的OnClick事件代码;procedure TForm1.SpeedButton1Click(Sender: TObject);begin if Form1.Tag = 1 then begin if Tag = 10 then Edit1.Text:= 0 else Edit1.Text:= (Sender as TSpeedButton).Caption; Form1.Tag:= 0; end else Edit1.Text:= Edit1.Text+ (Sender as TSpeedButton).Caption;end; 依次选中按钮SpeedButton2SpeedButton11,并在事件选项卡中选择事件OnClick,从事件名称右边的下拉列表中选择已建立的事件过程名SpeedButton1Click,使之共享同一个事件过程代码。3) 编写运算符类按钮SpeedButton12的OnClick事件代码;procedure TForm1.SpeedButton12Click(Sender: TObject);begin Form1.Tag:= 1; if v then begin x:= StrToFloat(Edit1.Text); v:= not v; end else begin y:= StrToFloat(Edit1.Text); case s of 0: Edit1.Text:= Format(%g, x+y); 1: Edit1.Text:= Format(%g, x-y); 2: Edit1.Text:= Format(%g, x*y); 3: if y 0

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论