Skip to content

Latest commit

 

History

History
403 lines (256 loc) · 8.86 KB

107.md

File metadata and controls

403 lines (256 loc) · 8.86 KB

Tcl 中的控制流

原文: https://zetcode.com/lang/tcl/flowcontrol/

在 Tcl 教程的这一部分中,我们将讨论流控制。 我们将定义几个命令,这些命令使我们能够控制 Tcl 脚本的流程。

在 Tcl 语言中,有几个命令可用于更改程序流程。 运行程序时,其命令从源文件的顶部到底部执行。 逐一。 可以通过特定命令更改此流程。 命令可以多次执行。 有些命令是有条件的。 仅在满足特定条件时才执行它们。

if命令

if命令具有以下一般形式:

if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?

if命令用于检查表达式是否为真。 如果为真,则执行命令主体。 主体用花括号括起来。

if命令计算一个表达式。 该表达式必须返回一个布尔值。 在 Tcl 中,1,是,true表示true,0,nofalse表示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"
}

我们有性别变量。 它具有"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 解释器来求值以下主体参数,并返回该求值结果。 如果最后一个模式参数为默认值,则它匹配任何内容。 如果没有任何模式参数与字符串匹配,并且没有给出默认值,那么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" }
}

在脚本中,我们提示您输入域名。 有几种选择。 例如,如果该值等于我们,则将"United States"字符串打印到控制台。 如果该值与任何给定值都不匹配,那么将执行默认主体,并将unknown打印到控制台。

$ ./switch_cmd.tcl 
Select a top level domain name:sk
Slovakia

我们已将sk字符串输入到控制台,该程序响应了斯洛伐克。

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

这是actresses.tcl脚本的输出。

#!/usr/bin/tclsh

foreach i { one two three } item {car coins rocks} {
    puts "$i $item"
}

我们可以并行遍历两个列表。

$ ./parallel.tcl 
one car
two coins
three rocks

这是parallel.tcl脚本的输出。

breakcontinue命令

break命令可用于终止由whileforswitch命令定义的块。

#!/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命令用于跳过循环的一部分,并继续循环的下一个迭代。 可以与forwhile命令结合使用。

在下面的示例中,我们将打印一个数字列表,这些数字不能除以 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 教程的这一部分中,我们正在讨论控制流结构。