您发布的代码存在两类问题。
基本语法问题
for {set i 0 }{$i < $val(nn)}{incr i }
{
这不起作用,因为您需要在for 的参数之间有空格(是的,for 不是 Tcl 中的关键字;它只是一个常规命令)并且您必须将正文的开始在行的末尾。 强烈建议您使用One True Brace style 编码;这就是 Tcl 的语法最简单的地方。
解决方法如下:
for {set i 0} {$i < $val(nn)} {incr i} {
请注意,我为修复它所做的只是移动(并插入)空格。
更深层次的语法问题
set n$i [$ns node]
$n$i set X_[expr 10+round(rand()*40)]
这些行的问题在于您尝试使用双重替换。好吧。 $ 处理真的很愚蠢,因为它之后会检查一个非空的“好”变量名,如果它存在则替换它,否则变成一个普通的旧 $。这意味着$n$i 是您从$n 和$i 获得的内容的串联。
最简单的解决方法是也使用另一个变量:
set thisnode [$ns node]
set n$i $thisnode
$thisnode set X_[expr 10+round(rand()*40)]
您甚至可以将前两行合二为一,因为 set 的结果是刚刚设置的值:
set n$i [set thisnode [$ns node]]
$thisnode set X_[expr 10+round(rand()*40)]
但我们确实应该鼓励您使用数组来处理这类事情,因为它们确实允许对某种排序进行双重替换。
set n($i) [$ns node]
$n($i) set X_[expr 10+round(rand()*40)]
那些额外的(…) 有很大的不同!
您还可以使用列表来存储生成的项目:
lappend n [$ns node]
[lindex $n end] set X_[expr 10+round(rand()*40)]
但在这种情况下,我真的很想使用辅助变量:
lappend n [set thisnode [$ns node]]
$thisnode set X_[expr 10+round(rand()*40)]
其他事情
你还应该把你的表达式放在花括号里。在这种特殊情况下并不重要,因为它没有任何替换,但这是一个非常的好习惯,因为它使 Tcl 更容易编译一般的表达式;即,当整个表达式是文字时,Tcl 可以提前编译它并且速度很快,而当表达式是非文字时,它直到最后一刻才能编译,每次都必须通过循环编译,并且还可能有一大堆其他危害。如果您对数百万件事情而不是 50 件事情进行循环,那将产生更大的差异……
为了清楚起见,可能值得将表达式分解为一个小过程:
proc random {from to} {
expr {$from + round(rand() * ($to-$from))}
}
$n($i) set X_[random 10 50]
编写(并调试它!)一次,然后在其他地方重复使用。这是懒惰的程序员的方式。
我猜这也是一个 NS2 问题。在这种情况下,您可能仍然会遇到问题:X 和 [expr …] 之间的下划线有点令人惊讶,除非您确实有要读取的具有大量非常相似变量的对象(然后丢弃其中一个随机值。那将是……相当令人惊讶,是吗?我怀疑你可能会更好:
for {set i 0} {$i < $val(nn)} {incr i} {
set n($i) [$ns node]
$n($i) set X [expr {10+round(rand()*40)}]
}
您需要保留参考文献吗?如果没有,您甚至可以接受:
for {set i 0} {$i < $val(nn)} {incr i} {
[$ns node] set X [expr {10+round(rand()*40)}]
}
但这可能不是您想要的;在实际代码中,您可能希望引用其他地方的节点,以便在它们之间建立链接……