当前位置:首页 > PHP学习宝典-第七章(续篇)

PHP学习宝典-第七章(续篇)

点击次数:1448  更新日期:2011-01-03
\n

有界限回圈和无界限回圈

有界限回圈(boundep loop)是将执行固定次数的回圈,查看程式码重复多少次就可以分辨出来,所用的叙述限定了它只能重复执行的次数。无界限回圈(unbounded loop),则会一直重复,直到某个条件变成真(或非真)为止。该条件取决于回圈内程式码的动作。有界限回圈是可预测的,但无限回圈或许会出现你意想不到的效果。

与某些程式语言不同,PHP实际是没有什么专门的有界限回圈结构,while、do-while和for都是无界限回圈结构,但无界限回圈也能够完成有界限回圈的一切功能。

除了本章中的回圈结构,PHP还提供了遍寻整个阵列内容的函式,这些将在第十一章中进行介绍。

while回圈

最简单的PHP回圈结构是while,语法如下:

while(condition)

statement

while回圈把条件(condition)运算式求值看成Boolean值,如果为真,则执行接下去的叙述(statement), 然后再次从条件评算求值开始。如果条件为非真,则while回圈终止。当然,就像if一样,接下去的叙述(statement)可以只有一条,也可以是大括弧围住的整个程式码区块。

While回圈的循环体可能一次也不执行,如下面的情况:

while(FALSE)

print(“This will never print.< BR >”);

或者可以是「永远」都在执行,如:

while(TRUE)

print(“All work and no play makes

Jack a dull boy.< BR >”);

或者按预期的次数执行,如下所示:

count = 1;

while (count <= 10)

{

print(“count is count< BR >”);

count = count + 1;

}

While会确切印出「10」行而停止(关于其它例子,请参照本章后面的「回圈范例」一节)。

do-while回圈

do –while回圈类似于while,但是测试发生在回圈结束时。语法如下:

do statement

while (expression);

叙述(statement)被执行一次,然后对运算式(expression)读音算求值。如果运算式为真,则反复执行该叙述,直到运算式为非真。

while和do-while之间的唯一实质差别是后者至少会执行一次,例如:count=45;

do

{

print(“count is count< BR >”);

count = count + 1;

}

while (count < = 10 );

会印出下面这一行:

count is 45

for回圈

最复杂的回圈结构算是for,语法如下:

for(initial-expression;

Termination-check;

Loop-end-expression)

Statement

在执行for叙述时,首先会对初始运算式(initial-expression)求值一次,通常会初始化变数。然后对终止检验(termination-check)评算求值,如果它为非真,则for叙述结束,如果它为真,则执行该叙述。最后,执行回圈结束运算式(loop-end-expression),然后根据终止检验并再次开始回圈。同样地,叙述(statement)可以表示单个叙述(以分号结尾),也可以表示以大括弧围住的程式码区块,或者可以是个条件结构。

如果把前面的for回圈重写为while回圈,则会如下所示:

initial-expression;

while(termination-check)

{

statement

loop-end-expression;

}

实际上,尽管for的典型运用会是有一个初始运算式,一个终止检验以及一个回圈结束运算式,但省略其中任何部分都有是有效的。如果把终上检验省略了,则结果会总是为真,因此,

for(;;)

statement

等同于

while(TRUE)

statement

包含多个for子句是有效的,每个子句可以逗号分隔即可。如果任何一个子句为真,则终止检验就认定其为真,这很像「or」测试。例如,下可的范例:

For(x = 1,y =1, z =1;// 初使运处式

y <10,z<10; //终止检验

x = x +1, y = y + 2, //回圈结束运算式

x = z + 3)

Print(“x, y, z< BR >”);

得到的浏览器输出为:

1,1,1

2,3,4

3,5,7

虽然for语法是最得杂的回圈结构,但它常用于简单的有界限回圈,可使用下面的格式:

For(count = 0;conut<limit; count = count + 1)

Statement

回圈限的for回圈

范例7-1展示的是有界限回圈的典型应用。因为大多数读者已经知道乘法表,我们这里做了一个除法表当例子。范例7-1产生的结果如图7-1所示。


范例7-1除法表

< ?php

start num = 1;

end num = 10;

? >

< HTML >

< HEAD >

< TITLE >A division table< /TITLE >

< /HEAD >

< BODY >

< H2 >A division table< /H2 >

< TABLE BORDER=1 >

< ?php

Print(“< TR >”);

