データファイルの読み込みで、最初に既に入力されているコードを検索し、 そのコードに対応したレコード番号で行う場合があります。 データのメンテナンス処理ではこの方法が普通かと思います。
今回は標準関数の SEARCH関数 を使ってみます。
※尚、バイナリサーチに関しては、拡張関数の中にバイナリサーチ処理関数(BSEARCH.FN3)があり、 これを使えば可能です。 この関数の使い方については別の記事で紹介します。
=====
2016/04/02:の時の情報
今回は標準関数の 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
コメント