0

次のような「if」ステートメントの短い構文を使用しています。

proc WriteParameter {Parameter Value} {
    # Ugly option - WORKS
    if {$Parameter eq "Unique"} {
        set Register ControlStatus
        set Data ${Value}0
        set Mask EF
    } else {
        set Register $Parameter
        set Data $Value
        set Mask {}
    }

    # Elegant option - DOESN'T WORK
    set Register [expr {$Parameter eq "Unique" ? "ControlStatus" : $Parameter}]
    set Data [expr {$Parameter eq "Unique" ? ${Value}0 : $Value}]
    set Mask [expr {$Parameter eq "Unique" ? EF : {}}]

    puts $Register-$Data-$Mask
    return 0
}
set Value 4E20 ;# Merely hexadecimal number
set Parameter Regular
WriteParameter $Parameter $Value

問題は、洗練されたオプションでは、'expr' ステートメントは常にその引数を整数として扱うため、'Data' が 4e+20 の値を取得することです。これは単に 'Value' の科学的表記法です。

ただし、「データ」を「値」にする必要があります (たとえば、外部レジスタに書き込むため)。

何か案は?

4

1 に答える 1

1

このexpr言語は、他の Tcl とはかなり異なります。そこでは、構文にもっと注意を払う必要があります。物事を"二重引用符で囲むと"役立ちます。

set Register [expr {$Parameter eq "Unique" ? "ControlStatus" : $Parameter}]
set Data [expr {$Parameter eq "Unique" ? "${Value}0" : $Value}]
set Mask [expr {$Parameter eq "Unique" ? "EF" : {}}]

ただし、 とは異なりif、腕の結果を数値に変換しようとしないため (C 定数の規則をほぼexpr使用して)、代わりに を使用したほうがよい場合があります。

set Register [if {$Parameter eq "Unique"} {string cat ControlStatus} {string cat $Parameter}]
set Data [if {$Parameter eq "Unique"} {string cat $Value 0} {string cat $Value}]
set Mask [if {$Parameter eq "Unique"} {string cat EF}]
# We can omit the else clause; the default is an empty string anyway

これは、Tcl 8.6.3 で導入された に依存しますstring cat(まあ、8.6.2 ですが、実際には回避したい I/O サブシステムにいくつかのバグがありました)。8.5 から 8.6.1 までのものを使用している場合は、代わりにこれを使用します。

set Register [if {$Parameter eq "Unique"} {return -level 0 ControlStatus} {return -level 0 $Parameter}]
set Data [if {$Parameter eq "Unique"} {return -level 0 ${Value}0} {return -level 0 $Value}]
set Mask [if {$Parameter eq "Unique"} {return -level 0 EF}]

はい、return -level 0その結果として値を与えるだけです。「明白で発見可能」…</p>

まだ 8.4 以前を使用している場合 (アップグレード、男! セキュリティ サポートが切れています!)、ちょっとしたヘルパー プロシージャが必要です。

proc value {value} {return $value}
set Register [if {$Parameter eq "Unique"} {value ControlStatus} {value $Parameter}]
set Data [if {$Parameter eq "Unique"} {value $Value 0} {value $Value}]
set Mask [if {$Parameter eq "Unique"} {value EF}]

上記のvalue手順は、Tcl の新しいバージョンでも機能しますが、バイトコードの効率が低下します。


ただし、上記のすべてについて、実際には別のことを行います。

set Register $Parameter
set Data $Value
set Mask ""
if {$Parameter eq "Unique"} {
    set Register ControlStatus
    append Data 0
    set Mask EF
}

scanまた、値を解析しformat、結果を 16 進数に変換するために使用することもあります(必要な場合)。そのように、表現だけでなくについて考える方がはるかに簡単です。

于 2014-12-31T22:30:38.587 に答える