忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

BHT-BASIC4.0:データファイルの検索について(SEARCH関数)
データファイルの読み込みで、最初に既に入力されているコードを検索し、 そのコードに対応したレコード番号で行う場合があります。 データのメンテナンス処理ではこの方法が普通かと思います。

今回は標準関数の SEARCH関数 を使ってみます。

■SEARCH関数について
SEARCH関数の定義は以下の様です。
SEARCH([#]<ファイル番号>,<フィールド変数>,<検索データ>[,<開始レコード>])

 <ファイル番号>:1~16の値を返す数値式
      (OPEN命令で指定したファイル番号を指定)
 <フィールド変数>:文字型単純変数
      (FIELD命令の前に宣言されている変数を指定)
 <検索データ>:文字列式

 <開始レコード>:数値式
      (検索を開始するレコードの番号を指定、省略時は先頭から)

 返す値:検索できたレコード番号、見つからない場合は0が返る
      (返す値は長整数型変数か実数型変数で代入)

データファイルからコードを指定し検索する関数を以下の様に定義します。
'---------------------------------------
'データ検索
'---------------------------------------
'Function MfSearchData%(Byval pstrCD$, Byref plngNum&, Byref plngRecNo&)
'引 数:
'	pstrCD$		:コード
'	pdblVal$	:数量
'	plngRecNo&	:レコードNO
'戻り値:
'	MfSearchData%	:読込OK:GcTrue%, NG:GcFalse%
'---------------------------------------
	Function MfSearchData%(Byval pstrCD$, Byref plngNum&, Byref plngRecNo&)
		'エラー処理宣言
		On Error Goto MfSearchData.ErrProc
		'フィールドサイズ
'		Const COL.CD% = 10	'上の関数[MfPutData%]で定義済み
'		Const COL.NUM% = 26
		'戻り値の初期化
		MfSearchData% = GcFalse%

		PRIVATE FILENO%, REC.CD$, REC.NUM$
		'TEST.DATファイルを、ファイル番号#1としてオープンします
		FILENO% = 1
		OPEN GcTEST.DAT$ AS FILENO% RECORD 2147483647
		FIELD #FILENO%, COL.CD% AS REC.CD$, COL.NUM% AS REC.NUM$
		
		PRIVATE W$
		W$ = LEFT$(pstrCD$ + GfSpc$(COL.CD%), COL.CD%)	'既定の桁数分スペースを付加
		IF plngRecNo& <= 0 THEN
			'先頭から検索
			plngRecNo& = SEARCH(#FILENO%, REC.CD$, W$)
		ELSE
			'指定レコード位置から検索
			plngRecNo& = SEARCH(#FILENO%, REC.CD$, W$, plngRecNo&)
		ENDIF
		IF plngRecNo& <> 0 THEN
			'読込
			GET FILENO%, plngRecNo&
			'値を返す
			plngNum& = VAL(GfTrim$(REC.NUM$))	'数量
			'正常を返す
			MfSearchData% = GcTrue%
		ENDIF
MfSearchData.Return	'関数戻り
		If FILENO% > 0 Then
			Close FILENO%
		Endif
		On Error Goto 0
		Exit Function
'-----
'エラー処理
'-----
MfSearchData.ErrProc
		Resume MfSearchData.Return
	End Function
SEARCH関数 に指定する検索データは、 関数[MfPutData%]でコードの後ろにスペースを付加したので、その処理を行っています。 
この時、ワーク変数の W$ を宣言していますが、 
引き数の変数 pstrCD$ は、コール元で代入された文字列長分しかサイズが無いので、 
それ以上の長さの文字列を代入できないためです。 

レコード番号の指定が0の場合は、ファイルの先頭からの検索を行います。
■検索関数の利用
上記の検索関数の動作をテストするソースを以下に記します。
	SCREEN 1				'漢字モード
	LOCATE , , 2			'カーソルをブロック表示
	'最初は書き込み処理の連続
	PRIVATE W%
	W% = MfPutData%("CD0001", 100, 0)
	W% = MfPutData%("CD0002", 102, 0)
	W% = MfPutData%("CD0101", 201, 0)
	W% = MfPutData%("CD0201", 202, 0)
	W% = MfPutData%("CD1001", 500, 0)
	W% = MfPutData%("CD0003", 1030, 0)
	W% = MfPutData%("CD0002", 1022, 0)
	
	PRIVATE CD$, RNO&, NUM&
	CD$ = "CD0101": RNO& = 0
	W% = MfSearchData%(CD$, NUM&, RNO&)
	IF W% = GcTrue% THEN
		PRINT CD$ + "(" + STR$(RNO&) +  "):" + STR$(NUM&)
	ELSE
		PRINT CD$ + ":Not Found"
	ENDIF
	CD$ = "CD0003": RNO& = 0
	W% = MfSearchData%(CD$, NUM&, RNO&)
	IF W% = GcTrue% THEN
		PRINT CD$ + "(" + STR$(RNO&) +  "):" + STR$(NUM&)
	ELSE
		PRINT CD$ + ":Not Found"
	ENDIF
	CD$ = "CD0002" 	'RNO&は上の続きで
	W% = MfSearchData%(CD$, NUM&, RNO&)
	IF W% = GcTrue% THEN
		PRINT CD$ + "(" + STR$(RNO&) +  "):" + STR$(NUM&)
	ELSE
		PRINT CD$ + ":Not Found"
	ENDIF
	WAIT 0, &h01 'キー入力待ち
	END
2番目の検索から分かるように、コードは順番に並んでいなくても検索できています。 
つまり SEARCH関数 は、指定されたレコード位置からベタに検索し、
指定された検索データが等しいものが見つかった時点で、検索を止めるようです。 

SEARCH関数 は特にバイナリサーチで行うわけではないので、
データ件数が多くて最後の方に目的のものが在る場合、時間が掛かるはずです。 

ハンディターミナルで入力されたデータを検索する場合は、 そこまで入力件数が多いわけではないと思うので、
この SEARCH関数 でも 問題無いのでしょう。 
このソースの実行結果は以下の図の様になります。 

※尚、バイナリサーチに関しては、拡張関数の中にバイナリサーチ処理関数(BSEARCH.FN3)があり、 これを使えば可能です。 この関数の使い方については別の記事で紹介します。



=====
2016/04/02:の時の情報











PR

コメント

コメントを書く