時間を計算するために作ったプログラムです。 個人的にはカセットテープにCDからダビングする際に、出来るだけ空き時間を少なくするようにA/B面の曲配分を行うために作りました。 時間計算だけでなく、曲名も一緒にファイルできるから、結構重宝していたのですが...
この電卓は2つの起動方法があります。
対話方式起動
tcalcとコマンド名のみ入力する方法です。 直接データを入力するのに適しています。 終了時は^z(コントロールキーを押しながら"z"のキーを押す)で終了します。
入力リダイレクト起動
入力をリダイレクトし、データの入力はファイルから行う方式です(起動例:Stcalc < calcfile.txt)。 テキストファイルの1行は半角255文字まで受け付けますが、100文字程度に押さえておく方が良いと思います。 必ずセパレータの始まりと終わりを同じ行に入れてください。 2行にわたる計算式またはコマンドは受け付けません。
tcalc [sep] <infile >outfile
sepはセパレータ指定で、半角2文字(最初がセパレータ開始文字、次がセパレータ終了文字の指定。指定例:[])で指定します。 省略した場合は{}が設定されます。
式とコマンドは後で説明しますが、とりあえず使ってみましょう。
入力リダイレクト方式でよく使われると思われる方法です。カセットテープの時間計算を行うときの私が使ったサンプルテキストファイルを紹介します。
1. xxxxxxxxxxxxx {5m28s}
2. xxxxxxxxxxxxx {2m59s}
3. xxxxxxxxxxxxx {5m46s}
4. xxxxxxxxxxxxx {8m30s}
5. xxxxxxxxxxxxx {4m24s}
{writeln(acc)}
これをsamp.txtというファイル名で作成します。 これがカセットの片面にはいるかを計算するため、tcalcを起動します。
tcalc < samp.txt
そうすると0d0h27m7s0pと表示され全部で27分7秒であることが分かります。 これで60分テープの片面に入れることが可能だと分かります。
その他の例としてメールの到着が遅れたとき、どれくらい遅れたかを計算するときなどでも使用できます(この場合は対話方式起動が良いでしょう)。
tcalcと入力してプログラムを起動します。 そして到着した時間から発送した時間を引くように入力します。
{27d02h21m35s minus(26d11h10m20s) writeln(acc)}
このように入力すると0d15h11m15s0pと表示され、15時間11分15秒かかってメールが到着したことが分かります(実話)。
そして^zを入力してプログラムを終了させます。
この電卓はaccumulator(アキュムレータ:累算器)を使って計算を行う方式です。 そのため、計算結果は常にアキュムレータに残されます。 また、このデータは積極的に表示しようとしない限り表示されませんので、計算結果が必要な場合は積極的に表示する必要があります(そうでないと「計算をしたけれども結果が表示されずにプログラムが終了する」ことになります)。
そして日時データだけの入力では常に加算を行うようにプログラムされています。 そのため日時データを並べるだけで加算を行いますが、アキュムレータの内容をクリアしたり違う値にセットし直す場合は、積極的に指示する必要があります。
メモリは50個ありますが、スタックと共用しているため、場所を注意して使用しなければなりません。 スタックは50番からだんだん低い方に向かって使っていきますので、メモリを使用する場合は一番低い方から使用すればいいでしょう。 もちろんスタックだけを使用するか、メモリだけを使用する場合は50個のすべてを使用することが可能です。
プログラムを起動した段階で、メモリとアキュムレータは0に初期化されます。 そのため、クリアしなくてもそのまま入力していくことが出来ます。
セパレータ内部にはコマンドをいくつ書いても問題ありませんが、コマンドとコマンドの間には半角スペース1つを空けてください。
11d22h33m44s55p
日付データをあらわし、アキュムレータに加えます(内容の一部が未記述でも可。例えば11h44sとか1d5sなど)。
set(11d..55p)
現在のアキュムレータの内容を破棄し、新しく値をセットします。
pop
現在の最上部のスタックの内容をアキュムレータに読み出し、最上部の一をひつ戻します。 それまであったアキュムレータの内容は破棄されます。
push
アキュムレータの内容をスタックの上に積み、その位置をスタックトップとします。 アキュムレータの内容はそのままです。
pop(%**)
**番のメモリ内容をアキュムレータに読み出します。 それまであったアキュムレータの内容は破棄されます。
push(%**)
アキュムレータの内容を**番のメモリに保存します。 アキュムレータの内容はそのままです。
clear
アキュムレータの内容をクリアします。
topreset(**)
スタックトップ位置を**に変更します。 このコマンドは通常は不要です。 スタックトップが変わってしまうので使わない方が良いでしょう。
multi(++)
アキュムレータの内容を++倍します。 1 <= ++ <= 255が指定可能です。
div(++)
アキュムレータの内容を++で割ります。 1 <= ++ <= 255が指定可能です。
minus(%**)
アキュムレータから**番のメモリ内容を引きます。
minus(11d..55p)
アキュムレータから指定された日時のデータを引きます。
add(%**)
アキュムレータと**番のメモリの内容を加えます。
swap(%**)
アキュムレータと**番のメモリ内容を入れ替えます。
write(acc)
アキュムレータの内容を表示します。
write('文字列')
シングルクォートで囲まれた文字列自体を表示します。 この例では文字列と表示します。 シングルクォート自体は表示しません。
write(%**)
**番のメモリの内容を表示します。
write(%all)
スタックに積まれている内容を全て表示します。 各データはカンマとスペースで区切られます。
write(¥.)
コントロール文字の表示をします (¥n : 改行/ ¥t : タブ/ ¥s : シングルクォート文字)。 コントロール文字は単独で指定します。 文字列に含めることは出来ません。
writeln(..)
表示を行ってから改行します。 表示を行える内容はwriteと同じです。
writ
改行のみを行います。
このwriteとwritelnはカンマで区切って複数指定が可能です。 例えばwrite('acc = ',acc,¥t,'1st mem = ',%1,¥t,'2nd mem = ',%2,¥n)などが可能です。