加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Foxpro 子程序、过程和函数

(2009-01-01 17:19:44)
标签:

杂谈

分类: VisuralFoxProl

Foxpro <wbr>子程序、过程和函数

初学者认识 Foxpro 子程序、过程和函数

 

    当我们编写一个软件的时候,通常都会遇到这样的情况:同一段程序在不同的地方要执行很多次。虽然 WINDOWS 为我们提供了“ 复制 ”、“ 粘贴 ” 的功能,但是如果您不想被人家笑是个外行的话,我建议您还是把它们写成“子程序”的形式,也就是我们通常用到的扩展名为.PRG 的程序文件,而不要去 “ 复制 ”+“ 粘贴 ”,更重要的是一味的复制大量的重复代码会使你的程序冗长、繁索,大大降低程序的性能和可读性;而使用子程序则会提高程序的利用率,缩短开发周期。

  编写一个子程序文件非常简单,只要我们:

  打开 项目管理器

  翻到 “ 代码 ” 页

  选中 “ 程序 ”

  按下 “ 新建 ” 按钮

  就一切 OK 了。看看下面的图你就会知道这是多么的容易。

Foxpro <wbr>子程序、过程和函数

    看到 “ 程序 1” 哪个子窗口了吗?那就是我们要输入代码的地方,只不过是我为了减小图形,所以把它给缩小了。

  好了,让我们动手来写我们的第一个子程序。这个子程序非常的简单,只是显示一个小窗口,上面来上那么一句 “ 你好 VFP” 。让我们在 “ 程序 1” 的子窗口写下以下的代码:

  MESSAGEBOX(“HELLO VFP”) &&显示提示窗口

  RETURN &&返回主程序

  搞定!让我们保存 一下,以便可以在以后的程序中调用它。单击右上角的小 X ,如果VFP发现你对子程序进行了修改,它就会问你是否保存子程序的修改,选 “是”并给它起个名字,就象用WORD保存一篇文档一样。 VFP会自动为它加上 .PRG 为扩展名的,这一点不用我们费心。假设我们存为 HELLO.PRG 。

