尝试使用 while 循环来执行“下一个”操作。 for 循环的 arg 生成 #arg 错误
我正在尝试自学使用 Tcl 进行编程。我为自己设定的学习 Tcl 的任务是解决 8 个皇后问题。我创建程序的方法是连续“原型化”解决方案。
我之前问过一个与正确布局嵌套 for 循环相关的问题,并收到了有用的答案。
令我沮丧的是,我发现我的代码的下一个开发会创建相同的解释器错误:“错误的#args”
我一直小心地在 while 循环命令之前的行末尾有一个左大括号。 我还尝试将 whileloop 的参数放在大括号中。这会产生不同的错误。我真诚地尝试理解 Tcl 语法手册页 - 不太成功 - 由我之前问题的回答者建议。 这是代码
set allowd 1
set notallowd 0
for {set r1p 1} {$r1p <= 8} {incr r1p } {
puts "1st row q placed at $r1p"
;# re-initialize r2 'free for q placemnt' array after every change of r1 q pos:
for {set i 1 } {$i <= 8} {incr i} { set r2($i) $allowd }
for { set r2($r1p) $notallowd ; set r2([expr $r1p-1]) $notallowd ;
set r2([expr $r1p+1]) $notallowd ; set r2p 1} {$r2p <= 8} {
;# 'next' arg of r2 forloop will be a whileloop :
while r2($r2p)== $notallowd incr r2p } {
puts "2nd row q placed at $r2p" ;# end of 'commnd' arg of r2 forloop
}
}
我哪里出错了?
编辑:提供明确的答复@slebetman
正如我的文本中所述,我确实支撑了 whileloop 的参数(实际上这就是我第一次编写代码的方式),下面正是尝试的 r2 forloop 的布局:
for { set r2($r1p) $notallowd ; set r2([expr $r1p-1]) $notallowd ;
set r2([expr $r1p+1]) $notallowd ; set r2p 1} {$r2p <= 8} {
;# 'next' arg of r2 forloop will be a whileloop :
while { r2($r2p)== $notallowd } { incr r2p } } {
puts "2nd row q placed at $r2p" ;# end of 'commnd' arg of r2 forloop
}
但这会产生致命的解释器错误:“编译时未知数学函数‘r2’ while { r2($r2p ....”
Am attempting to teach myself to program using Tcl. The task i've set myself to motivate my learning of Tcl is to solve the 8 queens problem. My approach to creating a program is to successively 'prototype' a solution.
I have asked an earlier question related to the correctly laying out the nested for loops and received a helpful answer.
To my dismay I find that the next development of my code creates the same interpreter error : "wrong # args"
I have been careful to have an open brace at the end of the line preceding the while loop command.
I've also tried to put the arguments of the whileloop in braces. This generates a different error. I have sincerely tried to understand the Tcl syntax man page - not too successfully - suggested by the answerer of my earlier question.
Here is the code
set allowd 1
set notallowd 0
for {set r1p 1} {$r1p <= 8} {incr r1p } {
puts "1st row q placed at $r1p"
;# re-initialize r2 'free for q placemnt' array after every change of r1 q pos:
for {set i 1 } {$i <= 8} {incr i} { set r2($i) $allowd }
for { set r2($r1p) $notallowd ; set r2([expr $r1p-1]) $notallowd ;
set r2([expr $r1p+1]) $notallowd ; set r2p 1} {$r2p <= 8} {
;# 'next' arg of r2 forloop will be a whileloop :
while r2($r2p)== $notallowd incr r2p } {
puts "2nd row q placed at $r2p" ;# end of 'commnd' arg of r2 forloop
}
}
Where am I going wrong?
EDIT : to provide clear reply @slebetman
As stated in my text, I did brace the arguments of the whileloop (indeed that was how i first wrote the code) below is exactly the layout of the r2 forloop tried:
for { set r2($r1p) $notallowd ; set r2([expr $r1p-1]) $notallowd ;
set r2([expr $r1p+1]) $notallowd ; set r2p 1} {$r2p <= 8} {
;# 'next' arg of r2 forloop will be a whileloop :
while { r2($r2p)== $notallowd } { incr r2p } } {
puts "2nd row q placed at $r2p" ;# end of 'commnd' arg of r2 forloop
}
but this generates the fatal interpreter error : "unknown math function 'r2' while compiling while { r2($r2p .... "
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
虽然期望只有两个参数。所以你的代码应该是:
尽管我不得不说,这是一个放置
while
的奇怪地方。至于尝试访问数组 r2 时生成错误的第二个问题,问题是您没有使用 $ 替换来获取该值。这是一个稍微不同的问题,它源于对 Tcl 中变量如何工作的误解。
Tcl 变量的工作方式实际上与其他语言中的变量不同。要访问变量的值,您必须使用
set
命令的返回值(例如[set r2p]
),或者作为快捷方式,使用 $ 替换为在变量名称前面附加 $ 字符(例如$r2p
)。另一方面,要操作变量,您必须使用变量名称本身,不带 $ 符号(例如r2p
)。这并不像听起来那么奇怪。这与 C 中指针的工作方式完全相同,只是 C 使用 * 字符而不是 $。
您的代码发生的情况是 expr 解析器(这是
while
、if
、for
等用来处理表达式的)看起来在您的r2($r2p)
处,并且不将其识别为变量访问,因此尝试将其作为 mathfunc 执行(例如sin()
或tan ()
或round()
) 然后失败,因为没有r2()
函数。补充说明:
需要注意的是,
for
和while
都不是 tcl 语法的一部分。它们只是您调用的函数/命令。与任何其他语言一样,函数如何接受其参数取决于它的编写方式。因此,要弄清楚如何使用while
或for
,您确实需要阅读它们的文档而不是 tcl 语法文档。请阅读我对另一个问题的回复,以更详细地解释发生的情况:使用 Tcl 将 if 语句中的表达式计算为 true
While expects only two arguments. So your code should be:
though I have to say, that's a weird palce to put a
while
.As for your second problem of an error generated while trying to access the array
r2
, the problem is you didn't use $ substitution to get to that value. That is a slightly different problem which stems from a misunderstanding of how variables work in Tcl.Tcl variables don't really work the same way as variables in other languages. To access the value of a variable you must either use the return value of the
set
command (for example[set r2p]
) or, as a shortcut, use $ substitution by appending the $ character in front of your variable name (for example$r2p
). On the other hand, to manipulate a variable you must use the variable name itself without the $ sign (for exampler2p
).This is not really as strange as it sounds. This works exactly the same way pointers work in C only C uses the * character instead of $.
What was happening with your code is that the expr parser (which is what is used by
while
,if
,for
etc to handle expressions) looks at yourr2($r2p)
and doesn't recognize it as a variable access and so tries to execute it as a mathfunc (likesin()
ortan()
orround()
) which then fails because there is nor2()
function.Additional explanation:
It should be noted that neither
for
norwhile
are part of tcl syntax. They are merely functions/commands that you call. Like in any other language, how a function accepts its arguments depends on how it was written. So to figure out how to usewhile
orfor
you really need to read the documentation for them instead of the tcl syntax documentation.Read my reply to this other question for a more detailed explanation of what's going on: evaluating an expression to true in a if statement with Tcl