我想动态创建数组并为其赋值。
set num 0
foreach i {1 2 3} {
set count$i(sp) {$num}
incr num
set count$i(ep) [expr $num+1]
}
当我运行您的示例代码时,出现了此错误:
can't read "i(sp)": variable isn't array
这是因为count$i(sp)
的$i(sp)
部分看起来像是对现有数组i
的引用。
您需要使用大括号将$i
与(sp)
隔离开来:
set num 0
foreach i {1 2 3} {
set count${i}(sp) {$num}
incr num
set count${i}(ep) [expr $num+1]
}
这将创建三个数组:
tcl8.6.8> parray count1
count1(ep) = 2
count1(sp) = $num
tcl8.6.8> parray count2
count2(ep) = 3
count2(sp) = $num
tcl8.6.8> parray count3
count3(ep) = 4
count3(sp) = $num
请注意,$num
周围的大括号使用文字字符串$num
。 您需要删除这些大括号:
set num 0
foreach i {1 2 3} {
set count${i}(sp) $num
incr num
set count${i}(ep) [expr $num+1]
}
tcl8.6.8> parray count1
count1(ep) = 2
count1(sp) = 0
tcl8.6.8> parray count2
count2(ep) = 3
count2(sp) = 1
tcl8.6.8> parray count3
count3(ep) = 4
count3(sp) = 2
但是,请准确解释"动态创建 Tcl 数组"的含义。 您真的想要三个单独的数组,还是可以拥有一个具有更多名称的数组,如下所示:
set num 0
foreach i {1 2 3} {
set count($i,sp) $num
incr num
set count($i,ep) [expr $num+1]
}
tcl8.6.8> parray count
count(1,ep) = 2
count(1,sp) = 0
count(2,ep) = 3
count(2,sp) = 1
count(3,ep) = 4
count(3,sp) = 2
如果你可以避免使用这样的动态变量名称,那就这样做;它们通常比它们的价值更麻烦。(您可以改用"复合"元素名称,如$i,sp
。否则,也许是因为访问数组的其他代码,处理它们的最简单方法是使用upvar
为具有固定名称的变量创建别名。 特别是,upvar 0
为同一范围内的变量创建别名:
set num 0
foreach i {1 2 3} {
upvar 0 count$i ary
set ary(sp) {$num}
incr num
set ary(ep) [expr $num+1]
}
upvar 0
的唯一问题是您无法真正撤消它;这就是为什么您几乎总是只在过程中使用它,因此当过程退出时,别名自然消失。
变量别名在过程上下文中非常有效,比在多个位置使用复合变量名称要高效得多。
另外,{$num}
看起来很可疑。这不是错误的代码,因为它有一个正确的解释,但可能不会做你期望的事情,并且通常表明存在问题,因为$num
没有被替换。您可能更喜欢[list $num]
.
您可能喜欢使用dict
而不是array
:
set count {}
set num 0
foreach i {1 2 3} {
dict set count $i sp $num
incr num
dict set count $i ep [expr {$num + 1}]
}
set count ;# -> 1 {sp 0 ep 2} 2 {sp 1 ep 3} 3 {sp 2 ep 4}
dict get $count 3 ep ;# -> 4