RealBasic University

このコラムはStone Table Softwareのオーナーであり、またREALbasic Developerの編集者でもあるMarc Zeedar氏により書かれたものを、著者の許可を得て翻訳したものです。この翻訳はHREM Researchにより提供されています。この日本語版へのご意見はRBU-Jまでご連絡下さい。

URL: http://www.applelinks.com/rbu/060/
INDEXに戻る

Monotab:パート I

私がREALbasicで気に入っているところは、私の思考過程と合致していることです。どんな些細なことでも何か問題に当たったときには、私はまずREALbasicを頼りにします。それはまるで、REALbasicは私を助けてくれるためにいつもいてくれる、無二の親友のようなものです。

しかし、REALbasicに助けを請うためには、つねにその機会を注意深く探っていなければなりません。「この問題を簡単にできるプログラムは書けないだろうか?」と、私はいつでも自分自身に問いかけています。

時あるごとに突き当たるひとつの問題は、タブで区切られたフォーマットの表形式のデータがあり、それをEメールで送信するのに適したフォーマットに変換する必要があるときです(それはウェブページのテーブルからデータをコピーしたときにしばしば起こります)。たいていのEメールプログラムはテキスト形式なので、タブで区切られたテーブルは次のような具合になります(データはMajor League Soccerから転載)。

Team	GP	W	L	T	Pts	GF	GA
San Jose Earthquakes	17	10	5	2	32	27	16
Dallas Burn	16	7	3	6	27	24	19
Colorado Rapids	17	8	8	1	25	24	28
New York/New Jersey MetroStars	16	7	7	2	23	24	21
Los Angeles Galaxy	16	7	7	2	23	20	22
Kansas City Wizards	16	5	5	6	21	21	22
Chicago Fire	15	6	7	2	20	24	22
D.C. United	15	6	8	1	19	18	22
New England Revolution	16	6	9	1	19	27	31
Columbus Crew	16	5	8	3	18	21	27

うぇっ!これではひどくて読むのはほとんど不可能に近いですね(私のひいきしているEauthquakesがリーグトップを走っていることも見分けられないでしょう!;-)。しかしこのようなタブをスペースに変換して、テーブルを等幅のフォントで表示すれば、読みやすいテキスト形式のテーブルになります。

あいにく、それを手作業で行うにはあまりにもたいくつな作業で、ほとんどの人はわざわざそうしないでしょう。しかし幸運なことに、私はEメールのフォーマットにはこだわる人なので、それをREALbasicにやってもらうことにしましょう。

Monotabの設計

今回のプロジェクトでは、タブ区切りのファイルから、各々の要素が適当な数のスペースで区切られたテキストファイルへ変換するプログラムを作成することにします。最終的には、テキストの長さによってスペースの数は異なることから、簡単な処理が入り組んだものになります。

プログラムを開始する前に、少しだけMonotabがどのように働くのか考えて見ましょう。

まず始めに、プログラムにテキストを入力する方法が必要になります。それについて私は、面倒な"Open Document"ダイアログよりも、単純なドラッグ&ドロップのインターフェースにしたいと思います。

二番目に、実際にどのように変換するのかについて考えましょう。どんなアルゴリズム(algorithm)を使用しましょうか?

もちろん単純にタブ文字を置き換えるわけには行きません。テキストの長さによってスペースの数は変わってくるので、スペースの数をまず設定する必要があります。例えば、始めのほうで表示したサンプルのテキストは、メジャーリーグのサッカーチームと、そのリーグ順位のリストです。しかしチーム名はそれぞれ長さが違うので、次の列と同位置から始めようとするとチーム名の後に続くスペースの数は変化してきます。

ここで、タブをスペース三つ分に置き換えた場合にどうなるのか、その様子を示しましょう。

Team   GP   W   L   T   Pts   GF   GA
San Jose Earthquakes   17   10   5   2   32   27   16
Dallas Burn   16   7   3   6   27   24   19
Colorado Rapids   17   8   8   1   25   24   28
New York/New Jersey MetroStars   16   7   7   2   23   24   21
Los Angeles Galaxy   16   7   7   2   23   20   22
Kansas City Wizards   16   5   5   6   21   21   22
Chicago Fire   15   6   7   2   20   24   22
D.C. United   15   6   8   1   19   18   22
New England Revolution   16   6   9   1   19   27   31
Columbus Crew   16   5   8   3   18   21   27

うぇっ!テーブルを正しく表示するには、計算をして各々のフィールドの適当なスペースの数を割り出さなければなりません。

