【第15章】ファイルと補助記憶装置

 このカテゴリーもいよいよ終点に近づいてきました。この章以後ではファイルを使うプログラムについて学びます。ファイルについて勉強するには、ファイル名、拡張子、補助記憶装置(媒体)などについても知る必要があります。本カテゴリーの目的は「プログラミング体験」と「プログラミング的思考を身につける」ですから、Windowsパソコン初心者の方でもわかるよう、この辺は必要最小限の範囲にとどめ、なるべく平易に説明します。またWord、Excelなどをすでに使っていて、ファイルについての基本知識がある方はこの章は読み飛ばしていただいてかまいません。
 またTiny Basic for Windowsではファイルを取り扱う方法は
    ①旧来の方法
    ②.NET Frameworkに対応した方法(新しい方法)
の2つがありますが、本カテゴリーではファイルとはどういうものかを知るために①の方法に基づいて説明します。

【ファイルとは】
 
図15-1は一般的にファイルとよばれているもので、○月分売上伝票とか○年○組生徒指導要録など、同じ種類(目的)の書類をまとめておくのに使われます。
 コンピュータのファイルも基本的にはこれと同じで
   ①同じ種類(目的)のデータをまとめておくもの
です。ただコンピュータのファイルには
   ②ある目的のための材料箱というもの
もあります。本カテゴリーでは①の意味でのファイルについて中心にお話します。



図15-1.事務用品のファイル

【ファイル・レコード、アイテム】

 ファイルとは同じ種類(目的)のデータをまとめておくものでした。たとえば担任クラスの生徒の名簿を考えてみます(図15-2)。



図15-2.名簿の例

 これがファイルです。ファイルの中の1件1件のデータ(この例なら1行)をレコードといい、1件のレコードを構成する各項目(この例なら出席番号、氏名、ヨミガナ)をアイテムといいます。
 プログラムを作るとき、最初に処理の手順(アルゴリズム)を考えたように、ファイルを使うには先にファイル設計をしておく必要があります。もし名簿が図15-3のようだったら、こんな名簿使いにくいことこの上ないですね。


図15-3.使いにくい名簿

 このように1レコード中のアイテムの並びをどうするのか先に決めておくことが大切です。ここでは図15-2のように出席番号、氏名、ヨミガナの順としておきます。

【主記憶装置と補助記憶装置】


図15-4.コンピュータを構成する各装置

 第4章で出てきたこの図をもう一度復習しましょう。今のノートパソコンでは一見してもわかりませんが、コンピュータの中身は図15-4のようになっています。今までやってきたプログラム、たとえば次のプログラムは、図15-4の主記憶装置より上の部分(中央処理装置=Central Processing Unit=CPU、入力装置、出力装置、主記憶装置)だけを使っています


INPUT "A=",A  
INPUT "B=",B  
C=A+B     
PRINT "A+B=";C 
END        

 ファイルを使うプログラムでは補助記憶装置(固定ディスク装置、CD/DVDドライブ、USBメモリ、SDカードなど)も使います。まず主記憶装置と補助記憶装置はどう違うのかを知っておきましょう。
 上のプログラムの場合、キーボードから入力された2つの数を、それぞれ変数A、Bに記憶します。このとき2つの変数は主記憶装置内に自動的に格納されます。これは主記憶装置はCPUが直接管理しているからです。これに対してデータを主記憶装置ではなく、補助記憶装置に記憶する場合、①使用するファイルを開く②データをファイルに書き込む③ファイルを閉じるというステップを踏まなくてはなりません。これは補助記憶装置はCPUが直接管理していないため、使うための準備から後始末まで、すべてプログラムでやらなくてはならないからです。

【補助記憶装置と補助記憶媒体】

 ここで、何の説明もなく補助記憶装置という言葉を使いましたが、具体的な例でみてみましょう。目で見て最もわかりやすいCD/DVDドライブを例にとります。


図15-5.補助記憶装置(CD/DVDドライブ)

 これはパソコン内蔵のCD/DVDドライブです。ここに音楽CDをセットすればパソコンをCDプレイヤーとして、映画やドラマなどのDVDをセットすればDVDプレイヤーとして使用することができます。そしてここに書き込み可能なCD-R、CD-RW、DVD-R、DVD-RW(以下、ディスクといいます)などをセットすれば、このCD/DVDドライブは補助記憶装置となります。上の写真をよく見ると、中心にセットしたCD、DVDを回転させる軸とディスクの内容を読み取ったり、ディスクにデータを書き込む光ヘッドがあるのが見えます。このような駆動装置、アクセス装置を総称して補助記憶装置といいます。


図15-6.補助記憶媒体(DVD-R)

 この装置にセットするディスクのひとつが図15-6のDVD-Rです。補助記憶装置にセットして使用するディスク、USBメモリなどを補助記憶媒体(最近ではメディア、ストレージというようです)といいます。ファイルはこの補助記憶媒体に書き込まれます(記録されます)。


図15-7.補助記憶媒体を補助記憶装置にセットしたところ

 このとおり補助記憶装置とは補助記憶媒体の内容を読み書きする装置のことなのですが、本カテゴリーでは煩雑さを避けるため補助記憶媒体をセットした状態(図15-7)を補助記憶装置と呼ぶことにします

[主記憶装置と補助記憶装置の特性と欠点]

①記憶容量

 一般的に主記憶装置と補助記憶装置では補助記憶装置の方が記憶容量が大きいです。筆者のパソコンの場合、主記憶装置の記憶容量は8GB(ギガバイト)ですが、使用している補助記憶装置はいちばん容量が小さいもので500GBほどです。今日ではコンビニで売ってるUSBメモリやSDカードでも32GB、64GBくらいが普通になっています。なので全校生徒(児童)の指導要録などの大量の(容量の大きい)データはファイルとして補助記憶装置に、計算結果や処理中のデータは保存の必要がない限り主記憶装置内だけで扱うようにします。

②速度

 主記憶装置と補助記憶装置では主記憶装置の方が記憶・記憶内容の読み出しの速度が速いです。今日のパソコン用補助記憶装置で一般的な事務処理プログラム程度ではあまり意識する必要はありませんが、画像・音声・動画を大量に扱う場合、補助記憶媒体への書き込み速度はシステム全体の運用効率にかなり影響が出ます。

③保存性

 最後にこの章で最も大事なことを知っておきましょう。それは補助記憶装置の記憶は媒体が物理的に破損するか記録内容を消去するプログラムを実行しない限り永久に残るということです。これに対して主記憶装置の記憶内容はパソコンの電源を切るかパソコンを再起動かけたところですべて消えます。なので永久に保存しておきたいデータは補助記憶装置に記憶させるようにします。

[ドライブとフォルダ(ディレクトリ)]



