お久しぶりです。宜しくお願いします。
早速本題ですが例えば
InStr(1, "酸素_AB","_")は2が返ります
最初バグかと思ったのですがバイト単位で見ると"酸"は
&H8E ・
&H5F _
で確かに2で合ってます。
当然5が返ってきて欲しいので
1バイト前の文字を調べ&H81~9F、E0~EFの間かチェックして
2バイト文字なら又続きから検索してチェックしてを繰り返して・・・
とやればいいかなと思ったのですが、非常に効率が悪いと思いました。
_以外でも記号とかの特殊文字で検索した時に起きる現象だと思いますが
皆さんは上記のような方法で文字列検索しているのでしょうか。
他にもっと良い方法をお知りでしたら是非教えて下さい。
AB 4.13
OS XP Home SP2
関係ない話ですが、今までInStrを何度となく使ってきたのに、
今の今まで上記のような事が起こらなかったのは凄いなぁと思っちゃいました。
InStrで"_"(アンダーバー・アンダースコア)を検索したい
先人の方が関数を作っていました。
せっかくなので利用させて頂いたら如何ですか?
使用方法はInStrと同じです。
せっかくなので利用させて頂いたら如何ですか?
使用方法はInStrと同じです。
[ここをクリックすると内容が表示されます]
コード: 全て選択
Re: [AB3] InStrの誤認識への対策 ( No.2 )
日時: 2004/03/02 18:08
名前: hira <hira@pc.707.to>
参照: http://hiras.web.poporo.net/
「執念の」InStr4関数です。以前よりかなり高速ですが、Unicodeへの変換があるためInStr3には勝てない模様…(--;
Declare Function MultiByteToWideChar Lib "kernel32" (CodePage As Long,dwFlags As Long,lpMultiByteStr As String,cchMultiByte As Long,lpWideCharStr As String,cchWideChar As Long)As Long
Function InStr4(StartPos As Long, buf1 As String, buf2 As String) As Long
Dim len1 As Long,len2 As Long
Dim uni1 As WordPtr,uni2 As WordPtr
Dim Ret As Long
Dim i As Long,i2 As Long,i3 As Long
Dim StartPos2 As Long
'データのチェック
If StartPos<0 Or StartPos>Len(buf1) Then Exit Function
If Len(buf2)=0 Then Exit Function
len1=MultiByteToWideChar(0,0,buf1,Len(buf1),0,0)
uni1=HeapAlloc(GetProcessHeap(),0,len1*2)
MultiByteToWideChar(0,0,buf1,Len(buf1),uni1,len1*2)
len2=MultiByteToWideChar(0,0,buf2,Len(buf2),0,0)
uni2=HeapAlloc(GetProcessHeap(),0,len2*2)
MultiByteToWideChar(0,0,buf2,Len(buf2),uni2,len2*2)
i=MultiByteToWideChar(0,0,buf1,StartPos-1,0,0)
Ret=0
While i<=len1-len2
i2=i:i3=0
Do
If i3=len2 Then
Ret=i*2+1
Exit Do
End If
If uni1[i2]<>uni2[i3] Then Exit Do
i2=i2+1
i3=i3+1
Loop
If Ret Then Exit While
i=i+1
Wend
'Shift-JISに換算した長さを返す
If Ret Then
InStr4=(Ret-1)\2+1
For i=0 To (Ret-1)\2
If GetByte(uni1+i*2+1) Then InStr4=InStr4+1
Next i
End If
HeapFree(GetProcessHeap(),0,uni1)
HeapFree(GetProcessHeap(),0,uni2)
End Function
>1バイト前の文字を調べ&H81~9F、E0~EFの間かチェックして
どうでもいいことですが、4つも比較を書くのは面倒なのでと書くところでと書いてしまいたくなります。
もっといい方法としては、例えば半角仮名文字や全角文字はあまり使われないと言う前提で、
4バイト単位で文字を読み込み、1バイト単位で論理和を取り、
「8ビット目が立っていたら全角文字を含む可能性がある」という判定を行うとかあるいは、AB以外の実行速度の速い言語(C言語とか)でDLLを作り、呼び出すとか。
どうでもいいことですが、4つも比較を書くのは面倒なので
コード: 全て選択
a=buffer
If (&H81<=a and a<=&H9F) or (&HE0<=a and a<=&HEF) then
continue
End If
コード: 全て選択
a=buffer xor &H20
If &HA1<=a and a<=&HCF then
continue
End If
もっといい方法としては、例えば半角仮名文字や全角文字はあまり使われないと言う前提で、
4バイト単位で文字を読み込み、1バイト単位で論理和を取り、
「8ビット目が立っていたら全角文字を含む可能性がある」という判定を行うとか
コード: 全て選択
a=GetDWord(buffer+i)
b=a or (a<<16)
b=b or (b<<8)
If b and &H80 then
...'厳密に調べる
Else
...'1バイト文字という前提の十分条件が整うので、素早く検索できる。
End If
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。
に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
ここ以外の場所では「暇人13世」というHNを主として使用。
に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
Re:InStrで"_"(アンダーバー・アンダースコア)を検索したい
返信ありがとうございます
>ゲストさん
コードの切れ端の存在を忘れていました(汗)。
そこを検索してから投稿すればよかったですね。
失礼しました。
>konisiさん
色んなやり方があるもんですね。
取りあえず今はhiraさんのコードを使わせていただくことにしましたが
自分でも色々研究してみたいと思います。
>ゲストさん
コードの切れ端の存在を忘れていました(汗)。
そこを検索してから投稿すればよかったですね。
失礼しました。
>konisiさん
色んなやり方があるもんですね。
取りあえず今はhiraさんのコードを使わせていただくことにしましたが
自分でも色々研究してみたいと思います。