そのためにしなければならない計算が二つあります。一つ目は、どの列からスタートするか、その場所を把握します。この後すぐに分かりますが、それは思ったほど簡単ではありません。二つ目は、お互いのフィールドのそれぞれの行についてスペースの数を計算しなければなりません。これがどのように動作するか確認するために、はじめの数行を例として見てみましょう。

Team                 GP   W   L   T   Pts   GF   GA
San Jose Earthquakes   17   10   5   2   32   27   16
Dallas Burn   16   7   3   6   27   24   19
Colorado Rapids   17   8   8   1   25   24   28
New York/New Jersey MetroStars   16   7   7   2   23   24   21

"GP"を揃えるためには、"San Jose Earthquakes"よりもずっと右なので、"Team"の後に少なくとも17文字のスペースを入れる必要があります。しかしながら、"New York/New Jersey MetroStars"は"San Jose Earthquakes"よりもさらに長いので、17文字では足りません!

それは最低限のスペース数を計算するには、現在のフィールド内のいちばん広いデータをはじめに見つけ出す必要があります(この場合は、"New York/New Jersey MetroStars"がそのフレーズです)。

しかしながら仮にそうしたとしても、常にそれだけでは十分でないと分かることでしょう。もちろん、幅の広いほうに合わせて始めの2列が揃えられても、そこは窮屈になって十分なスペースがありません。

Team                           GP   W   L   T   Pts   GF   GA
San Jose Earthquakes           17   10   5   2   32   27   16
Dallas Burn                    16   7   3   6   27   24   19
Colorado Rapids                17   8   8   1   25   24   28
New York/New Jersey MetroStars 16   7   7   2   23   24   21

それぞれのフィールドの間隔に必要最小量(3スペース分ほど)の設定をするのはどうでしょうか。さらに使いやすくするためには、ユーザにこの幅を好きなように設定させるというのはどうでしょう?

そこで三番目の質問が必要になってきます。つまりMonotabにはどのようなインターフェースが必要でしょうか?

明らかに、これは個人的に用いられるプログラムです。売られたり、配布されたりされることは無いので、最低限必要なものがあればそれで十分です。さらにそれは、いかなるインターフェースも持たずに、コマンドラインのプログラムとして実行することも可能でしょう(要するに、Monotabのアイコンの上にファイルをドロップし、変換して終了します)!しかしながら、これはREALbasicということもあり、骨子のインターフェースでさえもシンプルですので、プログラムにインターフェースを持たせることにしましょう。

私がインターフェースに関してはじめに思ったことは、これはタブ・データを取り扱うプログラムなので、行と列のデータを割り当てる表を作成してリストボックス内でデータを整理するのが理にかなっているということです。その方法で、ユーザはそれを変換する前に、データが正しく配置されているか確認することができます。"最低限のスペース"を設定するためには、スライド・コントロールを用いましょう。

Monotabを作成する前に、プログラムが正しく動いているかどうか確認するためのテストファイルが必要です。まずは私が友人や家族に送った、テキスト形式のWorld CupサッカーのTVスケジュールを作成するためにMonotabを使ってみました。ここにMonotabをテストするために使用できるオリジナルのタブ区切りファイルがあります(ダウンロードするためにはリンク上でOption-clickをしてください。そうしないと、ウェブブラウザはファイルの中身を表示してしまいます)。

インターフェースを設定する

REALbasicの新しいブランク・プロジェクト・ファイルを作成してください(RBを立ち上げて、File Menuから"New"を選択します)。デフォルトで作成されたWindow1ウィンドウ上でダブルクリックし、次のようになるように試みてください。

最上部にあるものはlistboxです。その属性はプログラムの実行時に動的に変更させるのでそれほど重要ではありません。しかし、すべての"lock"属性(lockLeft, lockRightなど)を設定し、ユーザがウィンドウを拡大させるとlistboxのサイズも変更するようにするのが良いでしょう。

sliderコントロールはpadSliderと命名され、maximumは25、valueは3にそれぞれ設定しました。pushButtonexportButtonと呼ばれます。そのような属性以外にも、デフォルトは他のすべてに都合がよいように設定されています。

StaticText1はpadSliderの現在値のテキスト表示です。したがって、次のコードをOpenイベントとValueChangedイベントに入力する必要があります。

 staticText1.text = str(me.value) + " spaces" 

padSliderを動的(liveScrolltrue)に更新するように設定すれば、staticTextはユーザがコントロールをスライドさせる度に設定し直されるでしょう。

次に、ドロップされたファイルを受け付けるように設定する必要があります。いつものように、これには二段階の過程があります。一つめに、REALbasicに受け付けるファイルの種類を知らせる必要があります。この場合はテキストファイルになります。したがって、Editメニューにいき、"File Types"を選択してください。そこで新しいタイプ("Add..."ボタンをクリック)を加えて、次のような設定を与えます。