図15-8.補助記憶装置のいろいろ


 前節では補助記憶装置の説明としてCD/DVDドライブをとり上げましたが、補助記憶装置には図15-8のようにいろいろなものがあります。それぞれの装置の詳しい構造を知ることは本カテゴリーの目的から外れますのでここでは説明しませんが、外見からはわからなくともどの装置も駆動部、アクセス部(コントローラ)と記録媒体(不揮発性メモリ)で成り立っていることは共通しています。これらの補助記憶装置をすべてパソコンに接続した上で、WindowsシステムツールのPCを開くと図15-9のように表示されます。


図15-9.複数の補助記憶装置が接続された状態

 図15-9の下半分のデバイスとドライブの部分を見ると現在接続されている補助記憶装置がわかります。ここで各装置のところに表示されているTIH0422000AやHD-PCGU3-Aなどをボリュームラベル(ボリューム名)といい、各補助記憶装置に付けられている名前とお考えください。ボリュームラベルはご自分の好きな名前に付け替えることができます。ボリュームラベルの後ろの(C:)や(F:)をドライブ名といいます(ドライブ名はお使いのパソコンにより異なります)。ボリュームラベルは長くて煩雑なので、プログラム中で補助記憶装置を扱うときはドライブ名を用います。
 では、これらの補助記憶装置にデータがどのように記録されているのかを見てみましょう。ここではTiny Basic for WindowsをUSBメモリにインストール(【第0章】実習の準備参照)したものとして考えます。デバイスとドライブのTBasic.exeが入っているドライブをダブルクリックしてください(この例ではUSBメモリ)。すると図15-10のように表示されます。

図15-10.USBメモリをダブルクリックしたところ

 黄色いノートみたいなアイコンが並んでいますが、これをフォルダディレクトリ)といいます。1個のUSBメモリを複数の目的に使う場合、ファイルをそのままでどんどん書き込んでいくと、後で見た時に「この作業に必要なファイルはどれだっけ」と探すのが大変になります。そこで目的別にファイルを分類しておくために、フォルダを作って、その中にファイルを書き込むようにします。この例ではTBasicというフォルダにTiny Basic for Windowsが入っています。ではTBasicというフォルダをダブルクリックしてみましょう。今度は図15-11のように表示されます。

図15-11.TBasicフォルダを開いたところ

 Tiny Basic for Windows本体のTBasic.exeとTiny Basicが使用するいろいろなファイルが同じフォルダ内にあるのが確認できます。他にもいろいろなフォルダやファイルがありますが、これらはTiny Basic for Windowsをインストールしたときに自動的にコピーされたドキュメントやサンプルプログラムです。

[ファイルパス]

 ここでいうパスとはpass(通行証/合格)ではなくpath(経路/道)です。対象のファイルまで辿り着く経路ということですが、Tiny Basic for Windowsの本体(TBasic.exe)が入っている場所を例にすると

 Dドライブ(の媒体)の中のTBasicというフォルダの中のTBasic.exeというファイル

ということになります。これをTiny Basicでは

 "D:¥TBasic¥TBasic.exe"(¥はお使いのOS/ブラウザによっては\と表示されているかもしれません)

と書きます。ファイルパスの書き方は

 ドライブ名:¥フォルダ名¥フォルダ名・・・・¥ファイル名

です。ファイルバスのうちドライブ名からフォルダ名は省略可能ですが、省略した場合(デフオルトのファイルパス)は、Tiny Basicの場合、TBasic.exeが入っている場所と同じ場所を指定したものとみなされます。

【カレントディレクトリと絶対パスと相対パス】

 今、ファイル操作(処理)の対象になっているフォルダ(ディレクトリ)のことをカレントディレクトリ(カレントフォルダ)といいます。そしてドライブ名からフォルダ名~・・・~ドライブ名~ファイル名で表すファイルパスを絶対パス、カレントディレクトリから見て目的のディレクトリの場所を示す表し方を相対パスといいます。下の図で説明します。


図15-12.絶対パスと相対パス


 ここにA駅からB駅を通ってC駅・D駅を結ぶ鉄道があります。B駅でC駅方面とD駅方面は分岐します。今、A駅発C駅行きの電車が走っています。この電車がB駅に停まっているとき、B駅で降りる乗客を降ろしたりB駅から乗る乗客を乗せることはできますがC駅までの乗客を降ろすことは(事故・故障などがない限り)ありません。この場合、電車が停まっている駅がカレントディレクトリだと思ってください。そしてこの電車が走る経路(駅順)、A→B→Cが絶対パスです。
 終点のC駅に着いた後、この電車はD駅行きになるとします。この場合、この電車はA駅まで戻る必要はなく、B駅まで戻って進行方向が変わりD駅に向かいます。この経路はC→1駅戻る→Dということになります。この表し方が相対パスです。筆者の趣味丸出しなたとえでごめんなさい💦💦

【この章のまとめ】

ファイルとは、同じ種類(目的)のデータをまとめておくもの、ある目的のための材料箱のことである。

補助記憶装置は主記憶装置と比べて大容量のデータを永久的に保存することが可能である。ただしアクセス速度は主記憶装置に比べて遅い。

ファイルを構成する1件1件のデータをレコード、レコードを構成する各データをアイテムという。

1つの補助記憶装置を複数の目的で使用する場合、目的別にファイルをまとめておくものをフォルダ(ディレクトリ)という。

ファイル操作の対象となっているフォルダをカレントディレクトリ(カレントフォルダ)という。

絶対パスとは目的のファイルまでの経路をドライブ名、フォルダ名~・・・ファイル名で表し方である。

目的のファイルまでをカレントディレクトリからの経路での表し方を相対パスという。

【第14章】関数とサブルーチン

【関数】

 今まで何回かこの言葉を使ってきましたが、命令との違いについて説明してきませんでした。ここまでのレベルのプログラムではこの違いがわからなくてもとくに支障はありませんでしたが、コンピュータのコンピュータらしいプログラムを作るには、知っておいた方がいいことなのでここで勉強しましょう。


図14_1.数学の関数
図14-1.数学の関数

 図14-1.は中学校でも習う一次関数のグラフです。数学でいう関数とは伴って変わる数という意味です。プログラミング言語における関数はこの意味もありますがどちらかというと「マジシャンの箱」のようなものと考えてください。