Print(“< TH > < /TH >”);

For (count 1 = start num;

count 1 <=end num;

count 1++)

Print(“< TH >count 1< /TH >”);

Print(“< /TR >”);

For(count 1= start num;

cound 1< = end num;

count 1++)

{

Print(“< TR >< TH >count 1< /TH >”);

For (count 2 = start num;

count 2< = end num;

conut 2++)

{

result = count 1/count 2;

Printf(“< TD >%.3f< /TD >”,

result); //这部份请参阅第十章

}

Print(“< /TR >
”);

}

? >

< /TABLE >

< /BODY >

< /HEML >



这段程式码的主体部份就是一个for回圈巢状嵌套著另一个for回圈,每个回圈执行「10」次,结果得到「10×10」的表格。外层回圈的每次巡遍印出一行,每次内层印出一项。唯一的新特性是选用的输出显示数字的方式,我们使用了printf(将在第十章中讲解)该叙述允许控制输出显示的小数位数。

无界限的while回圈

现在我们来看一个界限不很明显的回圈。范例7-2中的程式码唯一的就是求81的近似平方根(使用牛顿方法)。近似过程从猜测的「1」开始,然后透过提高猜测逼近9的实际平方根。这种逼近的轨迹如图7-2。

范例7-2 求平方根的近似值

< HTML >

< HEAD >

< TITLE >Approximating a square root< /TITLE >

< /HEAD >

< BODY >

< H3 >Approximating a square root< /H3 >

< ?php >

targe = 81;

quess = 1.0;

precision = 0.0000001;

quess squared = quess * quess;

While((quess squared – target > precision) or

(quess squared – target < – prqcision))

{

Print(“Current quess:quess is the aquare

root of target< BR >”);

quess = (quess + (target/ quess))/2;

quess squared = quess * quess;

}

Print(“quess squared = qhess squared< BR >”);

? >

< /BODY >

< /HTML >



现在,虽然很容易图解表示无界回圈,但这个近似和例子是制造出来的,首先,因为PHP已经有了非常完美的平方根函式(sqrt),其次是因为数字81是以硬码(hard code)方式编写到页面中的。这个页面不能求出其它任何数字的平方根。

在下一章的内容中,我们会示范怎么把这倦的程式码放入一个可把数字做为参数的函式中。在第九章中还会讲解如何把这个参数从一个页面传递到另一个方机面。

break和contiune

跳出回圈结构的标准方式是让主测试条件变成「非真」。但特殊的break和continue命令则提供了从加圈结构中退出选择性分支路,这些回圈结构包括while、do-while和for:

2 break命令跳出了包含它的最内层回圈结构。

2 continue命令跳转到包含它的最内层回圈的当前重复结束之位置。

例如,下面的程式码:

for (x = 1;x <10; x++)

{

//如果x是奇数,则中断

if (x % 2 !=0)

break;

print(“x”);

}

这程式什么也不会显示出来,因为1是奇数,会立即让回圈终止。另外,请看另一个程式码:

for (x = 1;x<10; x++)

{

//如果x是奇数,则跳过此回圈

if (x % 2 ! = 0)

continue;

}

将会输出显示:

2 4 6 8

这是因为continue叙述的效果是跳过任何奇数的列印作用。

使用break命令,程式设计者能够选择和主要终止条件一样的方式退出。请看下面的程式码,它的作用是输出显示质数列表(就是除了1和它本身,不能被其它数整除的数);

limit = 500;

to_test = 2;

while(TRUE)

{

testdiv = 2;

if (to_test>limit)

break;

while (TRUE)

{

if (testdiv> sqrt(to_test))

{

print “to_test”;

break;

}

//测试是否to_test可被testdiv除尽

if (to_test % testdiv == 0)

break;

testdiv = testdiv + 1;

}

to_test = to_test +1;

}

在前面的程式码中,有两个while回圈,外层回圈重复于1-500之间的所有数字,内层回圈实际进行对每个可能是公约数的测试。如果记忆体回圈找到了一个公约数,则该数字不是质数,因此不印出任何内容就break,因而退出内层回圈。另一方面,如果测试进行到了等于该数字的平方根,则可以安全地假定该数字一定是质数,列印该数后,退出内层回圈。最后,外层回圈在到达要测试的数字时,则会退出。本段程式码的结果是小于500的质数列表:

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193

197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307

311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421

431 433 439 443 449 457 461 463 467 479 487 491 499

