文字列の置換 (strmid) 『HSP3』
文字列の置換をみていきます。HSP3には置換命令や関数はないようです。今回は「strmid」関数を利用して置換処理をおこないます。素人が作ったモジュールなので使う場合は十分テストしてください。
| 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. |
#module ;******************************************************** ;■検索文字列に一致したすべての文字列を置換する ; ; 引数: (1)p_search 検索対象の文字列 ; (2)p_replace 置き換え文字列 ; (3)p_subject 元の文字列 ; ; 戻り値:str_subject 置換後の文字列 ;******************************************************** #defcfunc str_replace str p_search , str p_replace ,str p_subject str_subject = p_subject pre_position = 0 repeat ;置換対象(p_search)の文字位置を求める。 position = instr(str_subject,pre_position,p_search) if ( position == -1 ) : break position += pre_position ;置換対象(p_search)の前までの文字列を求める。 pre_subject = strmid(str_subject,0,position) ;置換対象(p_search)より後の文字列を求める rest_subject = strmid(str_subject,position+strlen(p_search),strlen(str_subject)) ;置換後の文字 = 前 + 置換文字 + 後 str_subject = pre_subject + p_replace + rest_subject ;現ポジションを維持 pre_position = position await loop return str_subject #global mes str_replace("c","A","abcdecf") stop |
置換処理ですがやっていることは単純です。最初から置換する文字を検索して置き換える処理を繰り返しているだけです。

①
16行目です。文字列「abcdecf」から検索文字「c」の位置を「instr関数」により求めています。検索開始位置は、前回の検索結果の位置以後から始めています。前回までの位置は既に置換されているので最初から調べる必要はありません。1回目のループは最初からの検索になるので、前回の位置を示す変数pre_positionは「0」になります。1回目のループでは「C」の位置は2バイト終わったところにあるので変数positionには「2」が格納されます。
②
20行目をみてみます。「strmid関数」で文字を抽出しています。開始位置が「0」になっているので最初からです。抽出文字サイズは「position」になっているので検索文字の位置までです。つまり、検索文字がある位置までの文字列を取得して変数pre_subjectに格納しています。検索文字は含まれないことに注意してください。1ループ目は「ab」が格納されます。
③
22行目をみてみます。同じく「strmid関数」で文字を抽出しています。開始位置が「position+strlen(p_search)」になっています。positionは検索文字がある位置です。開始位置が「position」だと検索文字「c」も一緒に抽出されてしまいます。ここでは検索文字は含めないようにしたいので、検索文字サイズ分だけ足した位置を開始位置としています。抽出サイズは文字列全サイズに今回はしています。実際に求めるサイズより大きいのですが、超えて指定してもエラーにならずに必要分だけ抽出してくれます。
※
厳密に指定するならば、検索文字以後の文字列の長さなので、
「strlen(str_subject) - position - strlen(p_search)」 です。
④
24行目は単に文字列を結合しているだけです。検索文字より前の文字列「pre_subject」と、検索文字より後の文字列「rest_subject」の間に、置換後の文字列を挟むことにより、検索文字が置換文字に置き換わります。よって、1ループ目では「abAdecf」になりました。この置換後の文字列に対し、また16行目から同じ動作を行います。
⑤〜⑦
2ループ目は文字列「「abAdecf」に対して上記と同じ動作を行ないます。開始位置ですが、1ループ目は最初からだったので変数pre_position は「0」でしたが、2ループ目は前回の検索結果位置から次の検索文字を探します。最初から探してもいいのですが、前回までの位置は既に置換されているので該当がないことがわかっています。文字列が長いと多少の時間節約になります。26行目で、前回の検索結果位置を変数pre_position に代入しています。
18行目:「position += pre_position」
ここでは、変数positionに、前回の検索結果位置「pre_position」を足しています。変数postionは直前の16行目で求めています。2ループ目は開始位置が最初からではなく、「前回の検索結果位置から次の検索文字の位置までの位置(サイズ)」を求めています。最初から前回の検索結果位置「pre_position」を足すことにより、変数positionを最初からの位置にしています。このように最初に統一することにより、何ループ目であろうと19行目から26行目の処理が同じで済みます。
17行目:if ( position == -1 ) : break
「instr関数」は検索対象となる文字がみつからなければ、「-1」を返してきます。置換する文字がなくなったのでループから抜けます。
以上が「strmid関数」を利用した置換処理です。簡単な処理なのですが、最初から順に繰り返しながらチェックしていることや、文字列を分割して一時変数に確保してるなど、長い文字列を対象に置換する場合は時間がかかったりメモリを消費するなどの欠点があります。文字列を簡単に抽出する関数として「getstr関数」があるのですが、この関数は改行があれば終了判定されるなどの制約を受けるので使いませんでした。