図14_2.プログラミング言語の関数
図14-2.プログラミング言語の関数

 マジシャンの箱はステッキで触れると中から鳩や万国旗が出てきますが(ネタ古っ)もちろんタネも仕掛けもあるわけです。プログラミング言語の関数とは、何か材料を入れると加工されて完成品が出てくる箱だと思ってください。この箱に入れる材料のことを引数(ひきすう)、箱から出てくる完成品を戻り値(もどりち)といいます。筆者の亡父が高校(旧制中学)の時使っていた数学の教科書では関数は「函数」と書かれていましたが、プログラミング言語の関数は函数と書く方が適切なような気がします。
 Tiny Basic for Windowsの関数では引数が不要なものもあります。今まで出てきたサンプルプログラム中にもすでに登場している関数もあります。

[Tiny Basic for Windowsの便利な関数](一部)

SQR(正の数)      平方根を求める
INT(数)       数の小数点以下を切り捨てて整数化する
ROUND(数)      数の小数点以下を四捨五入して整数化する
RND        0以上1未満の乱数を得る(*1)
PI                       円周率 3.14159265358979324 を得る(*2)
SIN(数)       正弦を得る(*3)
COS(数)       余弦を得る(*3)
TAN(数)       正接を得る(*3)
MAX(数1,数2)    数1と数2の大きい方を得る
MIN(数1,数2)     数1と数2の小さい方を得る

図13_5.弧度法(ラジアン)
図14-3弧度法(ラジアン)span>

(*1)正式な書き方はRND(数)。普通に乱数を発生させる場合、数は正の数。省略した場合は正の数が指定されたものとみなす。
(*2)関数というよりプログラミング言語が提供する定数(予約変数)。
(*3)数は弧度法(ラジアン、図14-3)で与える。

                 A=5
                 B=SQR(A)
                 C=INT(B)
                 PRINT B,C
                 R=10
                 S=PI*R^2
                 PRINT S
                 END

                 2.2360679774997897 2
                 314.159265358979324

                   図14-4.数値関数のサンプルプログラムと実行結果

 これらは戻り値が数値の関数なので数値関数とか数学関数とよばれます。プログラミング言語の関数には戻り値がストリングのストリング関数もあります。
DATE$                                       現在の日付を yyyy/mm/dd形式で得る
TIME$                                       現在時刻を hh:mm:ss形式で得る
LEFT$(ストリング,自然数)              ストリングの左から(自然数)分文字の文字を得る
RIGHT$(ストリング,自然数)           ストリングの右から(自然数)分文字の文字を得る
LEN(ストリング)                           ストリングの文字数を得る(戻り値は数値)
MID$(ストリング,自然数1,自然数2) ストリングの左から(自然数1)文字目から(自然数2)文字分の文字を得る

                 NOW$=DATE$+" "+ TIME$
                 L=LEN(NOW$)
                 Y$=LEFT$(DATE$,4)
                 M$=MID$(DATE$,6,2)
                 D$=RIGHT$(DATE$,2)
                 PRINT NOW$,L
                 PRINT "今年は";Y$;"年です"
                 PRINT "今日は";M$;"月";D$;"日です"
                 END

                 2023/04/26 11:37:30 19
                 今年は2023年です
                 今日は04月26日です

                    図14-5.ストリング関数のサンプルプログラムと実行結果

 これらの関数はプログラミング言語が提供しているものなので組込関数とよばれることもあります。

【ストリングの長さ】

 ※この節は昔のBASICをやったことのない方には???かもしれません。今のTiny Basicのプログラミングだけ覚えたい、という方は今は読み飛ばしていただいてかまいません。

            1:STRG1$="ABCDE"
            2:STRG2$="東京大阪福岡"
            3:PRINT STRG1$,STRG2$
            4:PRINT
            5:L1=LEN(STRG1$)
            6:L2=LEN(STRG2$)
            7:PRINT L1,L2
            8:PRINT
            9:C1$=MID$(STRG1$,3,2)
          10:C2$=MID$(STRG2$,3,2)
          11:PRINT C1$,C2$
          12:END

                          図14-6.Tiny Basicのストリング長を調べるプログラム

図14-7.ストリング長を調べる
図14-7.ストリング長を調べる


 図14-6のプログラムの実行結果は図14-7のようになります。Tiny Basicでは日本語(全角文字)も含めて「見える1文字」は1文字と数えます。同じプログラムを昔のBASICで実行すると図14-8のようになります。

図14-8.昔のBASICでのストリング長
図14-8.昔のBASICでのストリング長


 昔のBASICでは半角英数字・記号・カタカナは1文字1バイト、日本語(全角文字)は1文字で2文字と数えます。昔のBASICから今のTiny Basicに乗り換える場合、注意が必要なところです。

【サブルーチン】

 コンピュータの得意技のひとつがデータの保存と再利用でした。同じように処理の再利用もできます。図14-8のプログラムの10~13行目はサブルーチンとよばれ、プログラムの他の箇所から呼び出されて使われます。13行目のRETURN呼び出し元に戻る命令です。サブルーチンは何度でも呼び出して使えます。サブルーチンを呼び出して使う側(図14-6のプログラムなら1~9行目)をサブルーチンに対しメインルーチンと呼びます。制御文ブロックが構成できるTiny Basicでこの程度のプログラムではこのような単純なサブルーチンを使う意味はほとんどありませんが、ある制御文ブロック中の処理を別のブロックで使いたい時には使います。Tiny Basicでサブルーチンをサブルーチンらしく使う場面は、関数を自作する場合です(当カテゴリーでは扱いません)。

         1:RESTORE *EKIMEI
         2:EKI$=""
         3:WHILE EKI$<>"//"
         4:    READ EKI$,SHA$,SEN$
         5:    IF EKI$<>"//" THEN
         6:       GOSUB *DISP
         7:    END IF
         8:WEND
         9:END
       10:*DISP
       11:TXT$=EKI$+"駅は"+SHA$+SEN$+"の駅です"
       12:PRINT TXT$
       13:RETURN
       14:*EKIMEI
       15:DATA "厚岸","JR北海道","根室本線"
       16:DATA "谷田川","JR東日本","水郡線"
       17:DATA "合格","大井川鉄道","大井川本線"
       18:DATA "教会前","JR四国","鳴門線"
       19:DATA "東新庄","富山地方鉄道","宇奈月本線"
       20:DATA "//","",""

       厚岸駅はJR北海道根室本線の駅です
       谷田川駅はJR東日本水郡線の駅です
       合格駅は大井川鉄道大井川本線の駅です
       教会前駅はJR四国鳴門線の駅です
       東新庄駅は富山地方鉄道宇奈月本線の駅です

                 図14-8.サブルーチンを用いたプログラム例と実行結果