这里的的 MESSAGEBOX( )函数用来显示 HELLO VFP 窗口, RETURN 命令用来返回调用的子程序的主程序,当子程序执行到 RETURN 语句时返回到主程序调用语句的下一条语句继续执行。

  小心:要是你把代码写到 RETURN 的后面的话,是不会被执行到的。每个子程序至少有一个 RETURN 语句。

  保存好子序程后,让我们在命令窗口中用 DO 命令来调用它。直接在命令窗口中写入以下的命令:

  DO HELLO

  这时你就会看到一个小窗户跳出来,上面写着 “HELLO VFP” ,当然你也可以在你的程序中的任何地方用 DO HELLO 来调用这个程序,比如在一个命令按钮的 click 事件中,或在一个表单的 init 事件中。

  到此为止,我们这个简单的 HELLO VFP 子程序就全部做完了。怎么样,是不是很容易?接着看下面:

 

  带参数的子程序

  在实际的编写软件的过程中我们经常会遇到这样的事情,子程序的某些地方要随着不同的情况要灵活的改变,就象我们刚才编写的 ” HELLO VFP ” 程序中,我们可能会要求它不要老是显示出 ' HELLO VFP' 这句只同 VFP 打招呼的话,而是根据我们的需要显示非富多彩的提示信息,比如显示个 ” 吃了吗? ” 之类的问候。可我们又不想建那么多的 PRG 文件。这时我们就要引入子程序中的 ” 参数 ” 的概念。

  “ 参数 ” 简单的说就是我们要向子程序传递的信息。它即可以是一个字符串,也可以是一个整数。下面我们就来编写一个带有参数的子程序,看过之后我不说,您也能知道参数是干什么用的了。

  按照上面讲过的建一个新的子程序文件,取个名字为 NEWHELLO.PRG 。在它里面写入下面的代码:

    PARAMETERS C_HELLO && 用来接收参数。

  MESSAGEBOX(C_HELLO)

  RETURN

  参数用 PARAMENTERS 引导,若多于一个参数,则参数之间用逗号分开,这些东东称为形式参数,因为它们只是一个参与运算的符号,只是一个形式的量,所以叫做形式参数。

  下面我们来调用这个新的子程序。在命令窗口敲入下面的代码 :

  DO NEWHELLO WITH '吃了吗?'

  这时你就会看到屏上又跳出一个小窗口,不同的是这次的问候语变成 “ 吃了吗? ” 这句了。我们再在命令窗口写入下面的代码:

  DO NETHELLO WITH ' 还没呢,您想请我搓一顿儿呀! '

  又跳出一个小窗口,问候语又变成“还没呢,您想请我搓一顿儿呀!”这句了,有意思吧?

  WITH 关键字指出将要传递给子程序的参数(实参), PARAMETERS 定义的形式参数(形参)接收的就是它的值。

  小心:要强调的是 形式参数和实际的个数必须一致 。 ( 就好比有两个小伙子,而只分配给他们一个姑娘,不打架才怪 ) ;其次是二者的顺序必须一致,最后二者对应参数的类型必须一致;否则的话。。。。。。。嘿。。。。。。。我不说你也知道。

  子程序还有一项很好的功能,它可以通过参数从子程中返回值,然后在程序中的其它地方便可以引用这个参数(或叫变量)进行其它的运算。为了更好的说明我们现举一个例子,这回我们不用 HELLO 哪个例子了,再用它的话,说不定就该让我们点票子,下馆子了。

  我们举一个查询的例子来说明 返回值 的用处。

  按照上面讲的过程建一个新的子程序文件,取个名字为 MYLOCATE.PRG 。在它里面写入下面的代码:

  PARAMENTERS TJ && 定义形式参数 TJ

    USE 人事管理 && 打开人事管理表

  GO TOP && 使指针指向首记录

  LOCATE FOR NAME = TJ && 开始查找

  IF EOF()

  RETURN .F. && 如没找到就返回 .F.

  ELSE

  RETURN .T. && 如找到就返回 .T.

  ENDIF

  用 RETURN 语句,后面跟上一个表达式,这样我们就可以把一个值返回 。 如果不指定表达式,则返回真值 .t.

  下面我们来调用它,新建一个程序:

  C_NAME = ' 庄稼 ' && 设定要查询的名字

  DO MYLOCATE WITH C_NAME TO C_RETURN &&调用子程序

  ?C_RETURN &&显示查询结果

  用 TO 关键字来接收子程序的返回值,如果找到名字为“庄稼”的员工就会在屏上显示 .T. ,否则的话就显示 .F.

 

  过程文件

  也许有的细心的读者会问:“如果是一个大型的软件要用很多的子程序,岂不是要建很多的 PRG 文件?”。问的好。对于较大型的程序,太多的 PRG 子程序即不便于管理,还会由于每个子程序文件做为单独的文件来处理,而带来加载文件时的开销。这就要引入 ' 过程 ' 概念。

  其实过程和子程序是一回事儿,只不过是把多个子程序保存在一个 PRG 文件中,在 PRG 文件里每个子程序单独定义罢了。对于保存多个子程序的 PRG 文件我们称为 ” 过程文件 ” 。

  在过程文件中写子程序不能象我们单独建立子程序时一样直接就开始写代码。那样的话分不清哪段代码属于哪段子程序了。要先对子程序进行定义,也就是定义一个过程。

  过程的定义形式是:

  PROCEDURE 过程名

  [PARAMETERS PARS1[,PARS2….]]

    过程体

  RETURN TO [ 程序名 ]

    ENDPROC

  PROCEDURE 是标识过程定义的关键字,“过程名”是标识此过程的名字,它就象人的名字一样,只不过人的名字是用来区分人的而“过程名”用来标识过程的。但有一点“过程名”与人名不太一样,人的名字可以重复,虽然也会出麻烦但问题不是很大,“过程名”就不一样了,它要求必须是唯一的,最好还能表达过程的主要功能。电脑可没有哪么聪明会区分两个同名的过程。

  PARAMETERS 和 RETURN 的用法和我们讲过的子程序的用法一样,就不多唠叨了。

  调用过程的方法也和调用子程序的方法一样。但是要注意一点,在调用过程时要指出包含在哪个过程文件中。方法有两个:

  一、 DO 过程名 [WITH 参数表 ] [IN 过程文件 ] , IN 关键字指出定义过程的过程文件。

  二、必须在调用前加上一个语句: SET PROCEDURE TO 过程文件名(带扩展名),它打开指定的过程文件,该文件中的过程就可以直接用 DO 过程名 调用了。

  讲完了“过程”以后,我们就可以把前面的 NEWHELLO 子程序和 MYLOCATE 子程序和并到一个过程文件里了。我们用 MYPRG.PRG 来保存。

  **************MYPRG.PRG*************

