2022年的 Tcl/Tk 编程入门参考 5.条件、遍历、循环
象喻
2022年04月15日 15:05
收录于文集
共23篇

控制结构:条件、遍历、循环

这是编程语言普遍具有的控制特性,在介绍之前,让我先介绍一下Tcl/Tk里的布尔值。

布尔值

布尔值是编程语言中,普遍存在的一种数据类型。即便没有这种数据类型,也会有这个概念,比如Tcl/Tk。

布尔值表示 "是、非&#​34; 或者 "真、假&#​34; 这么一个成对的概念。Tcl语言里都是字符串,它通过一些特定字符表示布尔值。首先,很好理解的表示布尔值的单词(大小写均可):

yes, no

true, false

on, off

其次,数值 1, 0

代码块
Shell
自动换行
复制代码
string is boolean "on"
#>> 1
复制成功

但是实际上tcl语言中还有很多情况表示布尔值:

代码块
Shell
自动换行
复制代码
# 请看下例,做条件判断时,0以外的数值都被认为“真”,负值也是“真”,只有0代表“假”
if 0.1 {puts "yes"}
#>> yes

# 但是注意,单纯判断字符串时,1和0以外的数字不是布尔值
string is boolean 0.1
#>> 0
复制成功

此外,布尔值单词的一部分,也被认为是布尔值(😱这是极其坑爹的设定)

代码块
Shell
自动换行
复制代码
# 以下都代表"真"
string is boolean "t"
string is boolean "tr"
string is boolean "tru"
string is boolean "ye"
# 对应的:f, fa, fal, fals, n 都代表"假"

# 注意:字母 o 不会被认为是布尔值,因为on和off开头都是o
string is boolean o
>> 0
# 但是of可以用来表示"假",因为它是off的一部分
复制成功

cut-off

if  条件