【サブルーチンのネスティングと変数の値引継ぎ】

           1:A=0
           2:PRINT "メインルーチンスタート"
           3:GOSUB *SUB_1
           4:GOSUB *SUB_2
           5:PRINT "A=";A,"B=";B
           6:PRINT "プログラム終了"
           7:END
           8:
           9:*SUB_1
          10:A=A+1
          11:PRINT "サブルーチン1を実行しました";I
          12:RETURN
          13:
          14:*SUB_2
          15:A=A+10
          16:B=5
          17:GOSUB *SUB_1
          18:PRINT "サブルーチン2を実行しました";I
          19:RETURN

                       図14-9.サブルーチン間で変数を引継ぐプログラム

 図14-9のプログラムでは、メインルーチンの3行目まできたところでサブルーチンへ飛びます(この例では*SUB_1以後)。サブルーチン内の12行目まできたところでRETURNなのでメインルーチンに戻ります。戻り先はこのサブルーチンを呼び出した次の行です(ここでは4行目)。4行目はまたサブルーチンへのジャンブ(今度は*sub_2以後)です。サブルーチンの17行目までくると、またサブルーチン(*sub_1以後)へジャンプします。12行目のRETURNですが、今度は戻り先が18行目になります。サブルーチンもFOR制御文、WHILE制御文のようにネスティングができます。実行結果は図14-10のようになります。

図14-10.サブルーチン間で変数を引継ぐプログラム
図14-10.サブルーチン間での変数引継ぎ


 ところで、実行結果を見ていただければおわかりと思いますが、変数Aの値はメインルーチンからサブルーチン、また別のサブルーチンへ引き継がれていることがわかります。また変数Bは2つ目のサブルーチン内で初めて出てきたものですが、その値はメインルーチンに戻っても引き継がれます。普通のサブルーチンの使い方では変数の値はメインルーチンとすべてのサブルーチン間で引き継がれます。このようにプログラム中のすべての場所で値が引き継がれる変数をグローバル変数といいます。引き継がれるということは、たとえばサブルーチン内でメインルーチン内で使用している変数を誤って使ってしまうと、変数の値を壊してしまうことになります。これに対し特定の範囲でのみ有効な変数をローカル変数といいます。Tiny Basicや昔のBASICでは、自作の関数内で使用する変数以外はすべてグローバル変数になります。

【昔はよかったなぁ】

 今のTiny Basicではあまり出番のないサブルーチンですが、(IFブロックがなかった)昔のBASICではなくてはならないものでした。図14-9のプログラムは第12章の図12-7のプログラムをサブルーチンを使うよう書き換えたものです。IFブロックが使えない昔のBASICでは、条件が成立したとき(またはしなかったとき)の処理が数十行に及んだり、その中にまた別の制御文が入ったりするときは、サブルーチンを使わなければ事実上プログラミングは不可能でした(プログラムの1行が255文字以内という制限があったため)。

図14_9.サブルーチンを使ったプログラム例
図14_9サブルーチンを使ったプログラム例span>

 この最初の行(行番号10)のGOTO 1000を見て「懐かしい」と思われた方、昭和プログラマ同窓会やりましょう🍺🍶🍣。
 冗談はさておき、このプログラムは行番号1000~1200がメインルーチン、100~320行目がサブルーチン群です。最初の行のGOTO 1000がないと、プログラムは行番号100からメインルーチンとして開始されます。そして行番号190にきたところで「RETURN?ってどこへ帰ればいいんだ?」となり、コンピュータは止まってしまいます。これを避けるために、プログラム開始直後にサブルーチン群を飛ばしてメインルーチンの頭から実行するように、先頭にGOTO命令が置かれます。昔はなんでこんな面倒なプログラムの書き方をしたのかというと、昔のBASICではこのようにサブルーチンを最初に、メインルーチンを後ろに置いた方がメモリ節約になったからです。メモリが32Kのパソコンでまともなプログラムを書くには必須テクニックでした。GOTO命令はたしかにあまり使いたくない命令なのですが、サブルーチンが多いプログラムではなくてはならない命令だったのです。

【この章のまとめ】

材料(引数)を渡して完成品(戻り値)が出てくる箱を関数という。

プログラム中で何回も出てくる処理はサブルーチンにして呼び出して使うことができる。

サブルーチンはネスティングできる。

プログラム中のどこでも値が引き継がれる変数をグローバル変数、特定の範囲でのみ有効な変数をローカル変数という。

【第13章】ゲームを作ろう(乱数の魔術)

 今まで堅苦しいプログラムばかり作ってきましたが、ちょっと楽しいプログラムを作ってみましょう。そう、ゲームのプログラムです。コンピュータゲームというと「ゲームばかりやってないで勉強しなさい」とお父さんお母さんに叱られたとかオンラインゲームで課金し過ぎてお金がなくなったとかあまりいい話を聞きませんがそれはゲームで遊ぶ側の話です。そのゲームのプログラムを作るということになると話は違ってきます。ゲームのプログラム1つ作る過程でプログラミングの高度なテクニックや様々なアルゴリズムを学ぶことができます。筆者はゲームを作りながらプログラミングの勉強をすることは否定しません。ということでこのカテゴリーでも実際にゲームのプログラムを作ってみたいと思います。とはいっても 残念ながらTiny BASIC for Windowsでテキスト画面のみでは、画面いっぱいに敵戦闘機が飛び回るとか、クエストクリアしたら美少女が微笑むようなゲームは無理ですが、ストリングと計算式のみでも知育ゲームやアドベンチャーゲームのようなものはできます(なんか美少女のたとえが多くね?・・・汗)。

[乱数]


  ゲームで必須なものは乱数です。乱数とは、規則性のない数の並びのことです。たとえば2、3、4、6なら12の約数を小さい順に並べたものとわかりますが、4、7、2、9だとまったく規則性がありません。ゲームでは敵がどこから襲ってくるかわからない、どこに何が隠れているかわからないなど、ランダムに何かが出てくるという場があります。これを実現かるのが乱数であり、Tiny BASICにはこの乱数を発生させる機能があります。それが次のRND(*)です。次のプログラムを実行してみてください。


  FOR I=0 TO 10
   R=RND
   PRINT R
  NEXT I


 実行結果は図13-1のようになります。


図13_1.乱数を発生する
図13_1.乱数を発生する


 RNDは0以上1未満の乱数を発生する関数(後述)です。ただしひとつ注意することがあります。上のプログラムを何回か実行してみてください。おわかりと思いますが乱数とはいってもコンピュータで発生させる場合ある計算式にしたがって発生させるので、同じプログラムを繰り返し実行すると、発生する数の順番はいつも同じになってしまいます。これではたとえばシューティングゲームに使うにしても、敵が出てくる場所と順番がいつも同じになってしまい、面白みが半減ですね。これを回避するには、次のようにRANDOMIZE(*)という一文をRNDの前に入れます。これはコンピュータの内部時計を用いて、乱数発生の計算式の初期化を行なうものです。

  RANDOMIZE
  FOR I=0 TO 10
   R=RND
   PRINT R
  NEXT I

 これで数回実行してみましょう。今度は発生する数の順番はバラバラになったはずです。では、これで1から10までの整数をランダムに発生させる方法を考えてみましょう。RNDで発生する数は0以上1未満ですから

  RANDOMIZE
  R=RND*10+1

