ns:Avg:不能使用非数字字符串作为“+”的操作数

时间:2015-03-22 06:37:54

标签: file tcl ns2

这是一个模拟MM1队列服务器的代码(实际上不是一个重要的事实)。我试图获得每次运行队列中数据包数的平均值。鉴于我从文件中读取lambda的值,修改它,再次将其修改后的新值保存在文件中,然后使用当前值lambda运行模拟:

#Create a simulator object
set ns [new Simulator]

global ns tracefile namf Qsize Qbw Qlost Qmon Avgvals InterArrivalTime lambda

   proc readfile {filename} {
    set f [open $filename]
    set data [read $f]
    close $f
    return $data
}
proc writefile {filename data} {
    set f [open $filename w]
    puts -nonewline $f $data
    close $f
}


#Define different colors for data flow (for NAM)
$ns color 1 Blue

#Open the NAM trace file
set namf [open QMM1.nam w]
$ns namtrace-all $namf

set Qsize [open Qsize.tr w]
set Qbw   [open Qbw.tr   w]
set Qlost [open Qlost.tr w]   
set Avgvals [open Avgvals.tr a+]
set tracefile [open out.tr w]
$ns trace-all $tracefile


#set lambda and Mu

set mu     1100.0

catch {set lambda [readfile LamdaValue.tr]}
set lambda [expr {$lambda + 100.0}]
writefile LamdaValue.tr $lambda


#Create the Node to generate the traffic Queue and Server
set n1 [$ns node]
set n2 [$ns node]

# Since packet sizes will be rounded to an integer
# number of bytes, we should have large packets and
# to have small rounding errors, and so we take large bandwidth

#Create link between the two nodes
set link [$ns simplex-link $n1 $n2 100kb 0ms DropTail]

#Monitor the queue for link (n1-n2) for nam
$ns simplex-link-op $n1 $n2 queuePos 0.5


#set up a large Queue capacity (n1-n2)
$ns queue-limit $n1 $n2 100000

# generate random interarrival times and packet sizes

#Set arrivals to be exponential
set InterArrivalTime [new RandomVariable/Exponential]

#Avg=1/lambda
#$InterArrivalTime set avg_ [expr 1/$lambda]


set pktSize [new RandomVariable/Exponential]
$pktSize set avg_ [expr 100000.0/(8*$mu)]

#Set src to use UDP
set src [new Agent/UDP]
$src set fid_ 1
$ns attach-agent $n1 $src

# queue monitoring, write statistics to queueStat
set Qmon [$ns monitor-queue $n1 $n2 [open queueStat.out w] 0.1]
$link queue-sample-timeout


proc record {} {
global ns Qmon Qsize Qbw Qlost n1 n2 Avgvals lambda
set time 0.05
set now [$ns now]

# print in the file $Qsize the current queue size
# print in the file $Qbw the current used bandwidth
# print in the file $Qlost the loss rate

$Qmon instvar parrivals_ pdepartures_ bdrops_ bdepartures_ pdrops_ 
puts $Qsize "[expr $parrivals_-$pdepartures_-$pdrops_]"
puts $Qbw   "$now [expr $bdepartures_*8/1024/$time]"
set bdepartures_ 0                                
puts $Qlost "$now [expr $pdrops_/$time]"
$ns at [expr $now+$time] "record"
}   


proc finish {} {
    global ns tracefile namf Qsize Qbw Qlost Qmon
    $ns flush-trace 
    #Close the NAM trace file
    close $namf
    close $Qsize
    close $Qbw
    close $Qlost
    close $tracefile   
    #Execute NAM on the trace file
    #exec ./nam QMM1.nam & 
    exit 0 
} 

proc sendpacket {} {
    global ns src InterArrivalTime pktSize 
    set time [$ns now]
    $ns at [expr $time + [$InterArrivalTime value]] "sendpacket"
    set bytes [expr round ([$pktSize value])]
    $src send $bytes
}



