Tcl中的流程控制
最后修改于 2023 年 10 月 18 日
在本Tcl教程中,我们讨论流程控制。我们定义了几个命令,使我们能够控制Tcl脚本的流程。
在Tcl语言中,有几个命令用于改变程序的流程。当程序运行时,它的命令从源文件的顶部到最底部依次执行。这种流程可以通过特定命令来改变。命令可以执行多次。有些命令是有条件的。它们只有在满足特定条件时才会执行。
if命令
if
命令具有以下通用形式
if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?
if
命令用于检查一个表达式是否为真。如果为真,则执行一个或多个命令体。命令体由大括号括起来。
if
命令计算一个表达式。表达式必须返回一个布尔值。在Tcl中,1、yes、true表示真,0、no、false表示假。
!/usr/bin/tclsh if yes { puts "This message is always shown" }
在上面的例子中,由{ }
字符括起来的命令体总是被执行。
#!/usr/bin/tclsh if true then { puts "This message is always shown" }
then
命令是可选的。如果我们认为它会使代码更清晰,就可以使用它。
我们可以使用else
命令来创建一个简单的分支。如果if
命令后面的方括号内的表达式计算结果为false,则自动执行else
命令后面的命令。
#!/usr/bin/tclsh set sex female if {$sex == "male"} { puts "It is a boy" } else { puts "It is a girl" }
我们有一个sex变量。它包含字符串"female"。布尔表达式计算结果为false,我们在控制台中得到"It is a girl"。
$ ./girlboy.tcl It is a girl
我们可以使用elseif
命令创建多个分支。elseif
命令测试另一个条件,当且仅当先前的条件未满足时才会测试。请注意,我们可以在测试中使用多个elseif
命令。
#!/usr/bin/tclsh # nums.tcl puts -nonewline "Enter a number: " flush stdout set a [gets stdin] if {$a < 0} { puts "the number is negative" } elseif { $a == 0 } { puts "the numer is zero" } else { puts "the number is positive" }
在上面的脚本中,我们有一个提示输入值的提示。我们测试该值是否为负数、正数或等于零。如果第一个表达式计算结果为false,则计算第二个表达式。如果先前的条件未满足,则执行else
命令后面的命令体。
$ ./nums.tcl Enter a number: 2 the number is positive $ ./nums.tcl Enter a number: 0 the numer is zero $ ./nums.tcl Enter a number: -3 the number is negative
多次运行示例。
switch命令
switch
命令将其字符串参数与每个模式参数按顺序匹配。一旦它找到一个与字符串匹配的模式,它就会通过递归地将其传递给Tcl解释器来评估后续的命令体参数,并返回该评估的结果。如果最后一个模式参数是default,那么它匹配任何内容。如果没有任何模式参数与字符串匹配,并且没有给出default,那么switch命令将返回一个空字符串。
#!/usr/bin/tclsh # switch_cmd.tcl puts -nonewline "Select a top level domain name:" flush stdout gets stdin domain switch $domain { us { puts "United States" } de { puts Germany } sk { puts Slovakia } hu { puts Hungary } default { puts "unknown" } }
在我们的脚本中,我们提示输入一个域名。有几个选项。例如,如果该值等于us,则将字符串"United States"打印到控制台。如果该值与任何给定值都不匹配,则执行default命令体,并将unknown打印到控制台。
$ ./switch_cmd.tcl Select a top level domain name:sk Slovakia
我们在控制台中输入了sk字符串,程序响应Slovakia。
while命令
while
命令是一个流程控制命令,它允许根据给定的布尔条件重复执行代码。
while
命令执行由大括号括起来的块内的命令。每次表达式计算结果为true时,都会执行这些命令。
#!/usr/bin/tclsh # whileloop.tcl set i 0 set sum 0 while { $i < 10 } { incr i incr sum $i } puts $sum
在代码示例中,我们计算某个数字范围内值的总和。
while
循环有三个部分:初始化、测试和更新。每次执行命令称为一个周期。
set i 0
我们初始化 i
变量。它用作计数器。
while { $i < 10 } { ... }
位于while
命令后面的大括号内的表达式是第二阶段,即测试。命令体中的命令被执行,直到表达式的计算结果为false。
incr i
while
循环的最后第三阶段是更新。计数器递增。请注意,不正确地处理while
循环可能会导致无休止的循环。
for命令
当循环开始前循环的周期数已知时,我们可以使用for
命令。在这个结构中,我们声明一个计数器变量,该变量在循环的每次重复期间都会自动增加或减少其值。
#!/usr/bin/tclsh for {set i 0} {$i < 10} {incr i} { puts $i }
在此示例中,我们将数字 0..9 打印到控制台。
for {set i 0} {$i < 10} {incr i} { puts $i }
有三个阶段。首先,我们将计数器i
初始化为零。此阶段仅执行一次。接下来是条件。如果满足条件,则执行for块内的命令。然后是第三阶段;计数器递增。现在我们重复阶段2和3,直到条件不满足并且for
循环退出。在我们的例子中,当计数器i
等于10时,for
循环停止执行。
$ ./forloop.tcl 0 1 2 3 4 5 6 7 8 9
在这里,我们看到了forloop.tcl
脚本的输出。
foreach命令
foreach
命令简化了对数据集合的遍历。它没有显式的计数器。它逐个元素地遍历列表,并将当前值复制到构造中定义的变量中。
#!/usr/bin/tclsh set planets { Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune } foreach planet $planets { puts $planet }
在本例中,我们使用foreach
命令遍历行星列表。
foreach planet $planets { puts $planet }
foreach
命令的用法很简单。planets
是我们遍历的列表。planet
是临时变量,它具有列表中的当前值。foreach
命令遍历所有行星并将它们打印到控制台。
$ ./planets.tcl Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune
运行上面的Tcl脚本将给出此输出。
#!/usr/bin/tclsh set actresses { Rachel Weiss Scarlett Johansson Jessica Alba \ Marion Cotillard Jennifer Connelly} foreach {first second} $actresses { puts "$first $second" }
在这个脚本中,我们遍历列表中的值对。
foreach {first second} $actresses { puts "$first $second" }
我们在每次迭代中从列表中选取两个值。
$ ./actresses.tcl Rachel Weiss Scarlett Johansson Jessica Alba Marion Cotillard Jennifer Connelly
#!/usr/bin/tclsh foreach i { one two three } item {car coins rocks} { puts "$i $item" }
我们可以并行遍历两个列表。
$ ./parallel.tcl one car two coins three rocks
break和continue命令
break
命令可用于终止由while
、for
或switch
命令定义的块。
#!/usr/bin/tclsh while true { set r [expr 1 + round(rand()*30)] puts -nonewline "$r " if {$r == 22} { break } } puts ""
我们定义了一个无休止的while
循环。我们使用break
命令来退出此循环。我们选择一个介于1到30之间的随机值并打印它。如果该值等于22,我们结束无休止的while
循环。
set r [expr 1 + round(rand()*30)]
这里我们计算1..30之间的随机数。rand
是一个内置的Tcl过程。它返回一个介于0到0.99999之间的随机数。rand()*30
返回一个介于0到29.99999之间的随机数。round
过程对最终数字进行四舍五入。
$ ./breakcommand.tcl 28 20 8 8 12 22
我们可能会得到类似这样的结果。
continue
命令用于跳过循环的一部分并继续循环的下一次迭代。它可以与for
和while
命令结合使用。
在以下示例中,我们打印一个无法被 2 整除而没有余数的数字列表。
#!/usr/bin/tclsh set num 0 while { $num < 100 } { incr num if {$num % 2 == 0} { continue } puts "$num " } puts ""
我们使用 while
循环迭代数字 1..99。
if {$num % 2 == 0} { continue }
如果表达式num % 2
返回0,则可以被2整除。执行continue
命令,跳过循环的其余部分。在我们的例子中,跳过了循环的最后一个命令,并且未将该数字打印到控制台。开始了下一次迭代。
在本Tcl教程中,我们讨论了流程控制结构。