忍者ブログ

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

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

BHT-BASIC4.0:拡張関数のサーチ処理関数(SEARCH.FN3)の使い方
前回はバイナリサーチ(SEARCH.FN3)の紹介を行いましたが、 この検索では1個のコードに対して処理する機能しかありません。
コードは昇順にしないとバイナリサーチは利用できないので、 1レコードの中に複数コードが存在しソートできない場合などのデータファイルの場合には利用できません。

複数コードの条件付けを行い検索できるのが、拡張関数の サーチ処理関数(SEARCH.FN3) です。 今回はこの拡張関数について説明します。

■サーチ処理関数(SEARCH.FN3)について

この関数は以下の4個の機能があります。

機能番号処理内容
.fcAndSrch 1 「AND」サーチ(レコード番号検索)
.fcOrSrch 2 「OR」サーチ(レコード番号検索)
.fcAndSrchN 11 「AND」サーチ件数(件数のみ検索)
.fcOrSrchN 12 「OR」サーチ件数(件数のみ検索)

「レコード番号検索」と「件数のみ検索」で関数に渡す引数の書式が異なります。
[書式1]
 CALL "SEARCH.FN3" .fcAndSrch FILENO%, RSTART, REND, RECORD, STRING1$, STRING2$...
  RSTART, REND, RECORD は、整数型(%),長整数型(&),実数型(指定無し)が使用可能
[書式2]
 CALL "SEARCH.FN3" .fcAndSrch FILENO%, RSTART, REND, RECORD, STRING$(), STRINGN%
  RSTART, REND, RECORD は、整数型(%),長整数型(&),実数型(指定無し)が使用可能

<引き数>
  .fcAndSrch:機能番号指定
  FILENO%   :ファイル番号
  RSTART    :検索開始レコード番号
  REND     :検索終了レコード番号
  FIELDNO%  :フィールド番号
  STRINGn$  :検索条件
  STRING$() :検索条件(配列指定時)
  STRINGN%  :検索条件数(配列指定時)

  STRINGn$やSTRING$()は「検索方法」+「フィールド番号」+「検索文字列」で指定します。
  「検索方法」、「フィールド番号」は数値を「CHR$関数」で文字列化

<戻り値>
  RECORDNO :検索結果(レコード番号)
  ・RECORDNO には、検索条件に一致するデータが見つかったレコード番号が返されます。
   見つからなかった場合、0 が返されます。
  ・RECORDNO は、整数型の最大値(32767)を超える場合あるので、
   変数に代入する場合、長整数型変数か実数型変数を推奨します

今回の検索関数を使用する例のために以下の様なデータファイルを想定します。 これは今まで使ってきたTEST.DATに削除フラグを追加しています。 ファイル名はTEST2.DATとします。
項目名フィールド長内容
品番 16 商品コードの文字列
数量 12 商品の数量を文字列で格納
削除フラグ 1 "1":削除済み 、 "0"削除されていない

サーチ処理関数(SEARCH.FN3) を使う上で OR条件 よりも AND条件 を 使う方が多いと思うので、 AND条件 を例にとります。
品番と削除フラグの AND条件 でデータファイル( TEST2.DAT )を検索する 関数が以下の様になります。関数コールの書式は検索条件に文字列配列を使った「書式2」で行っています。
'---------------------------------------
'データ検索その2
'---------------------------------------
'Function MfSearchData2%(Byval pstrCD$, Byval pintDel%, Byref plngNum&, Byref plngRecNo&)
'引 数:
'	pstrCD$		:コード
'	pintDel%	:削除フラグ
'	pdblVal$	:数量
'	plngRecNo&	:レコードNO
'戻り値:
'	MfSearchData2%	:読込OK:GcTrue%, NG:GcFalse%
'---------------------------------------
	Function MfSearchData2%(Byval pstrCD$, Byval pintDel%, Byref plngNum&, Byref plngRecNo&)
		'エラー処理宣言
		On Error Goto MfSearchData2.ErrProc
		'フィールドサイズ(既に宣言済み)
