2011-01-05 9 views
1

Tclを使用してプログラムを教えようとしています。私がTclの学習を動機づけようとしてきた仕事は、8人の女王問題を解決することです。プログラムを作成する私のアプローチは、ソリューションを逐次「プロトタイプ化」することです。
ネストされたforループを正しく配置することに関する以前の質問をして助けになりました。
私のコードの次の開発で、同じインタプリタエラーが発生することがわかりました。「間違った#引数」
whileループコマンドの前の行の末尾に括弧を入れています。 私はwhileループの引数を中括弧で入れようとしました。これにより、異なるエラーが生成されます。私は以前の質問の回答者によって提案されたTcl構文のmanページを誠実に理解しようとしました。 コードはこちらforループの 'next' argにwhileループを使用しようとすると、#argエラーが発生する

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 
    } 
} 

どこが間違っていますか?

EDIT:私のテキストに記載されているように
@slebetman明確な回答を提供するために、私は以下ブレースwhile文の引数は(確かにそれは私が最初にコードを書いた方法だった)正確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』がしばらくのコンパイル{R2($のR2Pしばらく....」

答えて

5

ている間は、2つだけの引数だからあなたのコードを期待しています。次のとおりです:

while {$r2($r2p) == $notallowd} {incr r2p} 

私は、それはwhileを置くために変わった場所だと言わざるを得ないが。

アレイr2にアクセスする際に発生した2番目のエラーの問題として、その値に到達するために$置換を使用していないという問題があります。これは、変数がTclでどのように機能するかの誤解に由来するやや異なる問題です。

Tcl変数は実際には他の言語の変数と同じように動作しません。変数の値にアクセスするには、setコマンドの戻り値(たとえば[set r2p])を使用するか、ショートカットとして変数名の前に$文字を追加して$置換を使用する必要があります(たとえば$r2p)。一方、変数を操作するには、変数名自体を$記号なしで使用する必要があります(たとえば、r2p)。

これは本当に奇妙なことではありません。これは、ポインターがCで動作するのとまったく同じように動作します。CはCの代わりに*を使用します。あなたのコードで起こっていたこと

は、(式を処理するためにwhileifforなどで使用されるものである)exprのパーサがあなたのr2($r2p)を見て、変数のアクセスとしてそれを認識しないのでしようということです(sin()またはtan()またはround()のような)mathfuncとして実行してください。r2()機能がないので失敗します。


補足説明:

forwhileどちらもTCL構文の一部であることに留意すべきです。それらは単なる関数/コマンドです。他の言語と同様に、関数が引数をどのように受け入れるかは、関数がどのように記述されたかによって異なります。したがって、whileまたはforの使い方を理解するには、実際にはtcl構文のドキュメントではなく、それらのドキュメントを読む必要があります。

何が起こっているのより詳細な説明については、この他の質問に対する私の返事読む:evaluating an expression to true in a if statement with Tcl

+0

に疑問を編集を参照してください。 – JerryK

+0

それに対応して私の答えを編集しました。 2番目の問題は、配列r2の値にアクセスしようとしていますが、$置換または 'set'を使用していないことです。 – slebetman

+0

ありがとうございます。 Tclがどのように構文解析のためのコードを見ているのかについてのあなたの説明は、私のコードで将来の同様の誤りを発見するのに役立ちます。不足している$がなくなる前に、自分のコードを何度も見ていたでしょう。 Tclを学ぶことは困難な仕事を証明しています。たとえば、値にアクセスするための$の必要性を忘れるのは簡単です。 – JerryK

関連する問題