で 1 から 10 までの数がランダムで得られます。さらに

  RANDOMIZE
  R=INT(RND*10)+1

とすると、発生した数の小数点以下が切り捨てられ1から10までの整数がランダムで得られます。INTはInteger(整数の意味)の省略形でINT(数値)で( )内の数値の小数点以下を切り捨てて整数化する関数です。次のプログラムで試してみてください。結果は図13_2のようになります。

  RANDOMIZE
  FOR I=1 TO 10
   R=INT(RND*10+1)
   PRINT R
  NEXT I
  END


図13_2.1から10の整数をランダムに発生させる
図13_2.1から10の整数をランダムに発生させる

(*)RANDOMIZEとRNDの正式な書き方は

          RANDOMIZE 整数(-32768~32767の範囲)
          RND(整数)

ですが、Tiny Basicでは、どちらも整数は省略可です。省略しても不規則な数を発生します(図13-3)。普通のゲームプログラムならこれで問題ないと思います。

図13_3.1から100の整数をランダムに発生させる
図13_3.1から100の整数をランダムに発生させる


[数当てゲームのプログラム] 

 それでは、ここまでの知識を使って簡単なゲームを作ってみましょう。コンピュータが隠した 1 から 100 までの整数を当てるゲームです。図13-4のプログラムを見てください。

     1:CLS ' 画面をクリア
     2:RANDOMIZE    ' 乱数系列の初期化
     3:PRINT "***** 数当てゲーム *****"
     4:PRINT "今からコンピュータが隠した数を当ててください"
     5:PRINT "数は 1 から 100 の整数のみです"
     6:' 乱数を発生させる
     7:R=INT(RND*100)+1
     8:' 数を当てる
     9:' 正解が出るまで以下の処理を繰り返す
   10:DATAOK=0
   11:WHILE DATAOK=0
   12:   PRINT
   13:' 1~100の整数が入力されるまで繰り返す
   14:   NUMOK=0
   15:   WHILE NUMOK=0
   16:      INPUT " 1~100で数を当ててください",NUM
   17:      PRINT
   18:      IF NUM=>1 AND NUM<=100 THEN
   19:         NUMOK=1
   20:      END IF
   21:   WEND ' 1~100の整数が入力されるまで繰り返しここまで

   22:
   23:' 正解判定
   24:   IF NUM=R THEN
   25:' 正解のとき
   26:      PRINT "正解です。おめでとうございます"
   27:      DATAOK=1
   28:   ELSE
   29:' 正解ではないとき
   30:      IF NUM
   31:' 小さすぎるとき
   32:         PRINT "小さすぎます"
   33:      ELSE
   34:' 大きすぎるとき
   35:         PRINT "大きすぎます"
   36:      END IF
   37:   END IF
   38:WEND ' 正解が出るまでの繰り返しここまで
   39:END


                               図13-4.数当てゲームのプログラム


 プログラムスタート部分の1行目のCLSはCLear Screenの省略形で実行画面をすべて消去する命令です。表示が消去されるだけで記憶されているプログラムやデータが消去されるわけではありません(黒板消しのようなものです)。
 2行目は今、説明した乱数の初期化です。3~5行目はプログラムと遊び方の説明です。
 7行目がコンピュータが隠す数を発生させるところですが、ここでは1から100までの数を発生させることにします。
 プログラム全体の流れとしては、最初にコンピュータが数を隠した後、正解が出るまで答えの入力を繰り返し実行されるようになっています。そしてプレイヤーが答えた数が1~100以外の数以外のときは入力がやり直しになるようになっています。それは11、38行目のWWHILE~WENDと15行、20行目のWHILE~WENDのネスティングで実現しています。この手法は実務プログラムではオペレータの入力ミスを防ぐ対策としてよく使われるものです。覚えておいて損はありません。
 19、29行目のIF~END IFは正解不正解の判定です。正解ならこのプログラムを終了するように、不正解なら回答した数が大き過ぎか小さ過ぎかを表示するようにしています。


図13_5.数当てゲームの実行画面
図13_5.数当てゲームの実行画面


【いろいろなエラー】

 ここまでいろいろなプログラムを作ってきた皆さんは、いろいろなエラーを出してきたと思います。エラー(error)とは「誤り」とか「失敗」という意味です。何回もエラーを出して「俺にはプログラミングの才能なんてないんだ」と落ち込んでいる人はいませんか。気にする必要はありません。勉強中はむしろどんどんエラーを出してください(*)。筆者の経験で言えば、エラーを出してそれを修正してゆく中で学べるものはたくさんあります。

(*)Perl、PHP、C言語、アセンブリ言語などハードウェア、サーバーを直接操作するプログラミング言語の場合、パソコンをローカル環境(ネットワークから切り離したスタンド・アローンな状態)にして勉強してください。

 プログラミングで発生するエラーは大別すると次の3つになります。


文法エラー(Syntax error)

 文法エラーというより構文エラー(書き方の誤り)です。たとえば次のプログラムを実行しようとすると、図14-6のような状態でコンピュータは止まってしまいます。

     1:GOKEI=0
     2:NINZU=0
     3:BANGO$=""
     4:WHILE BANGO$<>"//"
     5:READ BANGO$,NAMAE$
     6: IF BANGO$<>"//" THEN
     7:      PRIMT BANGO$;" ";NAMAE$;" ";
     8:      INPUT "得点="・,TEN
     9:      GOKEI=GOKEI+TEN
   10:      NINZU=NINZU+1
   11: END IF
   12:WEND
   13:NINZU=NINZU-1
   14:HEIKIN=GOKEI/NIN
   15:PRINT USING "受験者 ##人";NINZU
   16:PRINT USING "平均点###.#";HEIKIN
   17:END
   18:DATA "001","相沢 恭平"
   19:DATA "002","小川 順子"
 (中略)
   54:DATA "037","渡部 浩司"
   55:DATA "//",""

図13-6.文法エラー
図13-6.文法エラー


プログラムの7行目を見ると、PRINTと書くべきところがPRIMTになっています。Tiny Basicにこんな命令はないので(変数とみなされてしまうため)、その後に続く内容と矛盾が生じてしまい、コンピュータが???状態になってしまったわけです。

