99Basicインタプリタ(手引き書) - ディスク / FILE操作の関係


◇ CLEAR

 変数を初期化します。
 書式1: CLEAR
 書式2: CLEAR [テキスト領域][,[変数領域][,[文字列領域][,ファイル数]]]
 書式3: CLEAR SYSTEM
ファイル数 -------- 同時にオープンできるファイルの最大数を設定します(0〜20の整数)
透明スペーサー
 ファイル数については何も指定しなければ、標準では同時に 4 ファイルしかオープン出来ませんが、
CLEAR , , , 20
 とすると、20ファイルまで同時に開けます。但しその分、メモリを多く消費します。
30 CLEAR , , , 20
 実際には、このようにプログラムの初めのほうに書きます。
 なお、これについては私はテスト確認をしていません。
透明スペーサー
 ちなみにファイルを同時に開ける数は、DOS-N88BASICでは最大10?(少なくとも私は10まで開いていました)。N88互換BASICでは最大8です。

Top  99Menu


◇ OPEN

 ファイルをオープンする。
 書式: OPEN ファイル名 [FOR <INPUT‖OUTPUT‖APPEND‖INPUT,OUTPUT‖INPUT,APPEND‖OUTPUT,APPEND] AS #ファイル番号
ファイル番号....1〜4 の数値
 DOS-N88BASICでは最大10?(少なくとも私は10まで開いていました)。N88互換BASICでは最大8までファイルを同時に開けましたが、99Basicでは最大4となります。この部分の修正は必要になります。しかし、以下の方法で拡張出来るようです。
◇ 最大20までファイルが開ける
 CLEAR , , , 20 を宣言しておくと、OPEN ファイル番号#は 1〜20になるそうです。
 (但しその分、メモリを多く消費します。)
 プログラム修正後にこれを発見したので、私はテストしていませんが、、。

*書式: OPEN ファイル名   [ FOR INPUT,OUTPUT] の場合
 オープンされるファイルは、読み書き両用シーケンシャルファイルとなります。
例文
740 OPEN D_BC$+"SH"+NT$(SW) FOR INPUT AS #2
750 FOR I=1 TO 1000: IF EOF(2)=0 THEN INPUT #2, NSA$(I) : IMAX1=I: NEXT I
1720 OPEN SH$ FOR OUTPUT AS #2
1740 WRITE #2,NSA$(IX)
透明スペーサー
*書式: OPEN ファイル名   [(無し)] AS #ファイル番号の場合
 [(無し)]   オープンされるファイルは、ランダムアクセスファイルとなります。したがって、LOC 関数や LOF 関数での戻り値は、レコード単位の数値となります。
例文
6010 OPEN DR$+"カイケイ."+YY$ AS #2
6025 '' FIELD #2, 51 AS W$ '' WIN互換ベーシック
6025 FIELD #2, STEP 51, 51 AS W$ '' 99Basic
◇注意
 このOPEN と FIELD で決めた変数(この場合は W$ )の取扱いに注意が必要。
 これ以降でもし、W$="**********"などが入ると、 GET #2, Iでその後に新しい W$ を得たはずが、全て同一のW$="**********"になってしまいます。
  注意 : ここでは例としてW$としましたが、それがA$、B$、C$でも同じハズです。

Top  99Menu


◇ OPEN 拡張子無しのファイル名

500 OPEN "WORK" FOR OUTPUT AS #3
 このように OUTPUT で、拡張子の無いファイル名"WORK"を指定すると、開かれるのは"WORK."ではなく、"WORK.dat"が作られてしまいます。
 ちなみにDOS-N88BASICとN88互換BASICでは、拡張子の無いファイル名"WORK"が正しく開かれます。正確には"WORK."なのかも知れませんが、。
透明スペーサー
600 OPEN "WORK" FOR INPUT AS #3
 このように INPUT で、拡張子の無いファイル名"WORK"を指定すると、「ファイルが見つからない」というエラーになります。
透明スペーサー

◇解決策
500 OPEN "WORK." FOR OUTPUT AS #3
600 OPEN "WORK." FOR INPUT AS #3
 "WORK."
 というように、.(ピリオド)を付けておけば大丈夫です。

Top  99Menu


◇ CLOSE

 すでに開いているファイルを閉じます。
透明スペーサー
6005 CLOSE #1, #2
 上記は#1, #2のファイルだけを閉じるという命令で、DOS-N88BASICとN88互換BASICでは通用しますが、99Basicでは文法エラー。次のように2つに分ければOKです。
