パソコン活用研究5番街(Visual Basic、Excel(VBA)、BASIC プログラミング研究)

キーボード入力

キーボードからの入力に関する命令、関数というと、INPUT, LINE INPUT, INKEY$, INPUT$,
KEY, ON KEY GOSUBといったところでしょうか。

INPUT および INKEY$の基本的な使い方については、BASIC超基本 、 BASIC超基本2 にて
とりあげました。また、リアルタイムゲーム作制のための実践的なキーボード入力に関するノウハウ
は、リアルタイムキースキャン でとりあげております。
ここでは、上記でとりあげた以外のキーボード入力に関する基本的なノウハウをまとめてみました。

1 キー入力待ちはINPUT$(n) が便利

INPUT,INPUT$,INKEY$ の違いはよろしいでしょうか。

  キー入力待ち 押されたキーを画面に表示 備考
INPUT 有 (リターンキーで入力確定) 複数の変数(数値、文字)入力可
INPUT$(n)  指定した文字数 (n) の入力
特殊キー入力可
INKEY$ 1文字(1byte)のみ入力
特殊キー入力可

例えば、INPUT$(3) とすると、3文字入力されるまで入力待ちします。
使い途といしては、いったんGAMEが終了して、もう一回やるかどうかを、"y" か "n"で答えさせるような
場合に一番適しているでしょう。

簡単な例をあげておきます。
<Input0.bas>

10 a$=input$(1)
20 if a$="Y" or a$="y" then goto 100  
30 if a$="N" or a$="n" then goto 200
40 goto 10
100 print "Contine":goto 10
200 print "end": end

2 キー入力による条件分岐 INSTRの使用

先ほどでてきた、 <Input0.bas> では、入力されたキーを IF文で判定して、それぞれの分岐先に
とばしていました。入力されるキーの種類がこれぐらいなら、まあいいでしょうが、5種類ぐらいのキーを
使い分けるゲーム、といったことになると、IF 文を5個並べることになります。そういう場合に、昔から
これぞBASICの定石といわれてきたのが、INSTR関数 の利用です。
簡単に INSTR の書式をあげておきます

INSTR ([<サーチ位置>], <文字列1>, <文字列2>)             
[  ]は省略可

文字列1 の中から 文字列2を捜します。サーチ位置には、文字列1の中で捜しはじめる位置を指定します。
INSTRは、文字列2が見つかればその位置を、見つからなければ0を関数値として返します。

以下に<input0.bas>をINSTR で書き換えたものをあげます。

10 a$=input$(1)
20 on instr("YyNn",a$) goto 100,100,200,200       
40 goto 10
100 print "Contine":goto 10
200 print "end": end

これぐらいのコードを書くと、素人のBASICプログラマとしては、「ちっとはBASIC知ってるな」とかコメント
されたものです。(大昔、アマチュアのBASICプログラムの雑誌への投稿が盛んだった時代の話。
いつかって?ウーム、パソコン進化の歴史からすると、縄文、弥生時代とでもいうべきか)

3 INSTRは早いか

BASICの場合は、やっぱり処理スピードが早いかどうかもきになります。
INSTR関数をつかって「お主、少しはやるじゃねーか」と言われても、スピードダウンになったんじゃ
お話になりません。それで、いちおう処理スピードについても検証してみました。

<inputsp0.bas>

N88互換BASIC for Win  22秒 Qbasic  22秒
10 width 80,20
20 cls
25 a$=""
30 t=val(right$(time$,2))
40 for i=0 to 1000
50 if a$="Y" or a$="y" then gosub 200    
55 if a$="N" or a$="n" then gosub 210 
60 next i
100 t1=val(right$(time$,2))
110 if t1<t then t1=t1+60
120 print t1-t :end
130 ' 22
200 return
210 return
10 'WIDTH 80, 20
20 CLS
25 a$ = ""
30 t = VAL(RIGHT$(TIME$, 2))
40 FOR i = 0 TO 300000
50 IF a$ = "Y" OR a$ = "y" THEN GOSUB 200   
55 IF a$ = "N" OR a$ = "n" THEN GOSUB 210
60 NEXT i
100 t1 = VAL(RIGHT$(TIME$, 2))
110 IF t1 < t THEN t1 = t1 + 60
120 PRINT t1 - t: END
130 ' 22
200 RETURN
210 RETURN

