第三十一章 Caché 命令大全 WHILE 命令

文章目录

  • 第三十一章 Caché 命令大全 WHILE 命令
  • 重要
  • 大纲
    • 参数
  • 描述
  • 参数
    • expression
  • 示例
  • 注意
    • `WHILE` 与 `FOR`
    • `WHILE`与 `DO WHILE`
    • `WHILE` 与 `CONTINUE`
    • `WHILE`, `QUIT`, 与 `RETURN`
    • `WHILE` 与 `GOTO`

第三十一章 Caché 命令大全 WHILE 命令

条件为真时执行代码。

重要

  1. 注意无限循环,必须指定退出命令
  2. FOR循环将新级别推入堆栈。 WHILE循环不会更改堆栈级别。调试FOR循环时
  3. FORWHILE在单步调试的时候有区别。

大纲

WHILE expression,... {
  code
}

参数

  • expression 测试条件。可以指定一个或多个逗号分隔的测试条件,对于执行代码块,所有条件都必须为TRUE。
  • code 用大括号括起来的ObjectScript命令块。

描述

WHILE测试表达式,如果expression的计算结果为TRUE,则它将执行左花括号和右花括号之间的代码块(一个或多个命令)。只要expression的计算结果为TRUE,WHILE就可以重复执行一段代码。如果expression不为TRUE,则不执行花括号内的代码块,并执行紧跟大括号(}的下一个命令。

