💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# Tcl 中的控制流 > 原文: [https://zetcode.com/lang/tcl/flowcontrol/](https://zetcode.com/lang/tcl/flowcontrol/) 在 Tcl 教程的这一部分中,我们将讨论流控制。 我们将定义几个命令,这些命令使我们能够控制 Tcl 脚本的流程。 在 Tcl 语言中,有几个命令可用于更改程序流程。 运行程序时,其命令从源文件的顶部到底部执行。 逐一。 可以通过特定命令更改此流程。 命令可以多次执行。 有些命令是有条件的。 仅在满足特定条件时才执行它们。 ## `if`命令 `if`命令具有以下一般形式: ```tcl if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN? ``` `if`命令用于检查表达式是否为真。 如果为真,则执行命令主体。 主体用花括号括起来。 `if`命令计算一个表达式。 该表达式必须返回一个布尔值。 在 Tcl 中,1,是,`true`表示`true`,0,`no`,`false`表示`false`。 ```tcl !/usr/bin/tclsh if yes { puts "This message is always shown" } ``` 在上面的示例中,始终执行由`{ }`字符包围的主体。 ```tcl #!/usr/bin/tclsh if true then { puts "This message is always shown" } ``` `then`命令是可选的。 如果我们认为可以使用它,它将使代码更加清晰。 我们可以使用`else`命令创建一个简单的分支。 如果`if`命令后方括号内的表达式的计算结果为`false`,则将自动执行`else`命令后方的命令。 ```tcl #!/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"`。 ```tcl $ ./girlboy.tcl It is a girl ``` 我们可以使用`elseif`命令创建多个分支。 仅当不满足先前条件时,`elseif`命令才会测试其他条件。 请注意,我们可以在测试中使用多个`elseif`命令。 ```tcl #!/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`命令之后的主体。 ```tcl $ ./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`命令将返回一个空字符串。 ```tcl #!/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`打印到控制台。 ```tcl $ ./switch_cmd.tcl Select a top level domain name:sk Slovakia ``` 我们已将`sk`字符串输入到控制台,该程序响应了斯洛伐克。 ## `while`命令 `while`命令是一个控制流命令,它允许根据给定的布尔条件重复执行代码。 `while`命令在大括号括起来的块内执行命令。 每次将表达式求值为`true`时都将执行命令。 ```tcl #!/usr/bin/tclsh # whileloop.tcl set i 0 set sum 0 while { $i < 10 } { incr i incr sum $i } puts $sum ``` 在代码示例中,我们从一系列数字计算值的总和。 `while`循环包含三个部分:初始化,测试和更新。 该命令的每次执行都称为一个循环。 ```tcl set i 0 ``` 我们启动`i`变量。 它用作计数器。 ```tcl while { $i < 10 } { ... } ``` `while`命令后面大括号内的表达式是第二阶段,即测试。 执行主体中的命令,直到表达式的计算结果为`false`。 ```tcl incr i ``` `while`循环的最后第三阶段是更新。 计数器增加。 请注意,对`while`循环的不正确处理可能会导致循环不断。 ## `for`命令 如果在启动循环之前知道周期数,则可以使用`for`命令。 在此构造中,我们声明一个计数器变量,该变量在每次循环重复期间都会自动增加或减少值。 ```tcl #!/usr/bin/tclsh for {set i 0} {$i < 10} {incr i} { puts $i } ``` 在此示例中,我们将数字`0..9`打印到控制台。 ```tcl for {set i 0} {$i < 10} {incr i} { puts $i } ``` 分为三个阶段。 首先,我们将计数器`i`初始化为零。 此阶段仅完成一次。 接下来是条件。 如果满足条件,则执行`for`块中的命令。 然后进入第三阶段; 计数器增加。 现在,我们重复阶段 2 和 3,直到不满足条件并留下`for`循环。 在我们的情况下,当计数器`i`等于 10 时,`for`循环停止执行。 ```tcl $ ./forloop.tcl 0 1 2 3 4 5 6 7 8 9 ``` 在这里,我们看到`forloop.tcl`脚本的输出。 ## `foreach`命令 `foreach`命令简化了遍历数据集合的过程。 它没有明确的计数器。 它逐个元素地遍历一个列表,并且当前值被复制到构造中定义的变量中。 ```tcl #!/usr/bin/tclsh set planets { Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune } foreach planet $planets { puts $planet } ``` 在此示例中,我们使用`foreach`命令浏览行星列表。 ```tcl foreach planet $planets { puts $planet } ``` `foreach`命令的用法很简单。 `planets`是我们迭代的列表。 `planet`是具有列表中当前值的临时变量。 `foreach`命令遍历所有行星并将其打印到控制台。 ```tcl $ ./planets.tcl Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune ``` 运行上面的 Tcl 脚本将给出此输出。 ```tcl #!/usr/bin/tclsh set actresses { Rachel Weiss Scarlett Johansson Jessica Alba \ Marion Cotillard Jennifer Connelly} foreach {first second} $actresses { puts "$first $second" } ``` 在此脚本中,我们迭代列表的值对。 ```tcl foreach {first second} $actresses { puts "$first $second" } ``` 我们在每次迭代时从列表中选择两个值。 ```tcl $ ./actresses.tcl Rachel Weiss Scarlett Johansson Jessica Alba Marion Cotillard Jennifer Connelly ``` 这是`actresses.tcl`脚本的输出。 ```tcl #!/usr/bin/tclsh foreach i { one two three } item {car coins rocks} { puts "$i $item" } ``` 我们可以并行遍历两个列表。 ```tcl $ ./parallel.tcl one car two coins three rocks ``` 这是`parallel.tcl`脚本的输出。 ## `break`和`continue`命令 `break`命令可用于终止由`while`,`for`或`switch`命令定义的块。 ```tcl #!/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`循环。 ```tcl set r [expr 1 + round(rand()*30)] ``` 在这里,我们计算出 1..30 之间的随机数。 `rand()`是内置的 Tcl 过程。 它返回一个从 0 到 0.99999 的随机数。 `rand()*30`返回 0 到 29.99999 之间的随机数。 `round()`过程将最终数字四舍五入。 ```tcl $ ./breakcommand.tcl 28 20 8 8 12 22 ``` 我们可能会得到这样的东西。 `continue`命令用于跳过循环的一部分,并继续循环的下一个迭代。 可以与`for`和`while`命令结合使用。 在下面的示例中,我们将打印一个数字列表,这些数字不能除以 2 而没有余数。 ```tcl #!/usr/bin/tclsh set num 0 while { $num < 100 } { incr num if {$num % 2 == 0} { continue } puts "$num " } puts "" ``` 我们使用`while`循环遍历数字`1..99`。 ```tcl if {$num % 2 == 0} { continue } ``` 如果表达式`num % 2`返回 0,则所讨论的数字可以除以 2。执行`continue`命令,并跳过循环的其余部分。 在我们的情况下,循环的最后一个命令将被跳过,并且数字不会打印到控制台。 下一个迭代开始。 在 Tcl 教程的这一部分中,我们正在讨论控制流结构。