回答:
我々は条件をチェックしたいとしa==b
(てみましょうa
とb
そのそれぞれ名前のレジスタに格納します)。
[ # Everything is wrapped in one big macro
[ # An inner macro for our *then* part
# <-- Stuff to execute if a==b here
2Q # Then quit the inner and outer macro
]sE # `E' is for Execution register ;)
la lb =E # if a==b, execute E
# if E is executed, it will quit the whole macro, so the rest is never reached:
# <-- Stuff to execute if a!=b here
]x # End macro; Execute
ましょう(foo)
、凝縮の目的のために、プレースホルダーになります:
[[(then)2Q]sE(condition)E(else)]x
[[thenaction]P][[elseaction]P][r]sI 2 4 =I x sI f
スタートですか?tehnおよびその他のアクションはスタック上にあり、「I
f」マクロはそれらをスワップし、条件付きで調整されます。スタックの最上部が実行され、未使用のマクロがIにドロップされてスタックがクリーンアップされます。2 4
比較するサンプルデータにすぎません。あるいは、[x]sI
より読みやすいと考えられる場合、パーツを比較に移動できます[[thenaction]P][[elseaction]P] 4 4 [r]sI =I x sI f
。f
スタックはその後きれいで、TATの例では、ちょうど...示さなければならない
dc
おり、OpenBSD dc
のif-then-else
構造を見た最初のページでした。dc
すべての主要なオペレーティングシステムで3つのフレーバーすべてを備えたファンバンドルが必要だと思います... o :-) ... if-then-else
上記の私の提案dc
は、r
コマンドが欠けているため、オリジナルでは機能しません... :-(
[[(if)2Q]si(condition)i(else)]x
マクロでラップし、if部分をその中の別のマクロでラップして、全体2Q
から抜け出すことができます。したがって、1 == 1の場合に1を印刷し、その後1を印刷する場合は、2を印刷します1[[1P2Q]si1=i2P]x
(ここでDCにアクセスできないため、テストされていません。しかしそれを見つけることができませんでした)
[/*else*/]sE[[/*then*/]sE]sIlalb=IlEx
vs [[/*then*/2Q]sIlalb=I/*else*/]x
-6バイトの違いになります。まだテストされていないtho:P
初心者にとっては頭痛の種ですが、dc
配列を提供します。次のように機能します。
value index :a # store `value' in array linked to top of stack `a', with index `index'
index ;a # push a[index] on (main) stack
通常、最初の要素のインデックスは0です。配列は、SUDSIシーケンスのように、特にカウンタと組み合わせてシーケンスを操作する場合に役立ちます。環境を破壊することなく特定の要素を選択したい場合、配列は必要な数のシャッフルの量(およびカウンターと比較の数)を減らすことができます。たとえば、多数の数値を配列に移動する場合は、z
(スタックの深さ)またはz 1-
インデックスとして使用し、要素を保存し、z == 0
終了するかどうかを確認する再帰関数を作成できます。
[z 1- :a z 0 !=F]dsFx # or I could just write such a function for you :)
次のことに注意してください。
dc
クラッシュします。dc
最近更新された可能性があり、クラッシュに関してアレイの動作がわずかに変更された可能性があります。現在どちらも確認できませんが、前回Linuxで使用したときは何かが違うと思います。
スタックから数字を破棄する必要がある場合があります。これを行う1つの方法は、単純に未使用の変数にポップすることst
です。ただし、状況によっては、他のいくつかの場所、たとえば数値入力がなくなった場合の入力ベースや、精度が異なる場合に実行する操作がない場合は精度指定子にポップできます。前者の場合、を使用しますi
。後者の場合、を使用しますk
。
o
使用することもできます。また、これらのいずれかが重要でない場合、ストレージとして使用することも、単に破棄することもできます- I
/ K
/ O
それぞれを呼び出し、sa
/ la
などでバイトを節約します。有効な値AFAIK:i
2-16; k
負でない整数。o
1より大きい整数
Z
、X
、およびz
Z
ToSをポップし、数字の場合は桁数(10進数)をプッシュし、文字列の場合は文字数をプッシュします。これは、結果の長さの検出(出力のバッファリング)または文字列の長さの計算に役立ちます。数値の場合、Z
整数部と小数部を組み合わせた長さをプッシュすることに注意してください。
X
ToSをポップし、数値の小数部の桁数をプッシュします。ToSが文字列だった場合、0
プッシュされます。
整数部の桁数を見つけるには、を使用しますdZrX-
。精度をdefaultから変更していない場合k==0
、using 1/Z
は短くなりますが、操作後に特定のゼロ以外の精度を維持する必要がある場合Kr0k1/Zrk
は、かなり目障りです。
z
スタック上のアイテムの数をプッシュします。私のお気に入りのコマンドの1つで、実際には値をポップしません!一連の数値を生成したり、カウンターをインクリメントしたりするために使用できます。zd
繰り返し使用すると(たとえば、マクロの開始時に)、各自然数または整数の計算を昇順でテストできます。
z
これまでにこれを使用したことがありますが、カウンターのハックとして使用することは私には一度もありませんでした…すばらしい…
数字はA
するF
ときに、異なる場所に(仮定入力ベースが10である)、それらは依然としてベース10の数字として効果的に治療されなければならないが15の数10の代わりに使用することができます。つまり、入力ベース10 FF
が255を表すのではなく、(15 * 10) + 15
165 を表すことになります。
実際には、これはすべての数字のために働く0
にF
任意の入力ベースに2
します16
。入力ベースが5であれば、それから26E
だろう(2 * 5^2) + (6 * 5) + 14
か、94。
この動作は、変更されていないGNUソースに対して有効です。ただし、@ SophiaLechnerが指摘しているように、RedHatベースのディストリビューションはbc-1.06-dc_ibase.patchを使用しているように見えるためibase - 1
、実際の値に関係なく、数字> = ibaseがとして扱われます。TIO dc
にはbc-1.06-dc_ibase.patchがないように見えます(Fedora 28¯_(ツ)_ /¯であっても)。
FF
表し99
、入力ベース5 26E
は、244
ベース10 と同じ74
です。
dc
バージョンを実行していますか?私はMacOSの上でUbuntuとGNU DC 1.3にGNU DC 1.4.1を使用しています
FFp
出力99
することです。あなたのMacOSバージョンでこれを確認できますか?
偶然これを発見しました。ゼロを生成するさらに別の方法:_
。
_
次の数字が負の数であることを示すdcへの信号です。例:
_3 # pushes -3
しかし、数字に従っていない場合はどうでしょうか?
_ # pushes 0...sometimes
これは、アンダースコアに続く次の非空白文字が数字ではない場合に機能します。改行の後でも数字が続く場合は、負符号として解釈されます。
c4 5_6 # -6,5,4
c4 5_ 6 # -6,5,4
c4 5_
6 # -6,5,4 # still a negative sign since the next thing it sees is a digit
c4 5_z # 3,0,5,4 # if it's followed by a non-digit, it's a 0
c4 5_p6 # 6,0,5,4
c4 _* # 0 # 4*0=0
dc
一度に1行ずつ入力を読み取ります。複数のアイテムを読み込む必要がある場合、1行に1つずつ?
読み込むには、すべての行を読み込むか、面倒なマクロループが必要です。代わりに、すべての入力項目をスペースで区切られた1行に配置できる場合、1つの入力項目がすべての入力項目?
を読み取り、各項目をスタックにプッシュします。
たとえば、ではseq 10 | dc -e'?f'
、seq
整数1〜10を1行に1つずつ出力します。?
ただ最初に読み込まれます1
ときに出力されるf
スタック全体をダンプします。ただしseq 10 | tr '\n' ' ' | dc -e'?f'
、tr
では、入力整数がすべてのスペースで区切られます。この場合、?
は行からすべての整数を一度に読み取り、すべてf
を出力します。
a
何度か便利になったのは、特定の演算子の使用を避けることです。演算子のASCII値をプッシュし、a
それを使用して文字列に変換し、s
後でマクロとして実行されるレジスタに保存します。オン。たとえば、私は除算を行う必要がありますが、キャラクターの使用を許可されないか、使用を避けようとしています/
。代わりにできます47asd
し、将来的に16を4で割る必要があるときにできます16 4 ldx
。
s
、何かで後置する必要があるようなコマンドでは機能しません。空白を回避することは、いくつかの課題で発生し、一般的には簡単ですdc
。文字列は別として、空白が必要になる非常に具体的な時間は、連続して複数の数字をプッシュするときです1 2 3
。これを避ける必要がある場合:
1[]x2[]x3[]x
。35asn
実行し1lnx2lnx3lnx
ます:。dc: ',' (054) unimplemented
警告に耐える場合は、コンマで区切った番号を使用することもできます。