文字列編集ルーチン
注: この記事に記載のコードはここからダウンロードできます。
最近、文字ストリングを編集する方法を知らないかと尋ねられました。例えば、「AX12345Q」といった製品コードを表す文字ストリングを編集して「AX-123-45 Q」を生成するとします。まず、編集ワードを入手しようとしたのですが、残念ながらそれは、どういうわけか数値にしか機能しません。挿入文字に必要な柔軟性を実現し、不一致のパラメーターに対して多少の「防御」もするサブプロシージャーの構築に取り掛かりました。
コードを記述する前に、編集ルーチンのプロトタイプを見てみましょう。一部の読者はまだ完全にフリー・フォームを使用していない可能性があるので、この説明では「旧」型の D 仕様定義を使用することにします。しかしダウンロード可能なコード・パッケージでは、固定フォームおよびフリー・フォーム両方のバージョンを用意しました。
プロトタイプは次のようになります。
サブプロシージャーは、最大 256 文字の可変長ストリングを返します。これは十分すぎるほど大きいはずです。
第 1 パラメーター (InputString) が編集するフィールドです。ルーチンが、入力としてどのサイズやタイプの文字フィールドでも受け入れることができるよう、Const キーワードを追加しました。同じことが第 2 パラメーターにも当てはまります。このパラメーターは使用するマスクです。ここで Const には、マスク・パラメーターとしてリテラルも指定できるという利点が加味されています。最後のパラメーターでは、文字マーカー・フィールドを変更できます。そのような訳でオプション *NoPass になります。デフォルト (私の場合はアンパサンド「&」) 以外のマーカーを使用するかどうかのみ指定する必要があります。 マスクは次のように動作します。「&」それぞれによって、入力フィールドの次の文字が結果にコピーされます。マスク・ストリングの他の文字は、単に結果にコピーされます。結果を生成するため、上記 (「AX-123-45 Q」) にはマスク '&&-&&&-&& &' が必要であることを示しました。
& を挿入文字として使用する必要がある場合、マーカーとして代替文字を選択し、第 3 パラメーターでそれを指定する必要があります。
コード・パッケージに含まれるサンプル・テスト・プログラムから、いくつかサンプル呼び出しを挙げました。この最初の呼び出しは '9735551212' といったストリングを '(973) 555-1212' に変換します。次の呼び出しは、第 3 パラメーターを使用してマーカー文字にスペースを指定し、その結果 '111223333' というストリングは 111-22-333 になります。
(A) では、フィールド outString を定義しました。ここには編集済みの戻り値が入ります。定義上の Inz により、開始時にストリングが空になるようにします。またこれを可変長ストリングとして定義すると、後で説明するように、結果フィールドに文字を追加するのに、単純な += 命令を使用するだけで済むため、さらに簡単に結果を構築できるようになります。変数 ix と mx はそれぞれ、入力ストリング (inText) とマスク (editMask) の現在位置を追跡します。
(B) はマスクのデフォルト・テキスト・マーカー文字を定義します。私はこれを初期値「&」に設定しました。自分が使いやすいように、この値をスペースに変更したい場合があります。その方が確実にマスクを読み取りやすくなります。しかし、スペースを頻繁に挿入する私にとっては、好ましいデフォルトではありません。
次に来るのは (C)、オプションの第 3 パラメーターが渡されたかどうか判断するテストです。渡された場合、marker にコピーされてデフォルトと置き換えられます。
(D) はループを開始して編集を行います。例外条件のテストと処理が簡単になるため、マスクの長さを制御条件として使用しました。(例えば、マスクより入力での文字数が多い。)
(E) では、マスクの現在位置がテキスト・マーカーを表しているかどうかテストします。もし表している場合、文字を結果にコピーする準備段階として入力位置が増分されます。しかしまず (F) で、まだ文字が残っているか確認します。この確認をしないと、以降の %Subst が失敗します。利用できる入力文字がある場合、それは出力結果に追加されます。ない場合は、代わりに空白が追加されます。
(G) の見方は逆になります。つまり、マスク文字を結果ストリングに追加します。
最後に (H) では、元の入力のすべての文字が処理されていたことを確認するためのチェックを追加しました。これは省略できたかもしれませんが、残りの文字を結果に追加する方が、マスクのエラーを検出しやすくなるのではと感じました。その他の入力を無視するか、実際にエラー信号を送信したい場合は、単にこのコードを修正してください。
あなたは(例えば)、 RPG の C 関数 sprintf() の使用法を示すのではなく、サブプロシージャーを作成したのはなぜかと思っているでしょう。これでうまくいったかもしれませんが、私の意見では、マスクの構造は、ほとんど明らかにされておらず、その結果、以降コードの保守を担当する他のプログラマーにはなかなか理解できません。
このユーティリティー・ルーチンが役に立つと願っています。他の読者の関心を引くと思われるような類似のサブプロシージャーがあったら、是非教えてください。