【问题标题】:How to fix ‘can't read "node_(0)": no such variable’ error in tcl?如何修复 tcl 中的“无法读取“node_(0)”:没有这样的变量错误?
【发布时间】:2019-12-25 11:43:07
【问题描述】:

我正在建立一个网络环境,其中有 n 个节点,由一个带有 DSR 协议的圆圈包围。但是,当我修复了大部分错误时,我无法解决的最困惑的错误就像标题一样。如何修复“无法读取”node_(0)“:没有这样的变量”错误?我不是已经在第 86 行的 for 循环中定义了吗?

我找不到这个问题的解决方案以及我何时更改

set node_($i) [$ns node]

set node_($i) [$ns_ node]

这是完整的代码。

set val(chan)   Channel/WirelessChannel
set val(prop)   Propagation/TwoRayGround
set val(netif)  Phy/WirelessPhy
set val(mac)    Mac/802_11
set val(ifq)    CMUPriQueue
set val(ll)     LL
set val(ant)    Antenna/OmniAntenna
set val(ifqlan) 50
set val(nn)     0
set val(rp)     DSR
set val(x)      1000
set val(y)      1000
set val(r)      400

proc usage {} \
{
    global argv0
    puts "\nusage: $argv0 \[-nn node\] \[-r r\] \[-x x\] \[-y y\]\n"
    puts "note: \[-nn nodes\] is essential, and the others are optional.\n"
}

proc getval {argc argv} \
{
    global val
    lappend vallist nn r x y z
    for {set i 0} {$i < $argc} {incr i} {
        set arg [lindex $argv $i]
        if {[string range $arg 0 0] != "-"} continue
        set name [string range $arg 1 end]
        set val($name) [lindex $argv[expr $i+1]]
    }
}


getval $argc $argv
if {$val(nn) == 0} {
    usage
    exit
}


set ns [new Simulator]  

set tracefd [open circle.tr w]
$ns trace-all $tracefd

set namtracefd [open circle.nam w]  
$ns namtrace-all-wireless $namtracefd $val(x) $val(y)


proc finish {} \
{
    global ns tracefd namtracefd
    $ns flush-trace 
    #close the trace file
    close $tracefd
    close $namtracefd
    #execute nam on the trace file
    exec nam circle.nam &
    exit 0
}


set topo [new Topography]   

$topo load_flatgrid $val(x) $val(y)

create-god $val(nn)
$ns node-config     -addressType    def\
        -adhocRouting   $val(rp)\
        -llType         $val(ll)\
        -macType        $val(mac)\
        -ifqType        $val(ifq)\
        -ifqLan         $val(ifqlan)\
        -antType        $val(ant)\
        -propType       $val(prop)\
        -phyType        $val(netif)\
        -channelType    $val(chan)\
        -topoInstance   $topo\
        -agenttrace     ON\
        -routertrace    ON\
        -mactrace       OFF\
        -movementtrace  OFF

##################################
for {set i 0} {$i < $val(nn)} {incr i} {
    set node_($i) [$ns node]
    $node_($i) random-motion 0
    $node_($i) set X_ [expr $val(r) * cos($i * 2 * 3.14159 / $val(nn))]
    $node_($i) set Y_ [expr $val(r) * sin($i * 2 * 3.14159 / $val(nn))]
    $node_($i) set Z_ 0
    $ns initial_node_pos $node_($i) [expr $val(x) / 10]
}
##################################

set tcp [new Agent/UDP]
$ns attach-agent $node_(0) $tcp
set null [new Agent/Null]
$ns attach-agent $node_([expr $val(nn) / 2]) $null

set cbr [new Application/Traffic/CBR]
$cbr set packetSize_ 5000
$cbr set interval_ 0.05
$cbr attach-agent $tcp
$ns connect $tcp $null

$ns at 0.1 "$cbr start"
$ns at 3.0 "$cbr stop"
$ns at 5.0 "finish"
$ns run

当我输入 ns circle.tcl -nn 12 时,我期望输出:

num_node is set 12
warning: Please use -channel as shown in tcl/ex/wireless-mitf.tcl
INITIALIZE THE LIST xListHead
channel.cc:sendUp - Calc highestAntennaZ_and distCST_
SORTING LISTS ...DONE!