PROCEDURE NEWHELLO &&定义第一个过程
PARAMETERS C_HELLO && 用来接收参数。
MESSAGEBOX(C_HELLO)
RETURN

ENDPROC
PROCDEURE MYQUERY && 定义第二个过程
PARAMENTERS TJ && 形式参数
USE 人事管理
GO TOP
LOCATE FOR NAME = TJ
IF EOF()
  RETURN .F.
ELSE
  RETURN .T.
ENDIF

ENDPROC

  我们调用时用下面的形式调用就行了:

SET PROCEDURE TO MYPRG.PRG &&将过程文件打开
DO NEWHELLO W99vH “ 吃了吗 ?”
DO MYLOCATE W99vH “ 庄稼 ” TO TC
? TC
 

自定义函

 

  说完了 子程序和过程 , 咱们再来说说函数。其实函数和过程是十分相似的,只有一点小小的差别。(注意:我们这里讲的是自定义函数,而不是系统的函数。因为这些函数都是我们根据自已的需要,由自已动手定义和编写的,所以叫做自定义函数。)

  首先在定义时所用的关建字不是相同的。函数的定义形式如下:

  函数定义形式是:

    FUNCTION 函数名

  [PARAMETERS 参数表 ]

  函数体

  RETURN [ 表达式 ]

    ENDFUNC &&本句可有可无。

    FUNCTION 是函数的标识符,后面是函数名,同过程名一样,它是该函数的唯一标识,它的名字不允许同 FOXPRO 中的其它关键字及函数、过程同名。 PARAMETERS 和 RETURN 关键字的用法是和“过程”及“子程序”是相同的。每一个函数有一个函数体,它也是由一系列的代码组成,来完成特定的任务。

  其次在调用上也和“过程”有一些差别。

  函数的调用:

  函数名( [ 参数表 ] )

  函数可以出现在任何表达式中,并与 FOXPRO 的标准函数一样调用。当 FOXPRO 执行到表达式中的自定义函数时,就钻进“函数”里执行函数体的代码,在遇到 RETURN 语句时,便用表达式的值返回并替代函数名参与调用函数时的表达式的计算。

  最后在用法上也要灵活运用。如果要在表达式中使用且只返回一个值,并且该值只在一处调用,则应定义为函数;若定义为过程,则值作参数返回,返回的参数才能应用到表达式中,但可将一个值用在多个地方。在其他情况下,不论是用在表达式中,也不论是否返回值或多少个值,则应定义为过程。

 

 下面我们定义一个自定义函数 MYQUERY()。他的功能与 MYLOCATE 子程序一样。我们也把他加入到上面的 MYPRG.PRG 过程文件中。新的 MYPRG.PRG 过程文件的内容如下:

  **************MYPRG.PRG*************

PROCEDURE NEWHELLO &&定义第一个过程
PARAMETERS C_HELLO && 用来接收参数。
MESSAGEBOX(C_HELLO)
RETURN

ENDPROC

PROCDEURE MYQUERY && 定义第二个过程
PARAMENTERS TJ && 形式参数
USE 人事管理
GO TOP
LOCATE FOR NAME = TJ
IF EOF()
  RETURN .F.
ELSE
  RETURN .T.
ENDIF

ENDPROC


FUNCTION MYQUERY && 定义函数
PARAMENTERS TJ && 形式参数
USE 人事管理
GO TOP
LOCATE FOR NAME = TJ
IF EOF()
  RETURN .F.
ELSE
  RETURN .T.
ENDIF

ENDFUNC

  在调用时的形式如下 :

  SET PROCEDURE TO MYPRG.PRG

  ?MYQUERY(' 庄稼 ')

  到此为止,关于 子程序、过程和函数 的使用方法就介绍完了。^0^

 

  差点忘了,还有一个重要的问题没有讨论,就是变量的 作用域 的问题。这个问题可是十分重要的哟! ^0^

  在 FOXPRO 中,在子程序、过程或函数内定义(下面将这三者一并简称为子程序)的变量是局限于过程和函数内部的,当返回主程序时这些变量就不存在了,除非用 PUBLIC 指明它是公共变量 。比如:

  public tj

  那么返回主程序后 tj 这个变量就还可以用。也就是说,在一个过程或函数内定义的内存变量,在这个过程或函数体内便一直起作用,一旦从过程或函数体中退出,它便不复存在了,因为这时 FOXPRO 会把它所占用的内存空间收回作别的用。如果要使它们在过程或函数以外起作用,应用 PUBLIC 关键字来指明它是公共变量。