実行エラー(execute error/running error)

 文法(書き方)の誤りはなくても、プログラム実行中に発生するエラーがあります。次の例は処理不可能なデータに当たってしまったコンピュータが「こんなのやってらんねぇ」となってしまった例です。
 上のプログラムを修正して次のようになりました。これを実行してみたところ図13-7のようになりました。
     1:GOKEI=0
     2:NINZU=0
     3:BANGO$=""
     4:WHILE BANGO$<>"//"
     5:READ BANGO$,NAMAE$
     6: IF BANGO$<>"//" THEN
     7:      PRINT BANGO$;" ";NAMAE$;" ";
     8:      INPUT "点数 ",TEN
     9:      GOKEI=GOKEI+TEN
   10:      NINZU=NINZU+1
   11: END IF
   12:WEND
   13:NINZU=NINZU-1
   14:HEIKIN=GOKEI/NIN
   15:PRINT USING "受験者 ##人";NINZU
   16:PRINT USING "平均点###.#";HEIKIN
   17:END
   18:DATA "001","相沢 恭平"
   19:DATA "002","小川 順子"
 (中略)
   54:DATA "037","渡部 浩司"
   55:DATA "//",""

図13-7.文法エラー
図13-7.実行エラー


 プログラム14行目は得点の合計を受験者数で割って平均点を計算するところですが、除数になる変数名がNINZUであるべきところNINになっています。この場合、プログラムの書き方としては誤っていないので文法エラーにはならずプログラムは実行開始されます。しかし変数NINの値は 0 なので14行目で処理不可能となり止まってしまいました(除数が0の割り算は不可能なのは算数でもコンピュータでも同じです)。

論理エラー(logical error)

 プログラムの文法上の誤りも入ってくるデータにも誤りはないのに、処理内容の誤りにより正しい処理結果が得られないエラーです。簡単な例で説明します。
 次の例はキーボードから単価と売上個数を入力し売上金額を計算するプログラムなのですが、単価100円、個数5と入力したところ金額が500円となるところが105円になってしまいました。

1:INPUT "単価=",TANKA
2:INPUT "個数=",KOSU
3:KINGAKU=TANKA+KOSU
4:PRINT "金額=";KINGAKU
5:END

図13-8.論理エラー
図13-8.論理エラー


 誤り箇所はプログラム3行目です。
    KINGAKU=TANKA*KOSU
 とするべきところが
            KINGAKU=TANKA+KOSU
になっています。この場合、プログラムの書き方に誤りはなく、データも変数TANKAの値が500、変数KOSUの値が5なので、KINGAKU=TANKA+KOSUの計算は問題なくできます。なのでプログラムは途中で止まらず最後まで実行されます。しかし得られた結果は求めているものではない、ということになります。
 このように論理エラーは途中でコンピュータが止まってしまうことがないので発見と修正が最もやっかいなエラーといえます。ゆえにこのような誤りのことを、みつけにくいという意味でバグ(bug、ダニのような小さな虫)、バグをみつけて修正することをデバッグといいます。

 コンピュータはたとえて言えば「忠実だけど融通がきかない部下」です。
「課長、この指示はこれでいいんですか?」
「おぅ、ありがとう。ここは間違い、こうしてくれ」
とはなりません。指示書が間違っていようが渡されたデータに誤りがあろうが、そのとおりに実行しようとします。たとえその結果、会社が倒産(システムがダウン)するとしてもです。コンピュータの計算(処理結果)が正確なのは正しいプログラムとデータが与えられていれば、の話です。

【この章のまとめ】

ゲームの主役は乱数である。

RNDは乱数を発生する関数である。

RANDOMIZEは乱数系列を初期化する。

プログラミング上のエラーには文法エラー実行エラー、論理エラーがある。

プログラムのミスをバグ、バグをみつけて修正することをデバッグという。

神岡鉄道廃線跡

 神岡鉄道はかってJR高山本線の猪谷(富山県)から奥飛騨温泉口(岐阜県)までを結んでいた第3セクター鉄道である。旧国鉄の神岡線を引き継ぎ1984年に開業したものの、わずか22年で全線廃止となった。廃線後も駅・線路などの施設は撤去されずに残り、保有していた2両の気動車KM-101/KM-151も神岡鉱山口駅に併設されている車庫(検車区)に保存された。
 神岡鉄道の保存状況は2008年、私が狭心症で入院する直前にこの目で確認しているのだが、その後はどうなっているのか、全くわからなかった。そこで休日の今日を利用して見に行ってくることにした。



↑クリックすると拡大画像で見られます

 猪谷を出るとしばらく高山本線と並走し、分離してすぐにこの鉄橋を渡ります。2008年に残っていたこの鉄橋、今はどうなったのかな、もしかしてもうなくなった?と思いきや、まだありました(嬉し涙)。

↑クリックすると拡大画像で見られます

 この鉄橋のある場所は地図上の赤線で示した所、撮影場所は🔴で示した位置。ここが富山と岐阜の県境。神岡鉄道はこの先岐阜県吉城郡神岡町(現・飛騨市)まで伸びていたので、終点の奥飛騨温泉口駅まで辿ってみたかったのだが、現在は新型コロナウィルス感染防止のため、県境を越えての移動は自粛が求められているので、今日はここまでで我慢我慢><

 ところでこの神岡鉄道、廃線後に鉄オタにとっては嬉しいゴタゴタがあった。2006年、当時の飛騨市長、船坂勝美氏が、神岡鉄道の線路を不定期の観光鉄道として存続させる道を模索する意向を表明した。この話は神岡鉄道からは施設・車両の無償譲渡、親会社の三井金属からは、経営失敗時の施設撤去に備えて15億円の寄付を受けることで合意し、鉄道復活に向けて動き出そうとしていた。しかし2008年の市長選で船坂市長は観光鉄道化を含めた当時の市政を批判する井上候補に敗北した。2代目市長井上久則氏は「15億円の寄付金は再開に向けての物とは考えていない。レールや鉄橋は撤去する」と表明し、鉄道再開はいったんは非常に困難な見通しとなった。ところがその後、2016年に都竹淳也3代目市長が就任すると、同年12月に市議会は補正予算に、廃線跡を活用した「ロスト・ライン・パーク」構想のための費用を盛り込み、シンポジウムの開催と、旧神岡鉱山前駅に保存中の車両の中の1両(KM-101)を旧奥飛騨温泉口駅に移設する事業を実施するとした。
 一方、市民団体などが運営する廃線跡を利用したレールマウンテンバイク「Gattan Go!!」(ガッタン ゴー)は2013年の利用者は26249人。2012年には鉄道の日実行委員会の日本鉄道特別賞を受賞という快挙を成し遂げ、2020年10月、廃線および構想から14年の歳月を経てついに動態保存による観光鉄道が実現した。