请帮帮我,我已经卡了很长时间了。

【问题讨论】:

  • 我不熟悉ns-2,但是如果你能得到完整的错误会更有用,尤其是知道错误发生在哪一行。在错误发生之前打印任何可能有用的变量也是找出可能出错的好方法。
  • 谢谢;您实际上提供了足够的信息,我可以推断出问题所在。

标签: tcl ns2


【解决方案1】:

添加四行,就可以运行模拟了。

set val(ifqlen)          50    ;# added (Line 7)
set val(nn)     10             ;# added (Line 10)
.
       -movementtrace  OFF \
       -ifqLen $val(ifqlen)    ;# added (Line 85)
.
for {set i 0} {$i < [expr $val(nn)]} {incr i} {
    set node_($i) [$ns node]   ;# added (Line 89)

set val(nn) 10 的原因:我没有让 [$argv] 工作。 ($ ns file.tcl -nn 10$ ns file.tcl nn 10

链接到编辑的文件:https://www.dropbox.com/s/m7zsnga6wf29r95/2Ezio-Auditore-DSR.tcl?dl=0

所有 ~3500 ns2 模拟 ex https://drive.google.com/drive/folders/0B7S255p3kFXNSmRYb2lGcDRUdWs?usp=sharing


编辑:添加了@Donal Fellows 的“参数解析器”,现在可以使用$ ns file.tcl -nn 12 运行。新示例https://www.dropbox.com/s/br6qaeg5kj73k14/4-circle-Ezio-Auditore.tar.gz?dl=0

ns2分析脚本https://drive.google.com/drive/folders/1rU_MFAEl1GCLMTJPLR3zbxPxkQQHkQ7T?usp=sharing

【讨论】:

    【解决方案2】:

    只要val(nn) 不大于零,就会产生该错误,然后是创建节点的循环:

    for {set i 0} {$i < $val(nn)} {incr i} {
        set node_($i) [$ns node]
        $node_($i) random-motion 0
        $node_($i) set X_ [expr $val(r) * cos($i * 2 * 3.14159 / $val(nn))]
        $node_($i) set Y_ [expr $val(r) * sin($i * 2 * 3.14159 / $val(nn))]
        $node_($i) set Z_ 0
        $ns initial_node_pos $node_($i) [expr $val(x) / 10]
    }
    

    将简单地决定它无事可做,甚至一次也不执行循环体。什么可能导致这种情况?好吧,如果我们看一下参数解析过程:

    proc getval {argc argv} \
    {
        global val
        lappend vallist nn r x y z
        for {set i 0} {$i < $argc} {incr i} {
            set arg [lindex $argv $i]
            if {[string range $arg 0 0] != "-"} continue
            set name [string range $arg 1 end]
            set val($name) [lindex $argv[expr $i+1]]
        }
    }
    

    我们可以看到很多问题,其中最大的就是这个(在set val($name)一行:

    lindex $argv[expr $i+1]
    

    这里的问题是$argv和表达式求值之间没有空格;在将结果作为单个参数输入lindex 之前连接两个字符串! (带有单个参数的lindex 仅返回该参数,使用“优雅地什么也不做”的原则。)这在所有情况下甚至在语法上都不正确,但可能是在您尝试并导致val(nn) 被设置的情况下类似于字符串-nn 101。现在,&lt; 运算符(在节点生成循环中)将使用 ASCII 排序,只要 任一方 看起来都是非数字 并且该字符串具有里面有额外的垃圾,所以它绝对不是数字的。哦亲爱的。 (- 是 ASCII 字符代码 45,0 是 ASCII 字符代码 48,所以 -0 之前。)这不是你想要的!

    这是参数解析器的固定版本:

    proc getval {argc argv} {
        global val
        for {set i 0} {$i < $argc} {incr i} {
            set arg [lindex $argv $i]
            if {[string index $arg 0] eq "-"} {
                set val([string range $arg 1 end]) [lindex $argv [incr i]]
            }
        }
    }
    

    记住,在 Tcl 中,空格很重要!

    【讨论】:

    • 真诚感谢您的回答。直截了当地解释我的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 2021-09-01
    相关资源
    最近更新 更多