6005 CLOSE #1 :CLOSE #2
透明スペーサー
 #番号を付けずに、ただ「 CLOSE 」とすれば、#1〜4までの全てを閉じます。#3, #4は開いたままで#1, #2のファイルだけを閉じるときには、上記のようにします。

Top  99Menu


◇ FIELD

 ファイルバッファ内に変数を割りつけます。
 書式: FIELD #ファイル番号[[,]<STEP レコード長‖CONT>],長さ AS 文字列変数[,長さ AS 文字列変数,...]
 FIELD 命令は、PUT 命令や GET 命令でランダムアクセスファイルをアクセスするときに使用される変数を、定義するための命令です。
例文
8720 OPEN DR$+"カイケイ."+YY$ AS #2
8730 FIELD #2, STEP 51, 51 AS W$
8750 I=LOF(2): ' ' IF DR2$="WIN互換ベーシック" THEN I=LOF(2)/51
 この「STEP 51, 」を入れないと、「#2, 51 」は無効で、256 バイト単位としてしまいます。逆に言えば、もし256 バイト単位で扱っていたプログラムなら、変更の必要はありません。
 ちなみにDOS-N88BASICまたはN88互換BASICからの移植の場合は、256 バイト単位以外なら必ず「STEP 51, 」の挿入が必要になります。
透明スペーサー

◇OPEN-FIELD-W$での注意 (GET W$の化け)

 このOPEN と FIELD で決めた変数(この場合は W$ )の取扱いに注意が必要。
  注意 : ここでは例としてW$としましたが、それがA$、B$、C$でも同じハズです。
8720 OPEN DR$+"カイケイ."+YY$     AS #2
8730 FIELD #2, STEP 51,  51 AS W$

9020 FOR I=B2 TO B3
9030    GET #2, I-1 : PRINT W$
 OPEN と FIELD宣言で使った変数(この場合は8730行のW$)を、それ以降でW$の変更は厳禁です。
 もしW$="**********"、またはMID$(W$, A, B)=A$(N) などでW$を変更すると、その後に GET #2, Iで新しい W$ を得たはずが、全て同一のW$="**********"などになってしまいます。
 N88互換BASICでは、毎回、新しい(本来の)内容のW$が得られる。DOS-N88BASICでも私の記憶では、N88互換BASICと同様だったハズ?
◇解決策
2565 ' LSET W$=D$(1): PUT #2,R '' N88互換BASIC
2570 LSET W$=D$(1): PUT #2,R-1 '' 99Basic = -1
 このように PUT # , でファイルの書き込みをするときに、初めて LSET W$=D$(1)でW$を書き換えます。

Top  99Menu