但主程序中的变量在子程序中可以用,如果在子程序中不想用主程序中变量,可在子程序中用如下命令将其屏蔽:

  private 变量名1,变量名2,...

  也可用如下语句屏蔽所有主程序的变量:

  private all

  也可在主程序中指明一个程序只能在本程序中使用,而不能在其下的子程序(或其上的主程序,怎么主程序还有主程序?等会讲)中使用,这种局部于过程或函数的内存变量也称局部变量或私有变量可以用 LOCAL 关键字 来声明:

  local 变量名1,变量名2,...

  在整个程序中起作用的变量也称全局变,用 PUBLIC 关键字来声明。

  提示

  主程序、子程序是相对的,比如 A 程序调用 B 程序,那 A 是主程序,B 是子程序;而 B 又可以调用 C 程序,那么这时 B 就是主,C 就是子了,也就是说爷爷是爸爸的爸爸。

  请看下面的例子:

***A.PRG***
use sjb
do b
***B.PRG***
locate for 姓名='庄稼'
if found()
do c
endif
return
***C.PRG***
messagebox('找到啦!')
return

  这回真的全部讲完了。现在我们学习过了过程和函数的使用方法,相信您不会再为了要去频繁的去复制和粘贴而发愁了吧。下章再见。

  下面是一些常用命令的语法说明。

  1 ) PROCEDURE 命令

  作用:定义一个过程

  语法:

  PROCEDURE 过程名

  [PARAMETERS PARS1[,PARS2….]]

  过程体

  RETURN TO [ 程序名 ]

  PROCEDURE 是标识过程定义的关键字,“过程名”是标识此过程的名字,它就象人的名字一样,只不过人的名字是用来区分人的而 ' 过程名 ' 用来标识标识过程的。但有一点“过程名”与人名不太一样,人的名字可以重复,虽然也会出麻烦但问题不是很大,“过程名”就不一样了,它要求必须是唯一的,最好还能表达过程的主要功能。电脑可没有哪么聪明会区分两个同名的过程。

    如果过程有参数,就用关键字 PARAMETERS, 后面跟随用逗号隔开的参数表,它起到向过程传递参数的作用。“过程体”是一系列 FOXPRO 的语名及其它成分,正是由它们来完成过程的主要功能。当过程执行到 RETURN 语句时返回到过程调用语句的下一条语句继续执行。要是你把代码写到 RETURN 的后面的话,嘿。。。。。。不被执行可别来找我。还有一点,每个过程至少有一个 RETURN 语句。没有了 RETURN 是万万不行的。就象人没了空气一样。

  2 ) FUNCTION 命令

  作用:定义一个函数:

  语法:

  FUNCTION 函数名

  [PARAMETERS 参数表 ]

  函数体

  RETURN [ 表达式 ]

  FUNCTION 是函数的标识符,后面是函数名,同过程名一样,它是该函数的唯一标识,它的名字不允许同 FOXPRO 中的其它关键字及函数、过程同名。由于这个函数不是 VFP 的亲生儿子,而是我们自已定义的,所以我们称它为自定义函数。函数可以有参数,用时把它们列在关键字 PARAMETERS 的后面,彼此以逗号分离开。在退出函数时,用 RETURN 语句,后面跟上一个表达式,这样我们就可以把一个值返回。如果不指定表达式,则返回真值 .t. 。每一个函数有一个函数体,它也是由一系列的代码组成,来完成特定的任务。

  3 )DO 命令

  作用:调用过程或子程序

  语法:

  DO 过程名 [W99vH 参数表 ] [IN 过程文件 ]

  WITH 关键字指出将要传弟给过程的参数, IN 关键字指出定义过程的过程文件。

  4 )SET PROCEDURE TO [ 过程文件名 ]

  作用:指出包含将要调用的过程或函的的过程文件。

 

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有