https://rail-mtb.com/about/history/
"https://rail-mtb.com/course/okuhida-gou/

 普通自動車の運転免許を持っていれば気動車の運転体験ができるようだ。それも(多少金額はかかるが)最終的には101/151の2両編成を本線で1.2km運転できるとのこと。老後の楽しみができた\(^ ^)/

【第12章】データの保存と再利用(2)データをブログラム中に置く

 前章のプログラムは出席番号、氏名、テストの得点すべてをキーボードから入力するものでした。作ったプログラムを実行してみていかがでしたか。データ入力がかなりたいへんだと感じた方も多いのではないでしょうか。小学校の先生なら(原則的には)すべての教科を担任の先生が教えます。中学・高校の先生なら担当教科は一つでも同じ学年の複数のクラスを担当することも多いでしょう。その度に出席番号、氏名、得点を入力することになり、入力が多くなればなるほど誤入力(誤操作)が発生する確率も高くなります。これをなんとかしましょう。

      1: *SAKKYOKUKA
      2: DATA "J.S.バッハ",1665,1750
      3: DATA "ベートーヴェン",1770,1826
      4: DATA "ショパン",1810,1849
      5: DATA "チャイコフスキー",1840,1893
      6: DATA "ドビュッシー",1862,1918
      7: DATA "//",0,0
      8: PRINT "偉大なる作曲家"
      9: RESTORE *SAKKYOKUKA
    10: NAMAE$=""
    11: WHILE NAMAE$<>"//"
    12:    READ NAMAE$,SEINEN,BOTSUNEN
    13:    IF NAMAE$<>"//" THEN
    14:       PRINT NAMAE$;" ";SEINEN;" ~";BOTSUNEN;
    15:    END IF
    16: WEND
    17: END


              図12-1.DATA文の内容をREAD命令で読み込むプログラム


[プログラム中にデータを入れる]


 図12-1
のプログラムを見てください。Tiny BASICでは固定的なデータはDATA文でプログラム中に置いてそれをREAD命令で変数に読み込むことができます。1行目はプログラム中の特定の場所に目印を付けるものでラベルといいます。ラベルを付けるときは半角の*に続けてラベル名を指定します。ラベル名の付け方の規則は変数名と同じです。

 2~4行目はDATAという指示語から始まって、その後に何か書いてあります。これはプログラム中に入れたデータです。このサンプルはクラシック音楽の作曲家の名前と生年、没年です。ラベルやDATA文は何かの動作をするわけではないので、プログラムを実行すると8行目から実行されます。
 12行目のREADはDATA文でプログラム中に埋め込まれたデータを変数に読み込む命令です。9行目のRESTOREはREAD命令で読み込むデータがどこからかを指示するものです。ここで1行目に付けたラベルの意味が出てきます。
 DATA文で入れるデータとREAD文で読み込む変数の型は一致していなくてはなりません。DATA文で用意されたデータの個数(a)とREAD文で指定した変数の個数(b)が一致していないとき、a<bだと余ったデータは無視されます。反対にa>bだと「お~い、データがないぞ」というエラーになります。このプログラムを実行すると図12_1.のようになります。


図12-2.DATA文の内容をREAD命令で読み込む
図12-2.DATA文の内容をREAD命令で読み込む


 DATA文で入れるデータはデータの型、読み込む変数の数が合っていればプログラム中のどこへ置いてもかまいません。またTiny BASICではDATA文は制御文ブロックの中に置いてもかまいません。DATA文は繰り返し処理や選択処理の対象にはなりません。図12-3のプログラムも図12-1のプログラムと同じ動作をします。

   1: RESTORE *SAKKYOKUKA
   2: *SAKKYOKUKA
   3: PRINT "偉大なる作曲家"
   4: DATA "j.S.バッハ",1665,1750
   5: NAMAE$=""
   6: DATA "ベートーヴェン",1770,1826
   7: WHILE NAMAE$<>"//"
   8:     READ NAMAE$,SEINEN,BOTSUNEN
   9:     DATA "ショパン",1810,1849
  10:    IF NAMAE$<>"//" THEN
  11:        DATA "チャイコフスキー",1840,1893
  12:        LIFE= BOTSUNEN-SEINEN
  13:        PRINT NAMAE$;" ";SEINEN;" ~";BOTSUNEN
  14:    END IF
  15:    DATA "ドビュッシー",1862,1918
  16: WEND
  17: DATA "//",0,0
  18: END


                          図12-3.DATA文を制御文ブロックの中に置く


 しかし、プログラム上は正しく動作するといっても、このようなプログラムはわかりにくいことこの上ないですね。後でプログラムの修正が必要になったとき作った当人でもかなり苦労すると思います。プログラムは後々のことを考えてわかりやすく書きましょう。