程序员必须小心避免WHILE无限循环。 WHILE 1 {… …(或任何其他永远不能评估为false的WHILE表达式)执行无限循环,因此循环代码必须发出QUIT退出循环。

左花括号或右花括号可以出现在其自己的代码行中,也可以与命令显示在同一行中。第1列中甚至可能会出现一个打开或关闭的花括号(尽管不建议这样做)。建议的编程做法是缩进大括号以指示嵌套代码块的开始和结束。在花括号前或后不需要空格。在右花括号之前(包括紧随无参命令的花括号),不需要空格。花括号只需要一个空格:右花括号必须与后面的命令用空格,制表符或换行符分隔。

花括号中的代码块可以包含一个或多个ObjectScript命令和函数调用。此代码块可能跨越几行。代码块中允许缩进,换行和空格。此代码块中的命令和命令中的参数可以用一个或多个空格或行返回分隔。

参数

expression

布尔测试条件。它可以采用单个表达式或逗号分隔的表达式列表的形式。如果Caché将表达式计算为TRUE(任何非零数值),则执行WHILE循环。通常,表达式是条件测试,例如x < 10“ apple” =“ apple”,但是任何计算结果为非零数字的值均为TRUE。例如7、00.1,“ 700”,“ 7dwarves”全部求值为TRUE。任何值为零的值为FALSE。例如,0,-0和任何非数字字符串都计算为FALSE。

对于表达式列表,Caché以从左到右的顺序计算各个表达式。如果遇到计算结果为0(FALSE)的表达式,它将停止计算。表达式右边的任何表达式的值为FALSE都不会得到验证或测试。

如果所有表达式的计算结果均为非零数值(TRUE),则Caché将执行WHILE循环代码块。只要表达式的计算结果为TRUE,Caché就会继续重复执行WHILE循环,并在每个循环的顶部测试表达式。如果有任何表达式的计算结果为FALSE,则Caché在WHILE关闭花括号后执行下一行代码。

示例

下面的示例执行WHILE循环指定次数。它在执行循环之前测试表达式:

/// d ##class(PHA.TEST.Command).Mainloop()
ClassMethod Mainloop()
{
	SET x=1
	WHILE x<10 {
		WRITE !," Looping",x
		SET x=x+1
	}
	WRITE !,"DONE"
	QUIT
}
DHC-APP>d ##class(PHA.TEST.Command).Mainloop()
 
 Looping1
 Looping2
 Looping3
 Looping4
 Looping5
 Looping6
 Looping7
 Looping8
 Looping9
DONE

下面的示例对执行两个表达式测试。这两个测试用逗号分隔。如果两个测试的结果都为true,则执行WHILE循环。因此,这些程序要么返回列表中的所有项,要么返回列表中项的指定样本大小:

/// d ##class(PHA.TEST.Command).TestWhile()
ClassMethod TestWhile()
{
	SET mylist=$LISTBUILD("a","b","c","d","e")
	SET ptr=0,sampcnt=1,sampmax=4
	WHILE 1=$LISTNEXT(mylist,ptr,value),sampcnt<sampmax {
		WRITE value," 是项 ",sampcnt,!
		SET sampcnt=sampcnt+1
	}
	IF sampcnt<sampmax {
		WRITE "这是整个数组"
	}
	ELSE {
		WRITE "这是 ",sampcnt-1," 数组项"
	}
}
DHC-APP>d ##class(PHA.TEST.Command).TestWhile()
a 是项 1
b 是项 2
c 是项 3
这是 3 数组项

/// d ##class(PHA.TEST.Command).TestWhile1()
ClassMethod TestWhile1()
{
	SET mylist=$LISTBUILD("a","b","c","d","e")
	SET ptr=0,sampcnt=1,sampmax=10
	WHILE 1=$LISTNEXT(mylist,ptr,value),sampcnt<sampmax {
		WRITE value," 是项 ",sampcnt,!
		SET sampcnt=sampcnt+1
	}
	IF sampcnt<sampmax {
		WRITE "这是整个数组"
	}
	ELSE {
		WRITE "这是 ",sampcnt-1," 数组项"
	}
}
DHC-APP>d ##class(PHA.TEST.Command).TestWhile1()
a 是项 1
b 是项 2
c 是项 3
d 是项 4
e 是项 5
这是整个数组

注意

WHILEFOR

可以使用FORWHILE来执行相同的操作:循环,直到事件导致执行脱离循环为止。但是,使用哪种循环结构会对在代码模块上执行单步调试(BREAK“ S +”BREAK“ L +”)产生影响。

FOR循环将新级别推入堆栈。 WHILE循环不会更改堆栈级别。调试FOR循环时,从FOR循环内部弹出堆栈(使用BREAK“ C” GOTOQUIT 1)可让在FOR命令构造结束后立即使用该命令继续单步调试。在调试WHILE循环时,发出BREAK“ C” GOTOQUIT 1不会弹出堆栈,因此,在WHILE命令结束后,单步调试不会继续进行。其余代码执行不中断。

WHILEDO WHILE

WHILE命令在执行循环之前测试表达式。 DO WHILE命令执行一次循环,然后测试表达式。

WHILECONTINUE

WHILE命令的代码块内,遇到CONTINUE命令会使执行立即跳回到WHILE命令。然后,WHILE命令计算其表达式测试条件,并基于该计算确定是否重新执行代码块循环。因此,CONTINUE命令在执行时的效果与到达代码块的右花括号完全相同。

WHILE, QUIT, 与 RETURN

代码块中的QUIT命令结束WHILE循环,并在右花括号后将执行转移到命令,如以下示例所示:

/// d ##class(PHA.TEST.Command).Testloop()
ClassMethod Testloop()
{
	SET x=1
	WHILE x < 10
	{
		WRITE !,"循环",x 
		QUIT:x=5
		SET x=x+1 
	}
	WRITE !,"完成"
}

该程序将Looping1写入Looping5,然后写入DONE

DHC-APP>d ##class(PHA.TEST.Command).Testloop()
 
循环1
循环2
循环3
循环4
循环5
完成

WHILE代码块可以嵌套。即,一个WHILE代码块可以包含另一个控制流循环(另一个WHILEFORDO WHILE代码块)。内部嵌套循环中的QUIT跳出内部循环,到达下一个封闭的外部循环。在下面的示例中显示:

/// d ##class(PHA.TEST.Command).Nestedloops()
ClassMethod Nestedloops()
{
	SET x=1,y=1
	WHILE x<6 {
		WRITE "外部循环 ",!
		WHILE y<100 {
			WRITE "内部循环 " 
			WRITE " y=",y,!
			QUIT:y=7
			SET y=y+2 
		}
		WRITE "回答外部循环 x=",x,!!
		SET x=x+1 
	}
	WRITE "完成"
}
DHC-APP>d ##class(PHA.TEST.Command).Nestedloops()
外部循环
内部循环  y=1
内部循环  y=3
内部循环  y=5
内部循环  y=7
回答外部循环 x=1
 
外部循环
内部循环  y=7
回答外部循环 x=2
 
外部循环
内部循环  y=7
回答外部循环 x=3
 
外部循环
内部循环  y=7
回答外部循环 x=4
 
外部循环
内部循环  y=7
回答外部循环 x=5
 
完成

可以在任何时候使用RETURN终止例程的执行,包括从WHILE循环或嵌套循环结构中终止。RETURN总是退出当前例程,返回到调用例程,或者在没有调用例程的情况下终止程序。不管是否从代码块中发出,RETURN的行为始终相同。

WHILEGOTO

代码块中的GOTO命令可以将执行定向到循环外部的标签,从而终止循环。代码块内的GOTO命令可将执行定向到同一代码块内的标签;该标签可以在嵌套的代码块中。代码块可以将执行定向到循环外部的标签,从而终止循环。

GOTO命令不应将执行定向到另一个代码块内的标签。尽管可以执行这样的构造,但将其视为“非法”的,因为它破坏了所输入代码块的测试条件。

下列形式的GOTO是合法的:

/// d ##class(PHA.TEST.Command).TestWhileGOTO()
ClassMethod TestWhileGOTO()
{
mainloop ; 转到代码块之外
	WHILE 1=1 {
		WRITE !,"在无限的WHILE循环中"
		GOTO label1
		WRITE !,"这不应该显示"
	} 
	WRITE !,"这不应该显示"
label1
	WRITE !,"进入label1并退出了"
}
DHC-APP>d ##class(PHA.TEST.Command).TestWhileGOTO()
 
在无限的WHILE循环中
进入label1并退出了
/// d ##class(PHA.TEST.Command).TestWhileGOTO1()
ClassMethod TestWhileGOTO1()
{
mainloop ; 转到同一代码块中的其他位置
	SET x=1
	WHILE x<3 {
		WRITE !,"在WHILE循环中"
		GOTO label1
		WRITE !,"这不应该显示"
label1
		WRITE !,"GOTO之后仍处于WHILE循环中"
		SET x=x+1
		WRITE !,"x=",x
	}
	WRITE !,"WHILE循环完成"
}
DHC-APP>d ##class(PHA.TEST.Command).TestWhileGOTO1()
 
在WHILE循环中
GOTO之后仍处于WHILE循环中
x=2
在WHILE循环中
GOTO之后仍处于WHILE循环中
x=3
WHILE循环完成
/// d ##class(PHA.TEST.Command).TestWhileGOTO2()
ClassMethod TestWhileGOTO2()
{
mainloop ; 从内部到外部嵌套代码块转到
	SET x=1,y=1
	WHILE x<6 {
		WRITE !,"外部循环",!
		SET x=x+1
label1
		WRITE "外循环迭代 ",x-1,!
		WHILE y<4 {
			WRITE !,"   内循环迭代 ",y,!
			SET y=y+1
			WRITE "   返回到 "
			GOTO label1
			WRITE "   这不应该显示",!
		}
		WRITE "内部循环完成",!
	}
	WRITE "全部完成"
}
DHC-APP>d ##class(PHA.TEST.Command).TestWhileGOTO2()
 
外部循环
外循环迭代 1
 
   内循环迭代 1
   返回到 外循环迭代 1
 
   内循环迭代 2
   返回到 外循环迭代 1
 
   内循环迭代 3
   返回到 外循环迭代 1
内部循环完成
 
外部循环
外循环迭代 2
内部循环完成
 
外部循环
外循环迭代 3
内部循环完成
 
外部循环
外循环迭代 4
内部循环完成
 
外部循环
外循环迭代 5
内部循环完成
全部完成
/// d ##class(PHA.TEST.Command).TestWhileGOTO3()
ClassMethod TestWhileGOTO3()
{
mainloop ; 从外部嵌套代码块到内部嵌套代码块
	SET x=1,y=1
	WHILE x<6 {
		WRITE !,"外部循环",!
		SET x=x+1
		WRITE "外循环迭代 ",x-1,!
		WRITE "跳转 "
		GOTO label1
		WRITE "这不应该显示",!
		WHILE y<4 {
			WRITE !,"   内循环迭代 ",y,!
			SET y=y+1
label1
			WRITE "内部循环 ",!
		}
		WRITE "内部循环完成",!
	}
	WRITE "全部完成"
}
DHC-APP>d ##class(PHA.TEST.Command).TestWhileGOTO3()
 
外部循环
外循环迭代 1
跳转 内部循环
 
   内循环迭代 1
内部循环
 
   内循环迭代 2
内部循环
 
   内循环迭代 3
内部循环
内部循环完成
 
外部循环
外循环迭代 2
跳转 内部循环
内部循环完成
 
外部循环
外循环迭代 3
跳转 内部循环
内部循环完成
 
外部循环
外循环迭代 4
跳转 内部循环
内部循环完成
 
外部循环
外循环迭代 5
跳转 内部循环
内部循环完成
全部完成

可以执行以下形式的GOTO,但它们被认为是“非法的”,因为它们使GOTO进入的块的条件测试失败(忽略):

/// d ##class(PHA.TEST.Command).TestWhileIllegal()
ClassMethod TestWhileIllegal()
{
mainloop ; 转到代码块
	SET x=1
	WRITE "跳转 "
	GOTO label1
	WHILE x>1,x<6 {
		WRITE "WHILE循环的顶部 x=",x,!
label1
		WRITE "WHILE循环的底部 x=",x,!!
		SET x=x+1
	}
}
DHC-APP>d ##class(PHA.TEST.Command).TestWhileIllegal()
跳转 WHILE循环的底部 x=1
 
WHILE循环的顶部 x=2
WHILE循环的底部 x=2
 
WHILE循环的顶部 x=3
WHILE循环的底部 x=3
 
WHILE循环的顶部 x=4
WHILE循环的底部 x=4
 
WHILE循环的顶部 x=5
WHILE循环的底部 x=5
 
/// d ##class(PHA.TEST.Command).TestWhileIllegal1()
ClassMethod TestWhileIllegal1()
{
mainloop ; 从代码块转到IF子句块的GOTO
	SET x=1
	WHILE x<6 {
		WRITE !,"WHILE循环迭代=",x,!
		SET x=x+1
		GOTO label1
		WRITE "这不应该显示",!
		IF x#2 { 
			WRITE "在IF子句中",!
label1
			WRITE "GOTO进入IF子句",!
			WRITE x," 是一个奇数",!
		} ELSE {
			WRITE "在ELSE子句中",!
			WRITE x," 是一个偶数",! 
		}
		WRITE "WHILE循环的底部",!
	}
	WRITE "全部完成"
}
DHC-APP>d ##class(PHA.TEST.Command).TestWhileIllegal1()
 
WHILE循环迭代=1
GOTO进入IF子句
2 是一个奇数
WHILE循环的底部
 
WHILE循环迭代=2
GOTO进入IF子句
3 是一个奇数
WHILE循环的底部
 
WHILE循环迭代=3
GOTO进入IF子句
4 是一个奇数
WHILE循环的底部
 
WHILE循环迭代=4
GOTO进入IF子句
5 是一个奇数
WHILE循环的底部
 
WHILE循环迭代=5
GOTO进入IF子句
6 是一个奇数
WHILE循环的底部
全部完成

你可能感兴趣的:(Caché,命令大全)