◇ LOF( )

 書式: LOF([#]ファイル番号)
 ファイル番号 ‥‥ 1〜4の数値  (# は省略可能です。)
 ファイル番号で指定されたファイルの、ファイル長を返します。
 もしシーケンシャルファイルならバイト数でファイル長が得られ、
 ランダムファイルなら、レコード数としてファイル長が得られます。(これはDOS-N88BASICと同じ)
 しかし、N88互換BASIC for Windows95では、ファイルの大きさをバイト単位で与えます。


 この違いを、以下のように修正する必要があります。
330 I=LOF(2): IF DR2$="WIN互換ベーシック" THEN I=LOF(2)/51
330 I=LOF(2): '  99Basic

6030 I=LOF(2): IF DR2$="WIN互換ベーシック" THEN I=LOF(2)/51
6030 I=LOF(2): '  99Basic

Top  99Menu


◇ GET #

 ランダムファイルから、ファイルバッファへ1レコード読み込みます。
 書式: GET #ファイル番号,レコード番号
 ファイル番号...1〜4 の数値
 レコード番号...0 以上の数値
 レコードの長さは、通常 256 バイトですが、FIELD 命令で特に指定した場合は、その指定値となります。
 レコード番号 0 が、ファイルの先頭となります。
 現在の読み出し位置とは関係なく、指定されたレコード番号の位置から読み出してきます。この命令の後、読み出し位置は、このレコード番号の次の位置となります。
透明スペーサー
 DOS-N88BASICとN88互換BASICでは、<レコード番号>は1から始まります。この部分を修正しないと、1番目のレコードを読まずに、読み出した結果は誤ったものになる可能性があります。
 また最後では、最大数を1つ超えたたためにエラーとなります。
 PUT #と同じく、この番号が99Basicでは -1 の修正が必要です。
 この時、「ファイルは、すでに最後まで読み込まれている」のメッセージが出ます。
 ちなみに PRINT ERR を実行すると、その時のエラー番号、
PRINT ERL を実行すると、その時のエラー発生行の番号が表示されます。
 99Basicのヘルプで「エラーコード」を調べると、次のようになっています。
55  File OPEN failure     ファイルがオープンできなかった
56  Input past end      ファイルは、すでに最後まで読み込まれている
透明スペーサー
 しかしある時に出た私のエラーでは、日本語メッセージは「ファイルは、すでに最後まで読み込まれている」でした。
 ところが PRINT ERRで調べると、55になっていました。
 大したことではありませんが、発生した ERRとヘルプファイルのエラー番号のにズレがありました。これが全体的なことなのか、この55など一部だけなのかは不明ですが、、
▼ N88互換BASICでは、GET #ファイル番号に変数を使うことが出来ません。そのため、以下のように書く必要があったのですが、
645    IF VV=1 THEN GET #1,R ELSE IF VV=2 THEN GET #2,R ELSE IF VV=3 THEN GET #3,R  ''  N88互換BASIC
650    IF VV=4 THEN GET #4,R ELSE IF VV=5 THEN GET #5,R ELSE IF VV=6 THEN GET #6,R  ''  N88互換BASIC
655    IF VV=7 THEN GET #7,R ELSE IF VV=8 THEN GET #8,R  ''  N88互換BASIC

▼ 99BasicではDOS-N88BASICと同様に、GET #ファイル番号に変数を使うことが出来て便利です。
500 FOR VV=1 TO 8
645     GET #VV , R  -1   ''  99Basic =  -1

6050 ' FOR WI=0 TO 4: GET #2,I-WI: IF VAL(MID$(W$,1,5))=9999 THEN I=I-WI -1  ELSE       NEXT WI '' WIN互換ベーシック
6060   FOR WI=0 TO 4: GET #2,I-WI: IF VAL(MID$(W$,1,5))=9999 THEN I=I-WI -2  ELSE       NEXT WI '' 99Basic

9730 ' GET #2,I      ''  N88互換BASIC と DOS-N88BASIC
9735   GET #2,I -1   ''  99Basic

◇ GET #  その2.=新しく GET した変数が化ける(変わらない)

 新しく GET した変数は、新しい値に変わるべきなのが、変化しないのです。
8720 OPEN DR$+"カイケイ."+YY$     AS #2
8730 FIELD #2, STEP 51,  51 AS W$

9020 FOR I=B2 TO B3
9030    GET #2, I-1 : PRINT W$
 OPEN と FIELD宣言で使った変数(この場合は8730行のW$)を、それ以降でW$の変更は厳禁です。
 もしW$="**********"、またはMID$(W$, A, B)=A$(N) などでW$を変更すると、その後に GET #2, Iで新しい W$ を得たはずが、全て同一のW$="**********"などになってしまいます。

Top  99Menu


◇ PUT #

 書式: PUT #ファイル番号,レコード番号
 ファイルバッファに置かれているデータを、ランダムアクセスファイルの、指定されたレコード番号の位置に書き込みます。
 現在のファイル読み書き位置とは関係なく、指定されたレコード番号の位置に書き込みます。この命令の後、ファイル書き込み位置は、このレコード番号の次の位置となります。
 レコード番号 0 が、ファイルの先頭となります。FIELD 命令で特に指定した場合は、その指定値となります。
 GET #と同じく、この番号が99Basicでは -1 の修正が必要です。
▼ N88互換BASICでは、PUT #ファイル番号に変数を使うことが出来ません。そのため、以下のように書く必要があったのですが、
5615   IF VV=1 THEN PUT #1,R ELSE IF VV=2 THEN PUT #2,R ELSE IF VV=3 THEN PUT #3,R ELSE IF VV=4 THEN PUT #4,R  ''  N88互換BASIC
5620   IF VV=5 THEN PUT #5,R ELSE IF VV=6 THEN PUT #6,R ELSE IF VV=7 THEN PUT #7,R ELSE IF VV=8 THEN PUT #8,R  ''  N88互換BASIC

▼ 99BasicではDOS-N88BASICと同様に、PUT #ファイル番号に変数を使うことが出来て便利です。
5500 FOR VV=1 TO 8
5610    PUT #VV , R     ''  N88互換BASIC と DOS-N88BASIC
5615    PUT #VV , R -1  ''  99Basic =  -1

Top  99Menu


◇ INPUT #

 書式: INPUT <[#ファイル番号,]‖[[WAIT 時間,]プロンプト文字列<,‖;>]<変数名[,変数名,...]
 シーケンシャルファイルから、文字列を入力し、変数に代入します。入力する文字列は、カンマで区切られた、変数の型と数に合ったものでなければなりません。
 ダブルコーテーションで囲まれた文字列が入力された場合は、ダブルコーテーションがはずされた文字列が得られます。
 PRINT # でファイルに出力した文字列は、カンマで区切られていないため、99 BASIC では正常に読みとることが出来ません。INPUT # で読みとる内容のファイルは、WRITE # で作成して下さい。
例文
160 INPUT #1,FA$(B)

 DOS-N88BASIC、N88互換BASICと比べかなり癖があり、使い方の難しいコマンドです。説明も大量にあるので、詳しくは別ページに分けました。

Top  99Menu


◇ PRINT #

 シーケンシャルファイル用の出力命令の1つです。(他にもシーケンシャルファイル用の出力命令として、WRITE #があります。)
 「PRINT # でファイルに出力した文字列は、カンマで区切られていないため、99 BASIC では正常に読みとることが出来ません。INPUT # で読みとる内容のファイルは、WRITE # で作成して下さい。」と書かれています。
 しかし私の場合は、PRINT # で出力の1データーを1行として、間にカンマ区切りを入れていないので、別に問題なく使えています。
例文
1220 PRINT #3, " ": PRINT #3, "** ";YMD$ ; "年度  スキー学校 決算 ** ";DATE$
1235 PRINT #3, USING PU0$;"  科  目";: PRINT #3, "  "; Y0$; "         ";Y1$ ;A4$ ; "         合  計"
1245 FOR G=G2+1 TO G4              '    収入科目〜支出科目
1250    PRINT #3, USING PU0$; F$(G);: PRINT #3, USING PU3$; H#(0,G); H#(1,G); H#(2,G)
1255 NEXT G
1265 PRINT #3, X1$; X1$
1270 PRINT #3,    TAB(17); Y0$; "         ";Y1$ ;A4$ ; "         合  計"   '  DOS-N88BASICとN88互換BASIC
1270 PRINT #3, SPACE$(17); Y0$; "         ";Y1$ ;A4$ ; "         合  計"   '  99Basic
1280 PRINT #3, USING PU0$;"> 収  入 <";: PRINT #3, USING PU3$ ;H3#(0) ;H3#(1) ;H3#(0)+H3#(1)
1285 PRINT #3, USING PU0$;"> 支  出 <";: PRINT #3, USING PU3$ ;H4#(0) ;H4#(1) ;H4#(0)+H4#(1)
 基本的には、PRINT #については、99Basicだからという変更は無いように思います。
 上記のTAB( )→ SPACE$( )への変更については、PRINT #そのものによるものではありません。

Top  99Menu


◇ WRITE #

 シーケンシャルファイル用の出力命令の1つです。(他にもシーケンシャルファイル用の出力命令として、PRINT #があります。)
 ちなみに、PRINT # の解説の中に、
 「PRINT # でファイルに出力した文字列は、カンマで区切られていないため、99 BASIC では正常に読みとることが出来ません。INPUT # で読みとる内容のファイルは、WRITE # で作成して下さい。」と書かれています。
透明スペーサー
例文
3340 CLOSE #9: OPEN D.BC$+"SH"+NT$(VV.VV) FOR OUTPUT AS #9 ' DOS-N88BASICとN88互換BASIC
3340 CLOSE #9: OPEN D.BC$+"SH"+NT$(VV.VV)+"." FOR OUTPUT AS #9 ' 99Basic
3350 FOR D=1 TO UMAX: IF NSA$(D)<>"" THEN WRITE #4,NSA$(D): NEXT D
透明スペーサー
 基本的には、PRINT #については、99Basicだからという変更は無いように思います。
 上記の+"."を挿入の変更については、WRITE #そのものによるものではありません。

Top  99Menu


◇ WRITE # と PRINT # の違い

◇ 出力dataに" "ゴミが付く(ダブルコーテーション)

Data-1
Data-2
Data-3
 上のような結果をデーターとして出力したいのに、下のように" "で挟まれてダブルコーテーションのゴミが付いて困る場合の対策です。
"Data-1"
"Data-2"
"Data-3"
3030 OPEN  DR$+ FILE_O$      FOR OUTPUT AS #2
3040 FOR I=1 TO 500
3070    シーケンシャルファイル用の出力命令行
3150 NEXT I
 例えば上記のようなプログラムで、出力命令行を
3070 WRITE #2,OU_T$(I)
 このようにWRITE #を使えば、出力データーはダブルコーテーションで挟まれます。
"Data-1"
透明スペーサー
3070 PRINT #2,OU_T$(I)
 このようにPRINT #を使えば、出力データーはダブルコーテーションは付きません。
Data-1
透明スペーサー
 ちなみに、PRINT # の解説の中に、
 「PRINT # でファイルに出力した文字列は、カンマで区切られていないため、99 BASIC では正常に読みとることが出来ません。INPUT # で読みとる内容のファイルは、WRITE # で作成して下さい。」と書かれています。
 この点に関係ある場合は、注意して下さい。

Top  99Menu



◇ ファイル関係での一連の要修正部分

6000 ' ---------- Sub. FILED Open #2 ---- 870,20005
6005 CLOSE #1: CLOSE #2
6010 OPEN DR$+"カイケイ."+YY$   AS #2
6025  '' FIELD #2,          51 AS W$  ''  WIN互換ベーシック
6025     FIELD #2, STEP 51, 51 AS W$  ''  99Basic
6027 '
6030 I=LOF(2)/51        ''  WIN互換ベーシック
6030 I=LOF(2) '' /51    '' 99Basic

6040    IF I=0 THEN 6110
6050 ' FOR WI=0 TO 4: GET #2,I-WI: IF VAL(MID$(W$,1,5))=9999 THEN I=I-WI -1  ELSE       NEXT WI '' WIN互換ベーシック
6060   FOR WI=0 TO 4: GET #2,I-WI: IF VAL(MID$(W$,1,5))=9999 THEN I=I-WI -2  ELSE       NEXT WI '' 99Basic
6110 IL0F=I

2070 ' GET #2,I    ''  WIN互換ベーシック
2080   GET #2,I -1  ''  99Basic

5500 FOR VV=1 TO 8
5610    PUT #VV , R     ''  N88互換BASIC と DOS-N88BASIC
5615    PUT #VV , R -1  ''  99Basic =  -1
 上記の赤文字が、要修正の部分です。

Top  99Menu


KILL ファイル削除

ディスク上のファイルを削除します。
 書式: KILL ファイル名
ファイル名......文字列
ファイル名を指定して、そのファイルを削除します。削除しても良いかの確認はしません。無条件に削除してしまいます。ワイルドカードも使えます。
 同じディレクトリー(=フォルダー)内に存在するファイルであれば、
  KILL ファイル名
 別のディレクトリー(=フォルダー)内に存在するファイルであれば、
  KILL C:\0h\homePAGEt\ファイル名
  このようにフルに書く必要があります。
 ちなみにワイルドカードとは、* = 以降の全て、 ? = その1文字
 例えば *.TXT なら、ファイルは全てを対象に、拡張子がTXTのファイル。
 AB*.TXT なら、初めの2文字がABで、以降の文字は何であれ、拡張子がTXTのファイル。
 AB??EF.TXT なら、初めの2文字がABで、続く2文字は何であれ、さらに続く2文字はEFで、かつ拡張子がTXTのファイル。
  KILL *.*
 万一これを実行すれば、そのディレクトリー(=フォルダー)内に存在するファイルの全てが、確認も無しに削除されてしまうのです。


 この命令については、DOS-N88BASICと全く同一では無いかと思います。それをわざわざここに書いたのは、
 久しぶりにプログラムを組むと、コマンドなどなかなか思い出せないものです。私は、「 DELETE ファイル名 」と書いてしまい、「文法どおりに記述されていない」というエラーが出ました。
 そういえば、「 DELETE 行番号-行番号 」式に使い、画面上で実行プログラムのある行範囲(または行)を削除するものでした。
 ところが、このファイル削除の KILL が思い出せず、いろいろ調べ、やっとたどり着いたというような訳でした。
 ですから、皆さんの中にも忘れていて、苦労している方がいらっしゃればと考え、ここに載せた次第です。

Top  99Menu