如果 {表达式结果为"真&#​34;} 那么 {搞点事情~}

基本用法:if {表达式} then {代码段}

if命令用于条件执行。它需要两个必要参数:一个参数是表达式,另一个是代码段,而then参数是可选的。当表达式运算结果为真时就会执行代码段。

表达式可以是多行语句,结果必须是布尔值。并不局限于数学表达式,其具体可执行的范围,跟expr命令一样,可以参考expr命令的文档。then这个参数是可以省略的,主要用于加强代码的可读性。

代码块
Shell
自动换行
复制代码
if {2 > 1} {puts "2333"}
>> 2333

set vb 3
if {
    $vb == 1
    || $vb == 2
    || $vb == 3
} then {
    puts "行数比较多时,then参数可以提升代码可读性——Bilibili 象喻"
}
复制成功

else

else参数:如果表达式结果为“假”时,就运行一段代码。

if {表达式} ?then? {代码段} else {代码段2}

如果 {表达式结果为"真&#​34;} 那么 {搞点事情~} 否则 {另外搞点事情~}

代码块
Shell
自动换行
复制代码
set vb 233
if {$vb == 1} {
    puts "vb is one"
} else {
    puts "vb is not one"
}
#>> vb is not one
复制成功

elseif

elseif类似于在else后面再接一个if命令。一个if命令可以有多个elseif。

如果 {表达式结果为"真&#​34;}  {搞点😼事情}

要不换个姿势 {表达式2结果为"真&#​34;}  {搞点*事情}

再试一次 {表达式3结果为"真&#​34;}  {搞点🦊事情}

实在不行 {搞点🐼事情}

代码块
Shell
自动换行
复制代码
set vbl 3

if {$vbl == 1} {
    puts "vbl is 1"
} elseif {$vbl == 2} {
    puts "vbl is 2"
} elseif {$vbl == 3} {
    puts "vbl is 3"
} else {
    puts "space.bilibili.com/494695230"
}
#>> vbl is 3
复制成功

*注意,虽然看上去像语法,但是if命令就是普通的Tcl命令,它有接受多个参数,其中像then、else和elseif这样的参数属于预设参数,后接的代码段,无论多长本身也是参数。

switch 匹配

switch命令用于进行匹配操作,该命令需要指定一个字符串来跟多个值进行匹配,每个进行匹配的值都有一段对应的代码段,当字符串与匹配值相同时,就执行这个匹配值对应的代码段。

*提示:Tcl语言的字符串只要不是{}括起来的,都能进行变量替换和命令替换。

该命令用于简化需要使用多个 if...elseif 语句的情况,也就是说如果不怕麻烦的话,该命令也可以用if...elseif语句来改写。

代码块
Shell
自动换行
复制代码
set x 3

switch $x {
1 {puts 1}
2 {puts 2}
default {puts "other"}
}
#>> other
复制成功

可选参数

 -exact  严格模式(默认值,精确识别特殊字符,比如: *、$ )  -glob  与 string match 命令相同,支持 * ? 匹配  -regexp  正则表达式  -nocase  不区分大小写  --  表示参数结束(用于匹配字符串以 - 开头时,这会导致tcl误认为是参数-xxx)

foreach 遍历

foreach  变量名  列表  ?变量名2?  ?列表2?  {代码段}

用于遍历列表中的所有元素:

  • 按顺序将元素赋值给变量,并执行代码段

  • 完毕后,将下一个元素赋值给变量,再次执行代码段……

  • 不断重复直到遍历全部元素

*提示:如果元素不足时,用空字符代替

 

代码块
Shell
自动换行
复制代码
# 简单例子:依次显示 1、2、3
foreach x {1 2 3} {
  puts $x
}

# 双列表:先将1给x,a给y,运行代码;再将2给x,b给y;最后将3给x,y被指派空字符
foreach x {1 2 3} y {a b} {
  puts "$x : $y"
}
#>>1 : a
#>>2 : b
#>>3 : 

# 双变量的例子,本例中指定了两个变量:x和y
foreach {x y} {1 2 3 4 5} {
    puts "$x : $y"
}
#>>1 : 2
#>>3 : 4
#>>5 : 

# 第一轮:将1赋值给x;将2赋值给y
# 第二轮:依序,将3赋值给x;将4赋值给y
# 第三轮:继续,将5赋值给x;此时列中没有其它元素了,y为空字符
复制成功

break 中断

break中止当前的遍历/循环,直接结束遍历/循环命令。也有叫它“跳出”的。

 

代码块
Shell
自动换行
复制代码
# 本例中,如果元素值为2,则中止foreach命令
foreach x {1 2 3 4} {
    puts $x
    if {$x == 2} {break}
    puts "----"
}
#>>1
#>>----
#>>2

# break命令直接中止当前遍历/循环,所以在break语句后面的代码不会执行
复制成功

continue 跳过

continue 跳过本轮遍历/循环,直接进入下一轮

代码块
Shell
自动换行
复制代码
# 本例中,如果元素值为2,则跳过本轮,接着进行下一轮
foreach x {1 2 3 4} {
    if {$x == 2} {continue}
    puts $x
}
#>>1
#>>3
#>>4

# continue不会中止整个遍历/循环,只会跳过本轮,直接进行下一轮
# 与break命令类似,continue命令也需要留意前后代码的顺序
# 一轮中:在continue前面的代码仍然会执行,只有后面的代码会被跳过
复制成功

incr 增加

incr 给变量增加数值,主要搭配下面介绍的循环命令。

incr 变量名 ?增量?  (变量值和增量都必须为整数)

代码块
Shell
自动换行
复制代码
set x 1
incr x
puts $x
#>> 2

incr x 231
puts $x
#>> 233

# 变量不存在时,incr命令会自动创建变量
incr y 666
puts $y
#>> 666
复制成功

for 循环

for  起始定义  测试条件  每轮最后执行的语句  {代码段}

For命令,也就是for循环,是编程语言里的经典循环语句,各个编程语言的具体实现略有不同,但是功能都类似。

TCL语言的for命令需要四个参数:第一个参数起始定义,第二测试条件,第三个参数是每轮最后执行的语句,最后一个参数是{代码段}。

for命令的运行方式:

  • 首先只运行一次<起始定义>部分的语句

  • 然后进入循环,判断<测试条件>的执行结果是否为真,如果结果为真,就运行{代码段}中的代码,代码段运行完毕之后,再运行<每轮最后执行的语句>,运行完毕之后,本轮结束,进入下一轮

  • 下一轮继续判断<测试条件>的执行结果是否为真,如果为真,就继续执行{代码段}和<每轮最后执行的语句>,然后继续进入下一轮

  • 一直循环直到<测试条件>为假,结束命令。

 

代码块
Shell
自动换行
复制代码
# 先定义x变量,进入循环。每轮末尾给x变量值加1,当x不小于3时,跳出循环
for {set x 1} {$x < 3} {incr x} {
    puts $x
}
#>> 1
#>> 2
# Tcl语言中x变量在循环结束后会保留,其它语言大都会删除该变量
puts $x
#>> 3

for {set x 1} {$x < 5} {incr x} {
    puts $x
    set x 5
}
#>> 1
puts $x
#>> 6
复制成功

while 循环

while 测试条件 {代码段}

只要测试条件为"真&#​34;,就会反复执行代码段

 

代码块
Shell
自动换行
复制代码
set x 1
while {$x<3} {
    puts "x is $x"
    incr x
}
#>> x is 1
#>> x is 2

puts $x
>> 3

# while命令在使用时要保证能够跳出循环,否则会陷入无限循环:
while 1 {
    puts "无限循环"
}
复制成功