tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板
VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re: MidB関数
投稿日: 2009/05/16(Sat) 17:54
投稿者魔界の仮面弁士
> あるテキストファイルを line input で1行ずつ読み込んで、midB関数で一部分を切取りたいのですが、MidB関数がうまく動いてくれません。
16bit 版である VB2、VB3、VB4(16bit) であれば、そのコードでうまくいきますが、
32bit 版である VB4(32bit)、VB5、VB6 では違う結果となります。

これは、32bit 版の Visual Basic で使われている文字コードが Shift_JIS ではなく、
すべての文字を 2 バイトで表現する「Unicode」(UTF-16)で管理されているためです。

'---------
Dim A1 As String
A1 = "   ああ-1  いい"

MsgBox Len(A1)      'VB2 では「11」、VB6 でも「11」
MsgBox LenB(A1)     'VB2 では「15」、VB6 では「22」

MsgBox MidB(A1, 4, 6)    'VB2では「ああ-1」、VB6では「???」(文字化けして表現不可)
MsgBox Mid(A1, 4, 6)     'VB2 も VB6 も「ああ-1  」
'---------


> MidB関数は全角は2バイト半角は1バイトで計算するはずなのになぜなのでしょうか?
だからこそです。32bit 版 VB では、すべての文字が 2 バイトで表されています。

詳細情報として、Visual Basic 6.0 リリースノート (Readmevb.htm) の
 「32 ビット環境での文字列操作関数の動作について」
 「32 ビットでの文字列操作の 注意事項」
 「ANSI 文字列のバイト単位の操作をする関数の例」
を参照しておいてください。


> "   ああ-1  いい"  という文字列
これは String 型ですよね。メモリ上に保持されているバイナリは、16進数表記で
 [VB2] 20 20 20 82 A0 82 A0 2D 31 20 20 82 A2 92 A2
 [VB6] 20 00 20 00 20 00 42 30 42 30 2D 00 31 00 20 00 20 00 44 30 44 30
と並んでいます。下段が 32bit 版である VB6 のメモリ配置です。


MidB(A1, 4, 6) という事は、(先頭を1とした)4バイト目から6バイト分なので、
 [VB2] -- -- -- 82 A0 82 A0 2D 31 -- -- -- -- -- --
 [VB6] -- -- -- 00 20 00 42 30 42 -- -- -- -- -- -- -- -- -- -- -- -- --
の部分が取り出される事になります。

これを String として処理するために、文字列としてデコードすると、
16 bit 版の VB と 32 bit 版の VB とでは、それぞれ
 'VB2
 S1 = Chr(&H82) & Chr(&HA0) & Chr(&H82) & Chr(&HA0) & Chr(&H2D) & Chr(&H31)
 MsgBox S1    '「ああ-1」となる。

 'VB6
 S2 = ChrB(&H00) & ChrB(&H20) & ChrB(&H00) & ChrB(&H42) & ChrB(&H32) & ChrB(&H42)
 MsgBox S2    '文字化けして「???」となる。
 S3 = ChrW(&H2000) & ChrW(&H4200) & ChrW(&H4232)
 MsgBox S3    '文字化けして「???」となる。
と処理される事になります(ちなみに、VB6 の方の S2 と S3 は同一です)。



もし、VB2 の場合と同様に、「ああ-1」と取り出したいのであれば、StrConv 関数を併用して、
Shift_JIS バイナリと Unicode バイナリの相互変換を行う必要があります。

'--------------------
Dim A1 As String
A1 = "   ああ-1  いい"

Dim SJIS As String, Cut As String, Unicode As String
SJIS    = StrConv(A1, vbFromUnicode)
Cut     = MidB(SJIS, 4, 6)
Unicode = StrConv(Cut, vbUnicode)

MsgBox Unicode    '「ああ-1」となる。
'--------------------

上記のようにすれば、望む結果になるかと思います。

ちなみにこの場合、それぞれの文字列のメモリ構成は、
 [A1]    20 00 20 00 20 00 42 30 42 30 2D 00 31 00 20 00 20 00 44 30 44 30
 [SJIS]   20 20 20 82 A0 82 A0 2D 31 20 20 82 A2 92 A2
 [Cut]   82 A0 82 A0 2D 31
 [Unicode] 42 30 42 30 2D 00 31 00
となっています。

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。