| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1288 人关注过本帖, 2 人收藏
标题:VFP学习、开发漫谈 (11)
取消只看楼主 加入收藏
liuxingang28
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:山东济南
等 级:贵宾
威 望:47
帖 子:652
专家分:2160
注 册:2014-2-7
结帖率:96.88%
收藏(2)
已结贴  问题点数:20 回复次数:0 
VFP学习、开发漫谈 (11)
今天与大伙聊一聊编程中的分支结构和循环结构。

分支结构包括“IF...ENDIF”和 “DO CASE...ENDCASE”两组命令以及 IIF() 和 ICASE() 两个函数。

这几个命令和函数在某些情况下,可以互相代替,但我一般采取如下原则:

1. 尽可能将同一层次上的多个 IF 语句改成 DO CASE 结构,因为 DO CASE 结构更清晰,更简洁。
2. 从可读性来说,尽量少用 ICASE()函数,将其改为 DO CASE 命令较好。
3. 同样,从可读性上考虑,不建议嵌套使用 IIF()函数,即:在IIF()函数内部再使用IIF()函数,可改用 IF...ELSE...ENDIF 结构

在使用 DO CASE 结构时,CASE 语句的前后顺序很重要,因为后面的 CASE 语句是在不满足前面的 CASE 条件时,才会执行。下面是一个计算调节税的代码,各 CASE 语句的顺序不能调换:
程序代码:
nAmt = 工资表.应发工资 - 3500    && 应纳税额
DO CASE
CASE nAmt <= 0                   && 应纳税额小于0,不纳税
    nTax = 0
CASE nAmt <= 1500                && 0 - 1500,税率 3%
    nTax = nAmt * 0.03
CASE nAmt <= 4500                && 1500 - 4500,税率 10%
    nTax = (nAmt - 105) * 0.1
CASE nAmt <= 9000                && 4500 - 9000,税率 20%
    nTax = (nAmt - 555) * 0.2
CASE nAmt <= 35000               && 9000 - 35000,税率 25%
    nTax = (nAmt - 1005) * 0.25
CASE nAmt <= 55000               && 35000 - 55000,税率 30%
    nTax = (nAmt - 2755) * 0.3
CASE nAmt <= 80000               && 55000 - 80000,税率 35%
    nTax = (nAmt - 5555) * 0.35
OTHERWISE                        && 超过 80000,税率 45%
    nTax = (nAmt - 13505) * 0.45
ENDCASE

在判断复选框(CheckBox)是否被选定时,用“IF EMPTY(Check1.Value)”比用“IF Check1.Value = 0”要好。因为复选框的 Value 属性既可以是数值型,也可以是逻辑型。使用前者可适用于这两种情况,而后者仅适用于Value是数值的情况。

VFP 在处理逻辑表达式时有自己的特点。

1. 在处理“条件A AND 条件B”时,若条件A不成立,则不会再去判断条件B。例如:执行“IF 1>2 AND MESSAGEBOX('正确否?',36,'提示')=6”时,并不会弹出对话框。
2. 在处理“条件A OR 条件B”时,若条件A成立,则不会再去判断条件B。例如:执行“IF 2>1 OR MESSAGEBOX('正确否?',36,'提示')=6”时,也不会弹出对话框。

从上面的两种情况可以看出,逻辑连接符(AND,OR)两边的条件表达式的前后顺序,对程序的执行有影响。一般来说,把执行速度最快、最易判断的关系表达式放在前面。

有时候,通过将多个关系表达式用 OR 连接在一起,可以代替多个并列的 IF 语句或DO CASE 语句。例如:

IF 采购单.制单人 # gcUserName
    * 禁止修改其他人的采购单
    lErr = .t.
ENDIF
IF !EMPTY(采购单.审核)
    * 禁止修改已审核的采购单
    lErr = .t.
ENDIF

可以简化为以下语句:

* 禁止修改其他人的采购单和已审核的采购单
IF 采购单.制单人 # gcUserName OR !EMPTY(采购单.审核)
    lErr = .t.
ENDIF

有时候,通过将多个关系表达式用 AND 连接在一起,可以代替嵌套的 IF 语句或DO CASE 语句。例如:

IF THISFORM.cmgEdit.Value = 3    && 单击命令按钮组中的“删除”
    IF MESSAGEBOX('是否删除当前记录?',36+256,'提示') = 6    && 确认删除
        DELETE
        THISFORM.Refresh
    ENDIF