'		Const COL.CD% = 16
'		Const COL.NUM% = 12
'		Const COL.DEL% = 1
		'戻り値の初期化
		MfSearchData2% = GcFalse%
		'FIELD関連変数
		PRIVATE FILENO%, REC.CD$, REC.NUM$, REC.DEL$
		'TEST.DAT2ファイルを、ファイル番号#1としてオープンします
		FILENO% = 1
		OPEN GcTEST2.DAT$ AS FILENO% RECORD 2147483647
		FIELD #FILENO%, COL.CD% AS REC.CD$, COL.NUM% AS REC.NUM$, COL.DEL% AS REC.DEL$
		'検索データの整形
		PRIVATE WK.CD$, WK.DEL$
		WK.CD$ = LEFT$(pstrCD$ + GfSpc$(COL.CD%), COL.CD%)
		If pintDel% = GcTrue% Then
			WK.DEL$ = "1"
		Else
			WK.DEL$ = "0"
		EndIf
		'レコードNO検索
		PRIVATE RSTART&, REND&, RECORDNO&, STRING$(2)[64], STRINGN%
		RSTART& = 1
		REND& = LOF(FILENO%)	'ファイルの最後まで検索
		STRINGN% = 2			'検索条件配列の個数
		STRING$(0) = CHR$(0) + CHR$(1) + WK.CD$	 '検索条件(=条件),フィールド番号(1:場所CD)
		STRING$(1) = CHR$(0) + CHR$(3) + WK.DEL$ '検索条件(=条件),フィールド番号(3:削除フラグ)

		CALL "SEARCH.FN3" .fcAndSrch FILENO%, RSTART&, REND&, RECORDNO&, STRING$(), STRINGN%
		If RECORDNO& > 0 Then
			'レコードNOが返された場合,レコードの取得
			GET FILENO%, RECORDNO&
			'数値文字列を返す
			plngNum& = VAL(REC.NUM$)
			plngRecNo& = RECORDNO&
			'正常を返す
			MfSearchData2% = GcTrue%
		Endif
MfSearchData2.Return	'関数戻り
		If FILENO% > 0 Then
			Close FILENO%
		Endif
		On Error Goto 0
		Exit Function
'-----
'エラー処理
'-----
MfSearchData2.ErrProc
		MfSearchData2% = GcFalse%
		Resume MfSearchData2.Return
	End Function

■検索関数の利用
上記の検索関数の動作をテストするソースを以下に記します。
	SCREEN 1				'漢字モード
	LOCATE , , 2			'カーソルをブロック表示
	'最初は書き込み処理の連続
	PRIVATE W%
	W% = MfPutData2%("CD0001",  100, GcTrue%,  0)
	W% = MfPutData2%("CD0002",  102, GcFalse%, 0)
	W% = MfPutData2%("CD0003", 1030, GcTrue%,  0)
	W% = MfPutData2%("CD0101",  201, GcTrue%,  0)
	W% = MfPutData2%("CD0201",  202, GcFalse%, 0)
	W% = MfPutData2%("CD1001",  500, GcTrue%,  0)

	PRIVATE CD$, RNO&, NUM&
	CD$ = "CD0001"	'削除ONで検索⇒検索OK
	W% = MfSearchData2%(CD$, GcTrue%, NUM&, RNO&)
	IF W% = GcTrue% THEN
		PRINT CD$ + "(" + STR$(RNO&) +  "):" + STR$(NUM&)
	ELSE
		PRINT CD$ + ":Not Found"
	ENDIF
	CD$ = "CD0002"	'削除ONで検索⇒検索NG
	W% = MfSearchData2%(CD$, GcTrue%, NUM&, RNO&)
	IF W% = GcTrue% THEN
		PRINT CD$ + "(" + STR$(RNO&) +  "):" + STR$(NUM&)
	ELSE
		PRINT CD$ + ":Not Found"
	ENDIF
	CD$ = "CD0002" 	'削除OFFで検索⇒検索OK
	W% = MfSearchData2%(CD$, GcFalse%, NUM&, RNO&)
	IF W% = GcTrue% THEN
		PRINT CD$ + "(" + STR$(RNO&) +  "):" + STR$(NUM&)
	ELSE
		PRINT CD$ + ":Not Found"
	ENDIF
	CD$ = "CD0201" 	'削除OFFで検索⇒検索OK
	W% = MfSearchData2%(CD$, GcFalse%, NUM&, RNO&)
	IF W% = GcTrue% THEN
		PRINT CD$ + "(" + STR$(RNO&) +  "):" + STR$(NUM&)
	ELSE
		PRINT CD$ + ":Not Found"
	ENDIF
	WAIT 0, &h01 'キー入力待ち
	END