二つめに、このタイプのファイルを受け付けるようlistBox1に伝えなくてはいけません。listBox1Openイベント内に、次のコードを入力してください。

 me.acceptFileDrop("text") 

完璧です!これでlistBox1にドロップされたどんなテキストファイルも、DropObjectイベントに送られるようになりました。次週では、ファイルの解析処理をして、実際に変換を行うコードを書きましょう。

今週のチュートリアルの完全なREALbasicプロジェクト(リソースを含む)を入手したい場合は、ここからダウンロードしてください。

SimpleEtch

前回、私はSimplePaintプロジェクトのスペシャル・バージョンを約束したので、ここで簡単に紹介したいと思います。

そのアイデアはSimplePaintをお絵かきプログラムであるEtch-a-SketchのようなSimpleEtchに書き換えることです。子供のころEtch-a-Sketchを使ったことがあれば、いったん"ペンのようなチップ"を置いてしまうと、それを持ち上げることができませんし、何かを描かずにカーソルを動かすことができなかったことを思い出すでしょう。すべてのEtch-a-Sketchによって描かれた絵は、一本の連続的な線で描かれています。それは不便です(あるいはやりがいがあるともいえるでしょう)が、そのためEtch-a-Sketchはユニークで、面白いものになっています。

ここに私がSimpleEtchで作成した図があります。

SimplePaintSimpleEtchに変更することは、とりわけ難しいことではないので詳細はここでは説明しません。基本的な違いは次の通りです。

完成したSimpleEtchのREALbasicプロジェクトはここで利用可能です。それをダウンロードして、このスペシャルバージョンがどのように動くのかを見て、私の行った変更点を勉強してみてください。

次週

Monotabを仕上げます。

Letters

今週は、スペインからの質問があります!Manuelさんは次のような手紙を書いてくれました。

Marcさんへ

次のCodeWarriorのPascal命令で、REALBasicと同等のものは何でしょうか。

 getValue := ord(firstValue >= secondValue) 

ここでgetValue、firstValueとsecondValueは拡張Pascal型です。

敬具

Manuel Urrutia Avisrror
泌尿器科教授
サラマンカ大学
スペイン

興味ある質問です。ここであなたが何をしたいのかはっきりしないので、回答はこれでよいか分かりません。Pascalは以前私のお気に入りの言語(Cは勉強したことがありません)でしたが、もう使い始めてからはだいぶ経っています。もし私がなにか完全に見落としていないならば、上記の宣言文は変なものです。

ord()関数は渡された文字のASCII値を返します。例えば、"C"を渡せば、67を返します。しかしあなたのコードでは、論理型の値を渡しています。すなわち、"firstValue >= secondValue"の文はfirstValueの方が大きか、あるいはsecondValueと等しければtrueを、そうでなければfalseを返します。それは、getValueord(true)あるいはord(false)のどちらかの結果に割り当てられることを意味します。しかしPascalがそれをどの様に取り扱ったかを思い出すにはあまりにも昔のことがらです(truefalseはたいていは1あるいは0のように評価されるので、私はそのどちらかでないかと思います。しかし100%確実ではありません)。

いずれにしても、上記のREALbasic版も同じようなもので。書き直すと次のようになります。

   dim getValue, firstValue, secondValue as integer 
getValue = asc(firstValue >= secondValue)

しかしこれを試してみると、"Type Mismatch(タイプの不整合)"エラーを引き起こすでしょう。それはREALbasicのasc()関数は文字列の入力を前提としているのに、論理値を受け渡したからです。つまりasc(true)asc(false)は機能しません。

これがあなたの望むことであるなら、これを避ける方法は次のようにif-then命令文でコードを構成することでしょう。

   dim getValue, firstValue, secondValue as integer 

if (firstValue >= secondValue) then
getValue = 1
else
getValue = 0
end if

これは少し入り組んでいて複雑ですが、もちろん実行可能です。これがあなたがよく利用しそうな関数であるなら、私はメソッドにすることをお勧めします。それをascBoolと呼ぶことにして、次のように設定してください。

 function ascBool(bool as boolean) as integer 
if bool then
return 1
else
return 0
end if
end function

上のメソッドを作成すれば、次のようにしてコードを活用できます。

 getValue = ascBool(firstValue >= secondValue) 


RBU-Jの通知サービス!コラムが発表されるたびに日本語版REALbasic Universityのお知らせの emailがあなたに届きます。登録・削除は ここ から。

INDEXに戻る