【问题标题】:Error: for loop in TCL Ffile错误:TCL 文件中的 for 循环
【发布时间】:2014-05-04 12:16:35
【问题描述】:

我是 ns2 的新手。 在以下代码中

     for {set i 0 }{$i < $val(nn)}{incr i }
     {
        set n$i [$ns node]
        $n$i set X_[expr 10+round(rand()*40)]
     }

我想创建 50 个节点,但是在执行 tcl 文件时,它在执行“$n$i set X_[expr 10+round(rand()*40)] 时显示错误为“invalid command name”$n0” "。我提供了 nn 为 50。

【问题讨论】:

  • 我看到了 3 个错误: 1. 左大括号应该与 for 位于同一行。 2. 您必须在大括号{} 之间添加一个空格。 3. $n$i 将替换为n 的值与i 的值连接。请改用[set n$i] set X_[expr 10+round(rand()*40)]。或数组。
  • 另一个可能的问题是$val(nn)。这意味着“获取val 数组的nn 成员的值。如果您在此之前使用过set val(nn) 50,那没关系。如果您使用过set nn 50 并期望获得的值使用$val(nn),你就有麻烦了。在后一种情况下,你应该把比较写成$i &lt; $nn
  • 所提供的任何答案对您有帮助吗?在这种情况下,您应该接受该答案以向浏览的访问者显示该答案有效。

标签: tcl


【解决方案1】:

您发布的代码存在两类问题。

基本语法问题

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)}]
}

但这可能不是您想要的;在实际代码中,您可能希望引用其他地方的节点,以便在它们之间建立链接……

【讨论】:

    【解决方案2】:

    Tcl 使用空格分隔的单词(参见http://tcl.tk/man/tcl8.5/TclCmd/Tcl.htm 规则 1、2、3),for 命令的语法是

    for 开始 测试 下一个 正文

    http://tcl.tk/man/tcl8.5/TclCmd/for.htm

    你需要这个:

     for {set i 0} {$i < $val(nn)} {incr i} {
        set n$i [$ns node]
        [set n$i] set X_[expr {10+round(rand()*40)}]
     }
    

    【讨论】:

    • 同样重要的是换行符(当不在大括号或双引号内,或者前面没有反斜杠时)是一个命令终止符
    猜你喜欢
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    • 2021-09-14
    • 2021-08-06
    • 2016-08-15
    • 1970-01-01
    • 2018-08-04
    相关资源
    最近更新 更多