<inputsp1.bas>
IF文を1つにしてみました

N88互換BASIC for WIN  13秒 QBASIC  18秒
10 width 80,20
20 cls
25 a$=""
30 t=val(right$(time$,2))
40 for i=0 to 1000
50 if a$="Y" or a$="y" then gosub 200 
60 next i
100 t1=val(right$(time$,2))
110 if t1<t then t1=t1+60
120 print t1-t :end
130 ' 13  (for  nextループは5秒くらい)  
200 return
210 return
10 'WIDTH 80, 20
20 CLS
25 a$ = ""
30 t = VAL(RIGHT$(TIME$, 2))
40 FOR i = 0 TO 300000
50 IF a$ = "Y" OR a$ = "y" THEN GOSUB 200
60 NEXT i
100 t1 = VAL(RIGHT$(TIME$, 2))
110 IF t1 < t THEN t1 = t1 + 60
120 PRINT t1 - t: END
130 ' 18  (for__ next 13seconds)        
200 RETURN
210 RETURN

<inputsp2.bas>
INSTR関数使用

N88互換BASIC for WIN 15.5秒 QBASIC  16秒
10 width 80,20
20 cls
25 a$=""
30 t=val(right$(time$,2))
40 for i=0 to 1000
50 on instr("YyNn",a$) gosub 200,200,210,210 
60 next i
100 t1=val(right$(time$,2))
110 if t1<t then t1=t1+60
120 print t1-t :end
130 ' 15.5
200 return
210 return
10 ' WIDTH 80, 20
20 CLS
25 a$ = ""
30 t = VAL(RIGHT$(TIME$, 2))
40 FOR i = 0 TO 300000
50 ON INSTR("YyNn", a$) GOSUB 200, 200, 210, 210   
60 NEXT i
100 t1 = VAL(RIGHT$(TIME$, 2))
110 IF t1 < t THEN t1 = t1 + 60
120 PRINT t1 - t: END
130 ' 16
200 RETURN
210 RETURN

ええとですね、これぐらい単純なプログラムだと、For ... Next のループ自体にかかる時間が無視できない
レベルにあるので、For ... Next ループ自体にかかる時間を考慮して下表のようにまとめてみました。

  N88互換Basic for Win QBASIC       
For ... Nextループ 5 秒 13 秒
IF文 2個(Inputsp0.bas) 17 秒 9 秒
IF文 1個(Inputsp1.bas) 8 秒 5 秒
INSTR関数(inputsp2.bas) 10.5 秒 3 秒

人それぞれ、いろんな評価があるでしょうが、実用上 INSTRを使うことは速さの点でも有益だと
言えましょう。ことにQBASICでの利用価値は高いと言えます。

蛇足ながら、N88互換BASIC と QBASIC でループの回数は300倍違います。ご注意。


4 LINE INPUT の利用

INPUTで文字列を入力する場合、カンマ(,)は、区切り記号として使うので、データとして入力できません。
カンマもデータとして入力したい場合は、LINE INPUTを使えばO.K.です。
LINE INPUT はリターンキーが押されるまでの文字列を全てデータとして入力します。
(本来、LINE INPUTはファイルからの読み込みの方でよく使われる)

以下に、入力された文字列を、カンマのところでばらばらに区切って表示するプログラムを
あげておきます。他に、MID$, RIGHT$, LENなど文字列関連の関数も使った例になってますので
Very Short な中に、濃い内容がつまったプログラムです。ビタミン剤のようなプログラムですから、
BASICはじめたバカリダヨーという人は、じっくり味わって消化して下さい。  
<LINPUT.bas>

5 position=1:p=1
10 line input a$
20 while p
30 p=instr(position,a$,",")
35 if p=0 then goto 60
40 print mid$(a$,position,p-position)
50 position=p+1
60 wend
70 print right$(a$,len(a$)-position+1)   