ENDIF

可以简化为以下语句:

IF THISFORM.cmgEdit.Value = 3 AND MESSAGEBOX('是否删除当前记录?',36+256,'提示') = 6
    DELETE
    THISFORM.Refresh
ENDIF

循环结构包括“FOR...”、“DO WHILE...”、“FOR EACH...”和“SCAN”四种结构。

对于“FOR i = 1 to n”这样的循环,需要注意的是:若变量的终止值是一个变量 n,则不要试图在循环内通过修改 n 的值,来达到改变循环次数的目的。这样做的结果是:n 的值确实改变了,但循环次数未变。
图片附件: 游客没有浏览图片的权限,请 登录注册


我们本来试图通过在循环体内将 n 改为 1 使其仅循环一次,但实际情况却是循环仍然执行了三次。这是因为在执行循环前,系统就将变量转换成了常量,从而确定了循环次数。

若将上例改为“DO WHILE”结构,则情况大为不同:
图片附件: 游客没有浏览图片的权限,请 登录注册


运行结果表明,循环仅执行了一次。与 FOR 循环不同,DO WHILE 每执行一次循环,系统都要重新计算一次表达式的值,包括其中的变量。因此在循环体内更改变量值对循环次数有影响。

再看一个实例,将上述代码中的变量 n 改为宏替换:
图片附件: 游客没有浏览图片的权限,请 登录注册


运行结果表明,循环又执行了三次。因为在循环开始时,系统通过宏替换将命令转换成了“DO WHILE i <= 3”,在循环体内改变变量的值对循环次数无影响。

再看下面一个例子,将上述代码修改如下:
图片附件: 游客没有浏览图片的权限,请 登录注册


运行结果表明,循环仅执行了一次。因为循环开始时,宏替换将命令转换成了“DO WHILE i <= n”。

上述几个例子虽然简单,但其中的细微差别却导致了循环行为有很大的不同,需要用户细细品味,举一反三。

FOR EACH 循环主要针对数组和集合。示例:为表单添加一个自定义方法 SetEnabled,用于启用或禁用表单上的文本框。若文本框无需更改,请在设计时将其 TabStop属性设为 .f.
图片附件: 游客没有浏览图片的权限,请 登录注册


SCAN 循环仅针对表,注意以下3点:

1. 默认范围是 ALL
2. 不用在循环体内 SKIP
3. 在执行 ENDSCAN 时系统会自动返回 SCAN 时的工作区,无需添加“SELECT 工作区”

最后,举一个应用实例,从中再体会一下 FOR 循环与 DO WHILE 循环的区别。

功能描述:下图中的 List1和 List2均支持多项选择,单击“>”按钮,将左列表中的选定项添加到右列表的尾部,并且选定的列表项从左列表清除。
图片附件: 游客没有浏览图片的权限,请 登录注册


在“>”按钮的 Click 事件中,若采用 FOR 循环,需使用两个循环,如下所示:
程序代码:
LOCAL oList1,oList2,i
oList1 = THISFORM.List1
oList2 = THISFORM.List2

* 将 List1 中选定的列表项添加到 List2
FOR i = 1 TO oList1.ListCount
    IF oList1.Selected[i]
        oList2.AddItem(oList1.List[i])
    ENDIF
NEXT

* 将 List1 中选定的列表项删除
FOR i = oList1.ListCount TO 1 STEP -1
    IF oList1.Selected[i]
        oList1.RemoveItem(i)
    ENDIF
NEXT

若采用 DO WHILE,仅使用一个循环即可,如下所示:
程序代码:
LOCAL oList1,oList2,i
oList1 = THISFORM.List1
oList2 = THISFORM.List2
i = 1
* 遍历所有列表项
DO WHILE i <= oList1.ListCount
    IF oList1.Selected[i]               && 若列表项被选定
        oList2.AddItem(oList1.List[i])  && 添加列表项到 List2
        oList1.RemoveItem(i)            && 从 List1 中删除列表项
        * 删除 List[i] 后,List[i+1] 会变成 List[i]
    ELSE
        * 移到下一个列表项
        i = i + 1
    ENDIF
ENDDO


[ 本帖最后由 liuxingang28 于 2014-3-17 11:09 编辑 ]
搜索更多相关主题的帖子: 开发 
2014-03-17 10:59
快速回复:VFP学习、开发漫谈 (11)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.019418 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved