Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
反向打印列表:TCL_Tcl_Reverse_Expect - Fatal编程技术网

反向打印列表:TCL

反向打印列表:TCL,tcl,reverse,expect,Tcl,Reverse,Expect,我正在读Don Libes的“Expect探索:基于TCL的工具包…” 本章末尾的问题是“编写一个过程来反转字符串。如果您编写了一个迭代解决方案,现在就编写一个递归解决方案,反之亦然。” 读到目前为止,我决定尝试以下方法: set list {a b c d e f g} for {set index [expr [llength $list]-1]} {$index>=0} {incr $index - 1} { for {set i [expr [llength $list]-1

我正在读Don Libes的“Expect探索:基于TCL的工具包…”

本章末尾的问题是“编写一个过程来反转字符串。如果您编写了一个迭代解决方案,现在就编写一个递归解决方案,反之亦然。”

读到目前为止,我决定尝试以下方法:

set list {a b c d e f g}


for {set index [expr [llength $list]-1]} {$index>=0} {incr $index - 1} {

for {set i [expr [llength $list]-1]} {$i>=0} {incr $i - 1} {

    puts [lindex $list $index]

}

}
但我得到了以下错误:

Error(s), warning(s):
wrong # args: should be "incr varName ?increment?"
    while executing
"incr $i - 1"
    ("for" body line 3)
    invoked from within
"for {set index [expr [llength $list]-1]} {$index>=0} {incr $index - 1} {

for {set i [expr [llength $list]-1]} {$i>=0} {incr $i - 1} {

    puts [lind..."
    (file "source_file.tcl" line 4)
g
我发现我没有正确地证明“index”变量,尽管我不确定为什么。 此外,这种方法是递归的还是迭代的

如有任何建议,将不胜感激


________解决方案____________________________________

根据@glenn提供的解决方案/方法,正确代码如下:

set list {a b c d e f g}



for {set i [expr {[llength $list]-1}]} {$i>=0} {incr i -1} {

    puts [lindex $list $i]

}

他的文章下面展示了许多其他示例。

首先,您要向incr传递3个参数:
$index
-
1
。如错误消息所示,incr最多接受2个参数。将“负1”指定为
-1
,不带空格

请仔细注意错误消息:

wrong # args: should be "incr varName ?increment?"
注意它是如何显示的
varName
——当您使用
$index
时,您传递的是变量的值,而不是名称。删除
$

for {set i [expr {[llength $list]-1}]} {$i>=0} {incr i -1} {
# .................................................. ^ ^^
#                                              varname increment

请注意expr:的参数周围的大括号:这是一个好习惯。

下面是

  • 递归的

    proc lreverse_rec {list} {
        if {[llength $list] == 0} return
        set procname [lindex [info level 0] 0]
        return [concat [lindex $list end] [$procname [lrange $list 0 end-1]]]
    }
    
    proc lreverse_tail {list {result {}}} {
        if {[llength $list] == 0} {return $result}
        lappend result [lindex $list end]
        set procname [lindex [info level 0] 0]
        tailcall $procname [lrange $list 0 end-1] $result
    }
    
  • 尾部递归

    proc lreverse_tail {list {result {}}} {
        if {[llength $list] == 0} {return $result}
        lappend result [lindex $list end]
        set procname [lindex [info level 0] 0]
        tailcall $procname [lrange $list 0 end-1] $result
    }
    
  • while循环a(来自本主题的a)

  • while循环b

    proc lreverse_while_b {list} {
        set result {}
        while {[llength $list]} {
            lappend result [lindex $list end]
            set list [lrange $list[set list {}] 0 end-1]
        }
        return $result
    }
    
  • while循环,但带有一些便利的列表操作程序

    proc pop {listVar} {
        upvar 1 $listVar list
        set result [lindex $list end]
        set list [lrange $list[set list {}] 0 end-1]
        return $result
    }
    proc push {listVar value} {
        upvar 1 $listVar list
        lappend list $value
    }
    proc shift {listVar} {
        upvar 1 $listVar list
        set result [lindex $list 0]
        set list [lrange $list[set list {}] 1 end]
        return $result
    }
    proc unshift {listVar value} {
        upvar 1 $listVar list
        set list [linsert $list[set list {}] 0 $value]
    }
    
    所有这些都导致了这个整洁的解决方案

    proc lreverse_listops {list} {
        set result {}
        while {[llength $list]} {push result [pop list]}
        return $result
    }
    
  • 我无法在网页上解释
    set list[…$list[set list{}].]
    习惯用法,但这是在变异值时对Tcl内部进行的优化。更新:在这里:(谢谢卡尔文先生)


    还有一些基准测试

    ## put all the above procedures here ...
    
    proc main {} {
        set list [list]
        for {set i 0} {$i <= 100} {incr i} {lappend list $i}
        foreach proc {
            lreverse_rec
            lreverse_tail
            lreverse_while_a
            lreverse_while_b
            lreverse_listops
        } {
            puts [format "%-20s %s" $proc [time [list $proc $list] 1000]]
        }
    }
    
    main
    

    为什么有2个for循环?FWIW,现在反转字符串是内置的:
    string reverse
    。类似地,反转列表是
    lreverse
    。尽管如此,尝试用手做这件事还是一个很好的练习。谢谢你!!这帮了大忙。我现在将回顾你的第一篇文章。顺便说一句,我将代码修改为:
    set list{a b c d e f g}对于{set I[expr{[lleength$list]-1}{$I>=0}{incr I-1}{put[lindex$list$I]}
    建议编写
    $list[set list{}
    而不是
    $list[unset list]
    。目标是相同的,但是使用
    set
    unset
    更有效。请参见中的“取消共享对象”。
    lreverse_rec         271.029 microseconds per iteration
    lreverse_tail        293.496 microseconds per iteration
    lreverse_while_a     75.541 microseconds per iteration
    lreverse_while_b     53.962 microseconds per iteration
    lreverse_listops     247.262 microseconds per iteration