[固定的なデータをプログラムの中に置く]

 このREAD、DATA文を使って第11章の図11-4のプログラムを改良しましょう。前章のプログラムでの問題点は出席番号、氏名、試験の点数すべてをキーボードから入力することでした。ここでこのプログラムで扱うデータの「性格」を考えてみましょう。出席番号、氏名といったデータは普通に考えれば学年の途中で全員分が変わるということはそうそうあることではありません。このような固定的なデータをマスターといいます。これに対し、試験の点数は変動的なデータ(トランザクション、元々は取引、売買の意味)です(筆者の体育の成績は例外です。5段階評価で3以下しか取れたことありません💦)。
 効率良さを考えるならマスターデータはDATA文でプログラム中に置き、これをREAD命令で読み込みながらトランザクションデータをキーボードから入力するというのが一般的です。プログラムは図12-4のようになります。

      1:DIM BANGO$(100),NAMAE$(100),TENSU(100)            ' データ保存領域
      2:RESTORE *CLASS_MEIBO              ' READで読み込むデータの開始位置を指定
      3:PRINT "***テストの平均点***"
      4:GOKEI=0
      5:NINZU=0
      6:I=0
      7:
      8:  NUM$="-1"
      9:WHILE NUM$<>"999"   ' 出席番号が終端値ではない間、以下の処理を繰り返す
    10:    READ NUM$,SHIMEI$ ' クラス名簿のデータを1件ずつ読み込む
    11:    IF NUM$<>"999" THEN ' 終端マークでなければ以下の処理を行なう
    12:          PRINT NUM$;" ";SHIMEI$;
    13:          INPUT "点数 ",TOKUTEN
    14:          BANGO$(I)=NUM$
    15:          NAMAE$(I)=SHIMEI$
    16:          TENSU(I)=TOKUTEN
    17:          GOKEI=GOKEI+TOKUTEN
    18:          NINZU=NINZU+1
    19:          I=I+1
    20:    END IF                          ' 出席番号が終端マークでないときの処理ここまで
    21:WEND                            ' 出席番号が終端値ではない間の繰り返しここまで
    22:LASTNUM=I-1
    23:
    24: PRINT
    25:' 平均点と、各自の得点と平均点の差を求めて表示
    26:HEIKIN=INT(GOKEI/NINZU)
    27:PRINT USING "受験者は ###人";NINZU
    28:PRINT USING "平均点は ###点";HEIKIN
    29:PRINT
    30:' 各自の得点と平均点との差を求める
    31:FOR I=0 TO LASTNUM
    32:    TENSA=TENSU(I)-HEIKIN
    33:    PRINT BANGO$(I);" ";NAMAE$(I);TAB(20);     ' 出席番号、氏名を表示
    34:    PRINT USING "### (###)";TENSU(I);TENSA ' 得点と平均点との差を表示
    35:NEXT I
    36:END
    37:
    38:' クラスの名簿(出席番号と氏名)
    39:*CLASS_MEIBO
    40:DATA "A001","青木 郁夫"
    41:DATA "A002","岩本 浩司"
    42:DATA "A003","大田 喜美子"
    43:DATA "A004","加藤 正孝"
    44:DATA "A005","山口 小夜子"
    45:DATA "B001","江藤 今日子"
    46:DATA "B002","近藤 仁"
    47:DATA "B003","中田 真一"
    48:DATA "B004","森田 淳二"
    49:DATA "B005","渡辺 三郎"
    50:DATA "999",""            ' 終端マーク

           図12-4.マスターデータをプログラム中に置く


 今回はプログラムを見やすく、また処理結果を見やすくを意識してみました。
 まずプログラム中のあちこちに出てくる ' (アポストロフィー)に続くなんたらかんたらですが、これは注釈です。Tiny Basicでは半角の ' は引用符ではなく、その後から行の終わりまでが注釈であることを示します。行の先頭に ' を付けると1行全部が注釈行になります。注釈はプログラム実行の際、無視されますから、通常のキーボードから入力できる文字なら何でも書けます。アラビア文字、ハングル文字、キリル文字などもOKですが、プログラム保存の際、エンコーディングをUTF-8にする必要があります。後にプログラムの修正等が必要になったとき、この変数は何のため?ここでどういう処理やってるの?などをわかりやすくしておくため注釈はどんどん入れましょう。
 7、23、37行目は処理のかたまりをわかりやすくするために置いた空行です。空行を置くときは全角の空白(スペース)が入ってしまわないように気をつけてください(エラーになります。修正の際、探すのがけっこう大変です)。
24、29行目のPRINT(オペランドなし)は、実行画面上で1行空行を空けて画面を見やすくするためのものです。
 27、28行目のPRINT USINGは続く" "内で指定した書式にしたがってデータを表示するものでした(第7章の後ろの方でやりました)。" "内に書式設定子以外の文字を入れると、その文字はそのまま表示されます。ここでは受験者数と平均点の1の位を合わせて見やすくするために使っています。
 33行目に出てくるTABは、tabulatorの意味で昔、タイプライターを使ったことのある方なら、ああ、あれか、とピンときたと思います。TABは行の左端から( )内で指定した位置まで表示位置を移動するものです。表示位置を移動するだけで空白を埋めるわけではないので、PRINT USINGと併用すると各項目の位置を揃えて見やすく表示させることができます。
 38~50行目は10行目のREAD命令で読み込んでゆくデータ(今回の例ではクラス名簿マスタデータ)です。ここで10行目は
     READ ストリング変数1,ストリング変数2
なのでデータの並びはこれに従っていれば、たとえば
     DATA "A001","青木 郁夫"
     DATA "A002","岩本 浩司"
     DATA "A003","大田 喜美子"
と書くところを
     DATA "A001","青木 郁夫","A002"
     DATA "岩本 浩司","A003","大田 喜美子"
と書いてもTiny Basicの文法的には問題ないのですが、プログラムとデータの関係がわかりにくくなってしまいます。メモリ節約との戦いだった1980年代頃ならともかく、今のパソコンとTiny Basicでのプログラミングでは、メモリ節約よりプログラムがわかりやすい書き方でいきましょう。
 50行目はデータの終端です。出席番号が"//"だったらデータ読み込み終了なので、出席番号にあたるデータを // にしています。その後の "" はNULL(ヌルストリング)といい、何も文字がないストリングです。10行目のREAD命令は出席番号と氏名を読み込むようになっているので、データの終端でも氏名のデータがないとエラーになります。そこで氏名の部分にダミーのデータを置いておく必要があるのです。
 このプログラムの実行結果は図12-5のようになります。

図12-5.図12-4のプログラムの実行結果
図12-5.図12-4のプログラムの実行結果


 このようにマスタデータはDATA文でプログラム中に置いてREAD命令で読み込んでゆくようにすると入力が楽になると同時に入力ミスを防ぐことができます。またマスタデータに変動が起こったとき、DATA文の部分を追加・削除・修正すれば済むことになり、システム全体のメンテナンス性も向上します。

【昔はよかったなぁ】

 昔のBASICを使って、図12-4のプログラムを平均点以下の受験者を黄色で、さらに平均点より20点以上低い受験者を赤で表示する鬼畜なプログラムにしてみましょう(図12-6)。

図12-6.平均点より低い受験者を色付きで表示する
図12-6.平均点より低い受験者を色付きで表示する

 プログラムは図12-7のようになります。昔のBASICは文字に色を付けるのは簡単でした。行番号380に出てくるCOLOR命令がそれです。
 行番号200にGOTOという命令がありますが、これは無条件ジャンブといい、指定された行番号(またはラベル)まで処理の手順を飛ばすものです。今のTiny Basicにもあることはあります。ただしGOTO命令をむやみに使うとプログラムがわかりにくくなります。IT関連企業の中にはGO TO(GOTO)命令の使用を禁止している会社もあるくらいです。ただ、昔のBASICではどうしても使わざるを得ないケースがありました(第14章の【昔はよかったなぁ】に出てきます)。
 もうひとつ、DATA文のところを見てください。昔のBASICではDATA文に含まれるストリングは" "で囲む必要はありませんでした。昔のBASICではDATA文群はかなりすっきりと書けました。

図12-7.図12-4のプログラムの実行結果
図12-7.平均点より低い受験者を色付きで表示するプログラム


【この章のまとめ】

DATA文でプログラム中にデータを置くことができる。

DATA文で置いたプログラムはREAD命令で変数に読み込むことができる。

RESTORE文でREAD文で読み込むDATA文がどこからかを指示できる。

マスタデータはDATA文でプログラム中に置くようにすると、入力が楽になり、入力ミスも防ぐことができる。

マスタデータはDATA文で置くようにするとマスタデータのメンテナンス性が向上する。

PRINT USING" "とTAB( )を上手に組み合わせると処理結果を見やすく表示させることができる。

- CafeLog -