5.2 编 写 脚 本
Powers cript画板中提供了很多辅助的功能,可以提高开发效率、减少开发人员死记硬背。尤其对于初学者,掌握这里介绍的功能可以加快学习的进度。
5.2.1 粘贴语句
对于PB的初学者或使用多种语言进行开发的编程人员来说,记清楚一些语言的语法规则是件很烦人的事情。PB在Powers cript画板中提供了很强的语句粘贴功能,可以很方便地在Powers cript任意位置粘贴PB的流程控制语句,可以像小学生做填空题似的在流程控制语句中加入条件和语句即可。
可以在窗口菜单Edit中的Paste Special下选择适当的命令,也可以在s cript视窗的鼠标右键弹出菜单中进行同样的选择。比如,需要在s cript视窗中粘贴Choose Case的语法格式,可以在Paste Special下选择Statement->Choose Case,在s cript窗口的当前光标位置自动放置如下脚本:
CHOOSE CASE /*expression*/
CASE /*item*/
/*statementblock*/
END CHOOSE
接下来只要修改部分注释就可以了。
当需要粘贴PB提供的函数时,选择Function->Built-in,然后稍等片刻(这时的鼠标不要点任何按键,显示内建函数的时间稍长)即可在s cript视窗中当前光标位置显示一个包含系统中当前可用函数的选择框。该选择框中一般包含的函数比较多,可以使用右侧的滚动条翻页查找,也可以直接使用键盘上的PgUp或者PgDn键翻页查找,还可以直接输入需要函数的首字母来自动翻到以该字母开头的函数处。注意,这时鼠标不要在该选择框之外进行操作,否则选择框将自动关闭。找到需要的函数后,双击,选择框自动关闭,在s cript视窗当前光标位置放置该函数。除了可以粘贴PB提供的函数外,还可以粘贴用户自定义函数和扩展函数,操作方法相同。如果选择了命令后,在s cript视窗中没有显示相应的选择框,则表示没有可供粘贴的对象。
需要粘贴SQL语句时,系统自动和数据库联接并进入到另外一个窗口中,在该窗口中一般进行选择数据表、字段和条件,返回这几个操作步骤,即可将SQL语句返回并粘贴到刚才的s cript视窗的当前光标位置。下面以粘贴Select SQL语句为例介绍操作过程。首先选择Paste Spaciel->SQL->Select,如果还没有同数据库建立联接,则此时需要联接数据库,在窗口底部信息栏中显示Connecting Database。建立联接后,显示一个选择数据表的对话框。接下来要指定哪些字段,如果从多个表中选择字段,应该指明表之间的联接条件。这里的操作和创建视图时的操作相同,可以参见上一章创建视图时的介绍。组合完毕后,点击PainterBar上最右侧的小功能图标返回到原来的画板中,并在s cript视窗中光标的当前位置插入刚刚组合的SQL语句。放弃粘贴该SQL语句,直接使用窗口右上角的关闭按钮关闭窗口。
在菜单中选择其他项目可以粘贴其他内容。比如,粘贴全局变量可以选择Global,粘贴共享变量选择Shared,粘贴实例变量选择Instance,粘贴应用系统中的窗口名称选择Window,粘贴本画板中控件名称选择Object,粘贴当前事件参数使用Argument,粘贴其他文件中的文字内容可以选择From File,粘贴流程控制语句使用Statement。
5.2.2 添加注释
给脚本添加注释,虽然延长了开发时间,好像是降低了开发效率,从长远来看却恰恰相反。因为一个软件的生存周期很长,只要软件在使用,就存在维护的问题,而从事维护工作的不一定就是开发人员,程序的可读性直接影响到程序的可维护性,添加详细的注释可以使程序有很好的可读性。即使开发人员自己从事软件的维护工作,随着时间的推移,一些具体的细节也会淡忘。除了维护,开发期间的调试工作也需要很好的注释,规模稍微大一点的软件项目,都要涉及到合作问题。如果程序没有很好的注释,别人总要反复询问,势必影响开发的进度。注释实际上是程序文档的一部分,从严格意义上来说,是开发人员必须要提交的。
s cript的注释有两种方式,一种是从“//”开始到换行时结束的注释,这种注释方式比较简短,使用快捷。如果在整行的开头使用“//”,还可以使用快捷方式,点击图标可以在选中行的行头添加注释标记“//”,点击图标可以取消选中行的行头注释标记。这两个小图标用来添加注释和取消注释,可以对多行操作。另一种注释方式是以“/*”开始,以“*/”结束,一般在注释较长时使用。例如,下面的注释:
/*---------------------------------------------------------------------------------------------------------
* 函数定义:Integer FUNCTION f_set_table_select (REF adw_dataWindow)
* 函数作用:将数据窗口adw_dataWindow的SQL语句设置为用户在查询条件组合
* 窗口中设定的SQL语句。
* 特别说明:参数adw_dataWindow的传递方式为by referrence,这点一定要注意。
* 作 者: 郭宝利
* 编写日期: 2001-1-2
*---------------------------------------------------------------------------------------------------*/
String ls_rtn //用来保存用户在查询条件组合窗口中设置的信息
String ls_Filter //用来获取用户指定查询条件
OpenWithParm(w_query_tj,"gz") //打开查询条件组合窗口
Ls_rtn = Message.stringparm //格式: SQL检索条件+'^'+汉字检索条件
If ls_rtn <> '' Then //用户设置了查询条件
Ls_filter = Left(ls_rtn,Pos(ls_rtn, '^') – 1) //获取数据窗口的过滤条件
/*--------------------- 开始用用户的查询条件检索数据 -----------------*/
If dw_1.RowCount()< 1 Then return //如果没有数据,则没有过滤的必要了
dw_1.SetFilter(ls_filter) //设置过滤条件
dw_1.Filter() //过滤数据
/*-------------------------------- 检索数据完毕 -----------------------------*/
Else
Return //直接返回
End If
建议在自定义函数的开始、小功能模块的开始、判断的各条件分支、比较难懂的算法、变量定义时、调用其他函数或窗口处、窗口调用返回的信息格式等地方书写注释。注释要讲明要点,清晰明了。对于协作开发的大型软件项目,公共模块的注释要讲清楚作者、编写日期、调用接口、函数的返回值、使用方法,并对模块的功能做简短的描述。上面的注释是一个自定义函数中常见的注释格式。
5.2.3 查找替换
使用Windows 95的人对查找和替换操作应该很熟悉了,PB在s cript画板中也提供了这种风格的查找和替换,但它提供了更多的选项。查找和替换这两个对话框在PowerBuilder中大同小异,这里只介绍替换窗口。在s cript视窗中,使用鼠标右键弹出菜单中的Replace Text、窗口菜单Edit中的Replace Tex和快捷键Ctrl+H,都可以打开如图5-2所示的对话框。
该对话框中有5个选项开关可以使用。Match Case表示是否匹配大小写;Search Selection Only表示只在选中的范围内进行搜索匹配;Search Backwards表示向相反的方向查找;Wrap at Beginning or End表示当查找到文件结尾时是否继续从文件的开始搜索,直到搜索的起点结束,该选项默认是选中的;Regular Expression表示进行常规表达式搜索,该搜索是比较有技巧的搜索,例如输入“err[1234]”并选中Regular Expression可以查找出err1,err2,err3,err4。关于这种搜索方法的匹配表达式可以参阅函数match的详细解释。
5.2.4 编译脚本
当关闭s cript视窗时,在s cript视窗中选择其他事件或者其他控件时,选择s cript窗口右键弹出菜单中的Compile窗口菜单Edit中的Compile或者快捷键Ctrl+L时都可以导致编译当前s cript视窗中的当前脚本。
直接关闭s cript视窗,系统对脚本进行编译。编译通过,则保存脚本,没有通过则显示一个对话框询问是否放弃脚本的修改并关闭。如果确认,则关闭s cript视窗并放弃刚刚做的脚本修改,如果选择“否”,则显示编译错误信息,并且不关闭s cript视窗。如图5-3所示。其他方法进行编译脚本出错时都会停留在s cript视窗,并显示编译错误信息,其界面和图5-3相同。
上面的程序中有一个错误信息。双击错误信息光标会跳到与该错误信息对应的语句位置,便于修改找错。
2005-4-13 19:45 kevin1982
5.3 Powers cript语言基础(1)
不管哪种语言,都有自己特定的数据类型、操作符、保留字、流程控制、函数和书写规则。学习一种编程语言,最基本的要求就是要掌握这些方面,较高要求就是灵活地运用函数。单个函数的用法比较好理解,但怎么用这些函数来解决实际问题,用哪些函数的效率比较高,这不仅仅是一个算法问题,而且在很大程度上取决于对函数灵活地运用(当然,程序执行效率也有赖于界面的设计,这在后面的界面设计章节介绍)。
所以,在学习Powers cript语言时,不能拘泥于一些死的规则、规定,要多实践、勤动手。很多工作上的事情都可以用Powers cript语言来解决,在学习Powers cript语言时可以尝试着用学过的内容来解决这些问题。例如,人民币的习惯表示都是大写的汉字,如何将数字转变为大写汉字表示;Powers cript语言提供了在字符串中查找指定子串的函数,如何编写通用的函数,来查找某字符串中最后一个指定的子串;和数据库打交道的应用程序一般都要涉及到排序和查询,如何编写一个通用的排序模块和查询模块等等。
具体到Powers cript语言的学习,要掌握变量、表达式、语句、事件和函数,其中要灵活运用函数。
5.3.1 注释
注释用于书写关于脚本的说明,提供功能上的解释或设计思路的简短描述,可以增强程序的可读性,便于日后的维护工作。有两种注释方式:
= 以“//”开头,后面是注释内容,在一行内书写下。这种注释方式不能在语句中间插入注释,只能是在一行的开头或一行的后面书写注释。s cript画板中为这种注释方式提供了快捷方式,使用比较方便。
= 在“/*”和“*/”符号之间的为注释内容,可以多行书写注释。这种注释方式可以在语句的中间插入注释内容,一般用于书写内容比较多的注释。
例如,下面的脚本中使用了这两种注释方式:
String ls_name //该变量用于保存职工姓名
/*下面的程序定义光标,从数据库workers表中提取所有的职工姓名。为保证不重复提取,在name字段名前使用了关键字distinct,然后对光标逐条数据进行处理,将姓名加入到下拉列表框中,以供用户选择。*/
declare name_cur /*光标名称*/ cursor for
select distinct /*该关键字可以确保不重复提取*/ name from workers;
……
5.3.2 标识符
标识符是指在脚本中使用的变量、标号、窗口、控件、菜单以及其他所有引用的对象的名称。该名称的命名应该遵循如下规则:
(1)必须以字母或下划线开头。
(2)最长为40个字符,不能包含空格。
(3)不区分大小写,例如name,Name,NAME是相同的。
(4)不能是保留字,如This,Parent。
(5)可以包含数字、字母和一些特殊字符,特殊字符有短线“-”、下划线“_”、美元符号“$”、号码符号“#”和百分号“%”。
在变量中可以使用短线,使标识符的表达能力更强,但同时也带来了麻烦。因为像li_in-li_out这样的表达式就有了歧义:到底是变量li_in减 li_out呢,还是一个变量名称呢?为此,PowerBuilder规定减操作符号为“ – ”,也就是说短线的两端都带有空格表示为减操作,否则是变量中的一个普通字符。因为空格不能出现在变量中,所以只在短线前面加空格表示减操作符就足够了,也就是“ –”。为了避免这样的麻烦,可以在s cript画板中配置不允许在标识符中使用短线(取消Allow dashes in identifiers选项即可)。
标识符命名时,应该使标识符有一定的字面含义,有助于程序的调试和脚本可读性的提高。可以在标识符中使用大写、短线、下划线来体现标识符的意义。例如:CharacterCounter、 character_counter,character-count肯定都比charactercount的可读性更好一些。一个好的标识符命名建议是:
变量作用域+变量类型+“_”+具有一定字面含义的名称
使用该建议,上面的标识符character_counter改为li_CharacterCount,能反映出更多的含义:“l”代表是本地变量,是 Local的缩写,“i”代表是integer类型的变量,CharacterCount表名该变量是用来记录字符个数的计数器。
按照上面的规则和建议,下面是变量的一些例子:
(1) is_code
(2) li_count
(3) firstbuttoncaption
(4) FirstButtonCaption
(5) 2nd_quantity
(6) first button caption
(7) child’sage
其中,前四个是正确的变量名称,后面三个是错误的。(1)和(2)是比较好的变量命名,能够体现变量的类型、作用域和含义;(3)的可读性不是太好,(4)的可读性稍好,但不能体现类型和作用域。
5.3.3 特殊ASCII字符
字符串中可以包括一些特殊的控制字符或者字符串的界定符,例如可以在字符串中加入制表符以保证显示格式的整齐。使用方法如表5-1所示。
表5-1 特殊ASCII字符
名 称
符 号
名 称
符 号
换行(Formfeed)
~f
新行
~n
横向制表符
~t
垂直制表符
~v
回车
~r
退格(Backspace)
~b
单引号
~’
双引号
~”
波浪号~
~~
通过上表可以看出,特殊字符都是使用~符号来引用的。实际上,其他任意字符都可以使用~符号再加上数字来表示。数字的表示可以是从0到255的十进制,也可以是从0到hFF的十六进制数,还可以是从0到377的八进制数。例如:
~121 //ASCII码值为121的符号,也就是“y”
~h79 //ASCII码值为十六进制的79的符号,也就是“y”
~o171 //ASCII码值为八进制的171的符号,也就是“y”
注意,h是十六进制英文Hexadecimal的缩写,o是八进制英文单词Octal的缩写,都是小写。
5.3.4 标号
标号是和GOTO语句配合使用的,是GOTO语句要跳转的地方。标号由一个标识符后面跟一个冒号(:)构成,可以在一个脚本中放入任意数目的标号,但是同一段脚本中,标号不能重复。GOTO语句跳转时也只能跳转到当前脚本中的标号处,不能跳转到其他脚本的标号处。在结构化的程序设计中不提倡使用GOTO语句,但是Powers cript还是支持它。标号可以单独占用一行,也可以和语句同在一行。例如:
OtherProcess:
If lb_selected Then Continue_process=True
……
OtherProcess: If lb_selected Then Continue_process=True
……
以本人的开发经验,标号都是可以避免的。
2005-4-13 19:47 kevin1982
5.3 Powers cript语言基础(2)
5.3.5 NULL值
NULL代表不知道或者没有定义,和空值完全不同。例如,在数据库中某字段取值为NULL,代表用户还没有处理这个字段的数据,有待于处理;而如果该字段取值为空,代表这个字段的数据用户做了处理,这个字段的取值是清楚的。
当变量定义后,变量没有取值,应该为NULL,但实际上不是这样。PowerBuilder为每种类型的变量都规定了默认值,当刚刚定义了某类型的变量时,该变量的取值为这种类型变量的默认值。如integer类型的默认值为0,string类型的变量的默认值为“”。
大多数情况下,NULL和数据库打交道时才经常使用。当某个取值为NULL的字段取值读入到变量时,该变量被置为NULL。也可以通过函数将变量的值置为 NULL,但是不能直接把NULL赋值给变量。任何类型的变量都可以被赋值为NULL,NULL是一个非常特殊的值。函数用法是:
SetNull(变量名)
执行成功时返回1,否则返回-1。
例如:
String ls_name //此时变量ls_name的取值为“”
SetNull(ls_name) //ls_name变量此时为NULL
判断某变量的取值是否为NULL时,使用函数IsNull(变量名),不能使用“=”来判断。例如“if ls_name=NULL then…”是不正确的,“if IsNull(ls_name) then …”是正确的。当某布尔表达式的取值为NULL时,Powers cript处理为False。例如,下面的语句都不能执行beep(1)语句:
Int li_Nbr
// Set li_Nbr to NULL.
SetNull(Nbr)
If li_Nbr =1 Then Beep(1)
If li_Nbr <> 1 Then Beep(1)
If Not (li_Nbr = 1) Then Beep(1)
正因为NULL的特殊性,在条件语句中判断时要备加小心。例如,下面的语句就能正确执行ELSE中的信息显示:
Int li_count
SetNull(li_count)
If li_count = 1 Then
MessageBox("Value", "li_count= 1")
Else
MessageBox("Value", "li_count= NULL")
End If
但是,如果把上面的语句做语法上的等价修改,就什么显示信息也没有:
Int li_count
SetNull(lli_count)
If li_count = 1 Then MessageBox("Value", "li_count= 1")
If li_count <> 1 Then MessageBox("Value", "li_count= NULL")
当字符串的联接运算中有NULL时,取值也为NULL。例如:
String ls_name,ls_temp
SetNull(ls_temp)
Ls_name = "张三"
Ls_name = ls_name + ls_temp
If IsNull(ls_name) Then MessageBox("提示","空值!")