QBASIでの実行結果

C:\QBASIC>qbasic
kasai,tsuyoshi,age,25,year,1995        
kasai
tsuyoshi
age
25
year
1995



5 入力されたキーのアスキーコードの取得


入力されたキーのアスキーコードを利用したい場合というのがあります。
例えば、[Esc] キー や -> のような矢印キーの入力の判定といった場合です。
このような時は、ASC関数を使います。

下のプログラムは何をやってるかと言うと、テキストファイルを読み込んで、画面に表示されない特殊キー
は[  ]内にアスキーコードを表示するというプログラム。75行に注目。
それから、80行は、読み込んだデータがラインフィード(LF アスキーコード10)だったら改行させている。
MS-DOSのTYPE コマンドにプラスαの機能をつけた感じのもの。
<KTYEPE.bas> QBASIC用

10 cls:key(1) on
20 on key(1) gosub 120  'N88互換BASIC用には on key gosub 120 でよい  
30 on error goto 100
40 input "File Name :",file$
50 open file$ for input as #1
60 while not(eof(1))
70 a$=input$(1,#1)
75 if asc(a$)>31 then print a$; else print "["+str$(asc(a$))+"]";    
80 if asc(a$)=10 then print
90 wend
100 close
110 key(1) off:end
120 return 100

これも、QBASICの実行例をいちおうつけときます。自らを読みこんでみました。

File Name :ktype.bas
10 cls:key on[ 13][ 10]
20 on key gosub 120[ 13][ 10]
30 on error goto 100[ 13][ 10]
40 input "File Name :",file$[ 13][ 10]
50 open file$ for input as #1[ 13][ 10]
60 while not(eof(1))[ 13][ 10]
70 a$=input$(1,#1)[ 13][ 10]
75 if asc(a$)>31 then print a$; else print "["+str$(asc(a$))+"]";[ 13][ 10]      
80 if asc(a$)=10 then print[ 13][ 10]
90 wend[ 13][ 10]
100 close[ 13][ 10]
110 key off:end[ 13][ 10]
120 return 100[ 13][ 10]
[ 13][ 10]


6 KEY, ON KEY
プログラム実行中に、キーを押して、割り込みをかけたい場合に使います。
上述の<KTYPE.bas>の10、20、110行目をみて下さい。
上述のプログラムでは、長いファイルを読みこんでいる時に、もう途中であきた、中断したいというケース
を想定して、ファンクションキー1(F1)を押せば、プログラムが終了するようにしてあります。
それが、10、20、110行目です。

KEY ON, KEY OFF は割り込みの許可、解除をします。
プログラム終了前に必ず KEY OFFする必要があります。さもないと、本来のファンクションキーの
機能がつかえないままとなります。

ON KEY GOSUB 割り込みルーチンの開始行の定義をしますが、N88互換BASIC for WIN と
QBASIC で若干書式と機能が異なります。

N88互換BASIC for WIN

KEY [(キー番号)] ON          
[  ]は省略可
キー番号には1から10までのファンクションキーの番号を指定する。省略すると全てのキーを指定した
ことになる。


ON KEY GOSUB 行番号, [行番号], ....
[  ]は省略可
行番号には、割り込みのかかった時に分岐させたいルーチンの開始行を指定する。
行番号は、はじめから順に、F1,F2,F3・・・を押した場合に対応する形になる。


QBASIC
QBASICの場合は キー番号が若干異なる。また、KEY( ) ON, OFFでキー番号を省略することは
できないようだ。
キー番号は 1から10がファンクションキー(これは同じ)、11が上矢印、12が左、13が右、14が下と
なっている。0を指定すると、全てのキーを指定したことになる。

また、割り込み開始行の定義は、ON KEY(キー番号) GOSUB という形で、必ずキー番号を指定
する形になる。


*今回とりあげたプログラムは<KTYPE.bas>以外は、N88互換BASIC for WIN 、QBASIC
ともに共通です。

TOP PAGE >Basic活用研究目次