最初のテストデータの書き込みで使っている関数 MfPutData2% は、下の方にソースがありますのでそちらを参照下さい。 また、これによって作成された TEST2.DAT は以下の図の様になります。(デバッガ上でのシミュレーションでのファイル参照ですが)

品番コードと削除フラグの指定を合わせて検索しています。
このソースの実行結果は以下の図の様になります。

関数 MfPutData2% のソースです。
Const GcTEST2.DAT$ = "TEST2.DAT"
'---------------------------------------
'データ書込(TEST2.DAT)
'---------------------------------------
'Function MfPutData2%(Byval pstrCD$, Byval plngNum&, Byval pintDel%, Byval plngRecNo&)
'引 数:
'	pstrCD$		:コード
'	plngNum&	:数量
'	pintDel%	:削除フラグ
'	plngRecNo&	:レコードNO(0:レコード追加)
'戻り値:
'	MfPutData2%	:書込OK:GcTrue%, NG:GcFalse%
'---------------------------------------
	Function MfPutData2%(Byval pstrCD$, Byval plngNum&, Byval pintDel%, Byval plngRecNo&)
		'エラー処理宣言
		On Error Goto MfPutData2.ErrProc
		'フィールドサイズ
		Const COL.CD% = 16
		Const COL.NUM% = 12
		Const COL.DEL% = 1
		'戻り値の初期化
		MfPutData2% = GcFalse%

		PRIVATE FILENO%, REC.CD$, REC.NUM$, REC.DEL$
		FILENO% = 0
		'TEST.DAT2ファイルを、ファイル番号#1としてオープンします
		FILENO% = 1
		OPEN GcTEST2.DAT$ AS FILENO% RECORD 2147483647
		FIELD #FILENO%, COL.CD% AS REC.CD$, COL.NUM% AS REC.NUM$, COL.DEL% AS REC.DEL$
		'フィールドへデータ設定
		REC.CD$  = LEFT$(pstrCD$ + GfSpc$(COL.CD%), COL.CD%)	'既定の桁数分スペースを付加
		REC.NUM$ = RIGHT$(GfSpc$(COL.NUM%) + STR$(plngNum&), COL.NUM%)	'既定の桁数分スペースを付加
		REC.DEL$ = "0"
		If pintDel% = GcTrue% Then
			REC.DEL$ = "1"
		Endif
		
		If plngRecNo& = 0 Then
			'レコードNOが0の場合,レコードの最後尾に追加
			PUT FILENO%
		Else
			'レコードNOが指定された場合,レコードの上書
			PUT FILENO%, plngRecNo&
		Endif
		'正常を返す
		MfPutData2% = GcTrue%
MfPutData2.Return	'関数戻り
		If FILENO% > 0 Then
			Close FILENO%
		Endif
		On Error Goto 0
		Exit Function
'-----
'エラー処理
'-----
MfPutData2.ErrProc
		Resume MfPutData2.Return
	End Function




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











PR

コメント

コメントを書く