proc Avg {} {
global ns Qmon Qsize Qbw Qlost n1 n2 Avgvals lambda

set sum 0.0
set c 1

set fid [open Qsize.tr r]
  set txt [read $fid]
  close $fid

  foreach {x} $txt {
    set sum [expr {$sum + $x}]
    incr c 1
  }


 set avg [expr $sum/$c]
puts $Avgvals "$lambda $avg"

}

set sink [new Agent/Null]
$ns attach-agent $n2 $sink
$ns connect $src $sink

proc repeatSim {} {
        global lambda
        if {$lambda < 1002} {
        exec ./ns QMM1.tcl &
        }
 }


    #Avg=1/lambda
    $InterArrivalTime set avg_ [expr 1/$lambda]
    puts "Lambda = $lambda"
        puts "Mu = $mu"
    $ns at 0.0 "record"
    $ns at 0.0001 "sendpacket"
    $ns at 1000.0 "Avg"
    $ns at 1000.0 "repeatSim"

#Run the simulation
$ns run

问题在于它执行前三个自我调用:

proc repeatSim {} {
        global lambda
        if {$lambda < 1002} {
        exec ./ns QMM1.tcl &
        }
}

然后它在标题中给出错误。 完整的错误声明是:

ns: Avg: can't use non-numeric string as operand of "+"
    while executing
 "expr {$sum + $x}"
    (procedure "Avg" line 12)
    invoked from within
"Avg"

我在代码中尝试了几次操作,但错误仍然以相同的方式显示。 你能说出问题所在吗?

1 个答案:

答案 0 :(得分:2)

如何调试代码的演练

让我们更仔细地查看该错误消息。

ns: Avg: can't use non-numeric string as operand of "+"
    while executing
"expr {$sum + $x}"
    (procedure "Avg" line 12)
    invoked from within
"Avg"

它表示+运算符的其中一个参数不是数字,而是在expr {$sum + $x}的过程的第12行调用Avg。 / p>

可能是哪个论点?什么可能真的错了?让我们看一下您的代码(为了清晰起见,重新缩进)。

proc Avg {} {
    global ns Qmon Qsize Qbw Qlost n1 n2 Avgvals lambda

    set sum 0.0
    set c 1

    set fid [open Qsize.tr r]
    set txt [read $fid]
    close $fid

    foreach {x} $txt {
        set sum [expr {$sum + $x}]
        incr c 1
    }

    set avg [expr $sum/$c]
    puts $Avgvals "$lambda $avg"
}

好的,有问题的行在foreach中,并且它用于添加$txt的字词(即从文件中读取)浮点数(因为sum初始化为0.0)。好吧,因为sum将继续保持浮点数,前提是要添加的所有值都是数字,我们必须有问题,文件中的一个单词不是数字。它不能成为别的因为表达本身就是括号,保证了在Tcl级别的可靠解释。 (expr $sum/$c不太好,但是在Tcl 8.5和8.6中可以预见,我们使用自定义高可靠性浮点到字符串转换器而不是标准C库中有点不稳定的那个。)

我们无法从提供的信息中了解违规的价值;错误跟踪没有记录它(它没有所有或者它太笨重)并且你没有提供失败的样本。如果您要进行调试,可以尝试将代码更改为:

proc Avg {} {
    global ns Qmon Qsize Qbw Qlost n1 n2 Avgvals lambda

    set sum 0.0
    set c 1

    set fid [open Qsize.tr r]
    set txt [read $fid]
    close $fid

    foreach {x} $txt {
        if {[catch {
            set sum [expr {$sum + $x}]
            incr c 1
        }] {
            puts "The value at index #$c ('$x') is not numeric"
        }
    }

    set avg [expr $sum/$c]
    puts $Avgvals "$lambda $avg"
}

如果事实证明问题在于您正在阅读的文件中有额外的metasyntax,则需要在将值加起来之前处理该问题。

你的代码也有一个错误:“平均值”会有点低,因为c会导致一个太大。