如何修复 tcl 中的“无法读取 "node_(0)":没有这样的变量”错误?
How to fix ‘can't read "node_(0)": no such variable’ error in tcl?
我正在设置一个网络环境,其中有 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!
请帮帮我,我卡了好久
加四行,模拟即可运行.
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
)
Link 到编辑后的文件:https://www.dropbox.com/s/m7zsnga6wf29r95/2Ezio-Auditore-DSR.tcl?dl=0
所有 ~3500 ns2 模拟前 https://drive.google.com/drive/folders/0B7S255p3kFXNSmRYb2lGcDRUdWs?usp=sharing
编辑:添加了@Donal Fellows 的 'argument parser',现在可以 运行 和 $ 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
只要 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
和表达式求值之间缺少space;在将结果作为单个参数输入 lindex
之前连接两个字符串! (lindex
只有一个参数 returns 那个参数,使用“优雅地什么都不做”的原则。)这在所有情况下甚至在语法上都不正确,但可能在您尝试并结果的情况下在 val(nn)
中被设置为类似于字符串 -nn 101
的内容。现在,<
运算符(在节点生成循环中) 将在 任一 侧看起来不正确时使用 ASCII 排序-numeric 并且该字符串中有额外的垃圾,因此它绝对是非数字的。哦亲爱的。 (-
是 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 中 space 很重要!
我正在设置一个网络环境,其中有 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!
请帮帮我,我卡了好久
加四行,模拟即可运行.
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
)
Link 到编辑后的文件:https://www.dropbox.com/s/m7zsnga6wf29r95/2Ezio-Auditore-DSR.tcl?dl=0
所有 ~3500 ns2 模拟前 https://drive.google.com/drive/folders/0B7S255p3kFXNSmRYb2lGcDRUdWs?usp=sharing
编辑:添加了@Donal Fellows 的 'argument parser',现在可以 运行 和 $ 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
只要 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
和表达式求值之间缺少space;在将结果作为单个参数输入 lindex
之前连接两个字符串! (lindex
只有一个参数 returns 那个参数,使用“优雅地什么都不做”的原则。)这在所有情况下甚至在语法上都不正确,但可能在您尝试并结果的情况下在 val(nn)
中被设置为类似于字符串 -nn 101
的内容。现在,<
运算符(在节点生成循环中) 将在 任一 侧看起来不正确时使用 ASCII 排序-numeric 并且该字符串中有额外的垃圾,因此它绝对是非数字的。哦亲爱的。 (-
是 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 中 space 很重要!