请注意,对于这段程式码,break只中断内层while回圈,这点是十分重要的。

还有另一种结构称为foreach,只能用于阵列的使用,我们会在稍后第11章介绍它的用法。

关于无穷回圈的注意事项

如果以前曾用过另一种语言程式设计,可能有过不小心弄了个无穷回圈的经验(回圈结构的退出条件永远不会为真,因此永远无法退出),当想到发生这种情况时,要做的第一件事情是终止程式,否则程式会永远地执行,浪费大量CPU资源。不过中断PHP的script是指什么呢?按浏览器上的stop(停止)按钮就够了吗?

实际上,这要取决于某些PHP配置的设定,可以设定PHP引擎忽略来自浏览器的中断(如按stop),也可以对script的执行施加一个时间限制(因此「永远」这件事就不会发生了),PHP4的预设设定是忽略中断,但一个script的执行时间限制为30秒,这样的时间限制意谓著你可以忽略所遭遇的无穷回圈问题了。

关于PHP设定配置的更多资讯,请参阅本书第三十七章。

可替换的控制语法

PHP提供了另一种开始和结束if、switch、for和while结构的方式。它用冒号(:)替代了初始的左大括弧,而且该结构的特殊结束叙述(endif、endswich、endfor和endwhine)替代右大括弧。

例如,if语法变成:

if (expression):

statement1

statement2



endif;

或是

if (expression):

statement1

statement2



elseif(expression2):

statement3



else:

statement4



endif;

请注意,else和endif部分也是用冒号开始的。而其相对应的while语法是:

while(expression):

statement

endwhile;

使用哪一种语法是个好人喜好的问题。这种非标准语法在PHP中的存在主要是由于历史原因,而且也是不了那些习惯于以前PHP版本的人们。在本己中我们还是坚持使用标准语法。

终止执行

有时在程式码执行中间想要放弃,PHP提供一些结构不帮助你完成,exit()结构城传入字串或是当作参数,然后将参数印出并中断程式执行,PHP程式内任何位于exit()之前的输出皆正常的送到使用者的浏览器,而之后任何的程式将不会被解析,并立即中断程式。如果传递的参数不是字串而是数字的话,该数字会成为程式执行的回传值,由于exit是一种结构而且非一个函数,所以你可以不需要传递任何参数,甚至不加上括号。

die()是另一种exit()的相似结构而且事实上运作功能是相同的(我们就习惯使用die(),因为它是比较容易输入的),那么exit()与die()的使用时机在哪能里呢?一个可能的用法就是当你的程式认为不需要传送资讯的时候,而你也不想使用层层的分支结构来测试是否继续执行,此时你可以用这些结构来中断网页的输出,然而可能会使得较长程式码的档案难以阅读与侦错。

而die()较好的使用时机是在问题出现之前。如果某种韶山外情况发生时就会破坏script的执行,所以一定要养成测试情况的好习惯,旯好是在某条提示资讯中带出die()叙述。如果一切在预料之中,则永远不会启动die();但如果出问题,就会有自己的除错资讯显示,而不会只知道PHP大略显示的可能错误资讯。

例如,请看下面的虚拟程式码,其中假定在进行资料库连接与使用:

connection = make_database_connection();

if (!connection)

die (“No database connetion!” );

use_database_connection(connection);

这个例子中假设一个make_database_connection()函式,它像其它PHP函式一样会传回有用的值,也就是如果失败传回一个非真值。下面的例子比前面的程式码更紧奏,利用了这个优先顺序比「=」指定运算子更低的情况来配合。

counection = make_database_connection()

or die (“No database connection!”);

use_database_connection(connection);

这样的方式是有效的,因为or运算子短路了,因此die()仅在运算式「connection = make_database eonnection()」的值为非真时开始求值。因为指定运算式的值就是被指定的值,这样的结果其实等于前一版本。)请注意如果我们使用||而不是or的话,由于||拥有比指定运算更高的优先顺序,所以会使得connection最后的值为||所判断的真或否的结果)

摘要

PHP有一系列像C语言风格的控制结构,其中分支或回圈取决于boolean运算式的值,这些运算式可以使用boolean运算子(and、or 、xor、!、&&和||)组合在一起。If和switch用在比较简单的分支;while、do-while和for用于回圈,exit和die可终止script的执行。

表7-3 总结了本章中所有控制结构,不过选择性使用的「..endif」语法除外。

表7-3 PHP控制结构




\n

出处:南方Linux

\n