表达和循环过程

时间:2017-04-25 16:49:10

标签: tcl

我有一些问题,希望任何人都可以解决我的问题,如下所示;

  1. 第一个问题;数学

    set a 3
    puts [format "%.3f" [expr ($a+2)/2]]
    

    为什么输出仍为2.000

  2. 第二个问题;如何停止/打破incr"第三次循环"过程并继续"第一次循环"过程

    for {set numA 0} {$numA < 5} {incr numA} {      ;#First Looping process
      for {set numB 0} {$numB < $oneNum} {incr numB} {  ;#Second Looping process
        for {set numC 0} {$numC < $twoNum} {incr numC} {    ;#Third Looping process
          if {$dataA == $dataB} {
            #How to stop incr "Third Looping" process and continue "First Looping" incr process
          }
        }
      }
    }
    

2 个答案:

答案 0 :(得分:1)

对于第一个问题,expr不知道它产生的结果是给一个想要浮点数的命令,因此它使用整数除法,因为两个操作数都是整数。

我们可以在不改变任何内容的情况下分几步完成整个过程:

set a 3
set b [expr ($a+2)/2]
puts "b=$b"
puts [format "%.3f" $b]

我也打印了中间值,以便您可以看到($a+2)/22; Tcl的整数除法向下舍入。鉴于这是真的,很遗憾format将值呈现为2.000

对于第二个问题,Tcl不支持多级break。尽管如此,它并不会成为一个问题,并且大多数情况下都可以通过战略性使用帮助程序来处理。

更详细地说,您可以使用break来停止当前最内层循环,但只能停止最内层循环。 {@ 1}}之间的Second Looping process不会被最内层嵌套级别的break停止。直接处理这个问题的最简单机制是自定义异常代码,但这并不简单:

set MyException 123;  # Small integer greater than 5
for {set numA 0} {$numA < 5} {incr numA} {                   #First Looping process
    for {set numB 0} {$numB < $oneNum} {incr numB} {         #Second Looping process
        try {
            for {set numC 0} {$numC < $twoNum} {incr numC} { #Third Looping process
                if {$dataA == $dataB} {
                    return -level 0 -code $MyException
                }
            }
        } on $MyException {} {
            break
        }
    }
}

您可以通过使用标志变量来避免使用非常棘手的自定义异常代码:

for {set numA 0} {$numA < 5} {incr numA} {               #First Looping process
    for {set numB 0} {$numB < $oneNum} {incr numB} {     #Second Looping process
        set foundIt false
        for {set numC 0} {$numC < $twoNum} {incr numC} { #Third Looping process
            if {$dataA == $dataB} {
                # Set the flag to indicate we've found our matching case
                set foundIt true
                # Terminate the inner loop
                break
            }
        }
        if {$foundIt} {
            break
        }
    }
}

这非常难看(特别是当逻辑变得更复杂时),但是有效。幸运的是,它并不经常出现。更常见的是,人们会像这样拆分代码:

proc innerSearch {numA} {
    global oneNum twoNum
    for {set numB 0} {$numB < $oneNum} {incr numB} {     #Second Looping process
        for {set numC 0} {$numC < $twoNum} {incr numC} { #Third Looping process
            if {$dataA == $dataB} {
                # Stop the Second Looping by returning from the procedure
                return
            }
        }
    }
}

for {set numA 0} {$numA < 5} {incr numA} {               #First Looping process
    innerSearch $numA
}

在实践中,这往往会更有意义,因为会使用更多的助记符名称。

答案 1 :(得分:1)

算术运算符&#34; /&#34;的输出取决于它所应用的数据类型。您有整数值,因此输出是整数。您可以将其中一个值转换为浮动,如下所示

puts [format "%.3f" [expr ($a+2)/double(2)]]
2.500

对于第二个问题,继续命令将停止第三个循环并转到第一个

for {set numA 0} {$numA < 5} {incr numA} {      ;#First Looping process
  for {set numB 0} {$numB < $oneNum} {incr numB} {  ;#Second Looping process
    for {set numC 0} {$numC < $twoNum} {incr numC} {    ;#Third Looping process
      if {$dataA == $dataB} {
        continue
      }
    }
  }
}