Question

i am new to ns2. In the following code

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

I want to create 50 nodes but while executing the tcl file it shows the error as "invalid command name "$n0" while executing "$n$i set X_[expr 10+round(rand()*40)]". I have provided nn to be 50.

Était-ce utile?

La solution

You've got two classes of problems with the code you posted.

Basic syntax problems

for {set i 0 }{$i < $val(nn)}{incr i }
{

This won't work because you need spaces between arguments to for (yes, for isn't a keyword in Tcl; it's just a regular command) and you must put the start of the body at the end of the line. You are strongly recommended to use One True Brace style coding; that's what Tcl's syntax makes most easy.

Here's how to fix that:

for {set i 0} {$i < $val(nn)} {incr i} {

Note that all I've done to fix it is move around (and insert) spaces.

Deeper syntax problems

    set n$i [$ns node]
    $n$i set X_[expr 10+round(rand()*40)]

These lines have a problem in that you're trying to use double substitution. Well sort of. The $ handling is really dumb, in that it checks for a non-empty “nice” variable name afterwards, substituting it if it is there and becoming a plain old $ otherwise. This means that $n$i is the concatenation of what you get from $n and $i.

The easiest fix is to use another variable as well:

    set thisnode [$ns node]
    set n$i $thisnode
    $thisnode set X_[expr 10+round(rand()*40)]

You can even roll those first two lines into one, since the result of set is the value that was just set:

    set n$i [set thisnode [$ns node]]
    $thisnode set X_[expr 10+round(rand()*40)]

But we really ought to encourage you to use arrays for this sort of thing, as they do allow double-substitution of a sort.

    set n($i) [$ns node]
    $n($i) set X_[expr 10+round(rand()*40)]

Those extra () make a big difference!

You could also use a list to store the generated items:

    lappend n [$ns node]
    [lindex $n end] set X_[expr 10+round(rand()*40)]

But I'd really be tempted to use a helper variable in that case:

    lappend n [set thisnode [$ns node]]
    $thisnode set X_[expr 10+round(rand()*40)]

Other things

You also ought to put your expression in curly braces. It doesn't matter in this particular case as it's not got any substitutions in it, but it's an extremely good habit to get into as it makes it much easier for Tcl to compile the expression in general; i.e., when the overall expression is a literal, Tcl can compile it ahead of time and that's fast, whereas when the expression is non-literal it can't be compiled until the last moment, has to be compiled each time through the loop, and can have a whole bunch of other hazards too. It would make a much larger difference if you were doing a loop over millions of things rather than 50…

It might be worth factoring the expression into a little procedure, for clarity:

proc random {from to} {
    expr {$from + round(rand() * ($to-$from))}
}
$n($i) set X_[random 10 50]

Write it (and debug it!) once and reuse it elsewhere. It's the Lazy Programmers' Way.

I'm guessing that this is really an NS2 question too. In which case you'll probably run into problems still: the underscore between the X and the [expr …] is a little surprising, unless you really have got objects with large numbers of very similar variables where you want to read (and then discard the value of) a random one of them. That would be… rather surprising, yes? I suspect you might be better off with:

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

Do you need to keep the references around? If not, you might even be OK with:

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

But that that's probably not what you want though; in real code you'll be wanting to refer to the nodes from elsewhere so you can put in links between them…

Autres conseils

Tcl works with whitespace-separated words (See http://tcl.tk/man/tcl8.5/TclCmd/Tcl.htm rules 1,2,3), and the syntax of the for command is

for start test next body

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

You need this:

 for {set i 0} {$i < $val(nn)} {incr i} {
    set n$i [$ns node]
    [set n$i] set X_[expr {10+round(rand()*40)}]
 }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top