- PR -

null区切りされた文字配列について

投稿者投稿内容
Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2005-08-30 20:57
諸農です。

VS2005でVBプロジェクトを作って確認してみました。

Dim str As String = Encoding.GetEncoding("SHIFT_JIS").GetString(bytArray)

の部分にブレークポイントを置いて、デバッガで停止後、F10で次のステップに進み、ブレークポイントを置いた行のstr上にマウスカーソルを移動させます。
すると、ここでビジュアライザが起動しますが、ビジュアライザの表示には「""」と表示されます。。
いや、確かにこれだと「nullターミネートされているんだ」と思うのも無理はないですね。

ところがこれが、VS2005でのVC#プロジェクト または VC#2005 Express Editionだと
ビジュアライザに「\0日本語\0日本語日本語」と表示されるんですよね。。。

_________________
諸農和岳
Powered by Turbo Delphi & Microsoft Visual Studio 2005

十兵衛@わんくま同盟
http://blogs.wankuma.com/jubei/
aacute
常連さん
会議室デビュー日: 2005/08/25
投稿数: 30
投稿日時: 2005-08-30 23:45
引用:

taaさんの書き込み (2005-08-30 20:21) より:
Jubeiさんのプログラムコード通り、
「Dim strs() As String = str.Split(Char.MinValue)」であれば、
正常にNull文字でSplitができました。
ありがとうございます。

只、なぜ私のプログラムでは正常に動作していなかったかと
いうと、セパレート値を"Nothing" or "vbNull" or &H0等で
指定していたからです。
その為、String型もStringBuilderと同様にNULLターミネイト
していると思っていました。
(ただし、セパレート値を"Char.MinValue"に指定すると
正常に動作する明確な理由はまだわかっていません。)


Char型と数値型とNothingは全く別のものなんだと思います。

str.Split(Convert.ToChar(&H0))
こんな感じでChar型に変換してやると同じ様に動きます。

というか私の環境(vbcコマンドでのコンパイル)では
str.Split(&H0)
はエラーになりますが。
taa
常連さん
会議室デビュー日: 2005/08/29
投稿数: 44
投稿日時: 2005-08-31 15:24
解決しました。ありがとうございます。
最後に、今回知り得た情報を以下に記載致します。

アンマネージコード(C++)のDLLを呼び出し、返却された
文字配列データ(null区切り)を取得する場合、私が知る限り
2つあります。

1つめは、マネージコード(VB.NET)をBYTE型の配列で受け取り、
SJISの文字コードをUnicodeへEncodeし、Null文字でSplitする方法。

2つめは、マーシャリングして、String型で受け取り、Null文字で
Splitする方法。

性能は測っていませんが、どちらでもいいと思います。
以下にアンマネージコードのインターフェースとマネージコード
のプログラムコードを2パターン記載します。

ちなみにマナーをよく知らず、クロスサイトポスト(他のサイトの掲示板への書き込み)していますのでクロスサイトポスト先の場所を以下に示します。
皆さんに不愉快な思いをさせて申し訳ありませんでした。

●クロスサイトポストされている場所
http://dobon.net/cgi-bin/vbbbs/cbbs.cgi?mode=al2&namber=12417&rev=&no=0

また、最後にこんなにご迷惑をお掛けしたにもかかわらず、本当にたくさんの
書き込みをありがとうございました。
この書き込みをもってこのトピックを「解決済み」とさせて頂きます。
本当にどうもありがとうございました。

------------------------------------------------------------------------

<アンマネージコード(DLLインターフェース)>
TEST_RESULT TEST_APICALL TEST_StrGet(
 //IN :ディレクトリ名 
 char[10] DirName,

 //OUT :0ターミネートしたファイル名リスト(ASCIZ文字列:SJIS)
 char[100] FileListBuf
);

<BYTE配列で受け取る場合のマネージコード>
Imports System
Public Declare Function TEST_StrGet Lib "test.dll" ( _
 ByVal DirName As String, _
 ByVal FileListBuf() As Byte, _  '★Byte配列で受け取る。
) As Integer

Sub Main()
   Dim FileName As String

   '★SJISの文字コードのByte配列(FileListBuf)の内容をUnicodeの文字列へEncodeする。
Dim strFileList As String = Encoding.GetEncoding("SHIFT_JIS").GetString(FileListBuf)
   '★UnicodeへEncode文字列データをNull文字毎にSplitする。
   ※separateを"Char.MinValue"に指定しないと分割されない。&H0、Nothing、VbNullでは分割されませんでした。
   ただし、少し工夫すれば可能らしいです。
  Dim strFileListArray() As String = strFileList.Split(Char.MinValue)

For Each FileName As String In strFileListArray
Debug.Print(FileName & vbCrLf)
Next FileName
End Sub

<マーシャリングしてString型で受け取る場合のマネージコード>
Imports System
Public Declare Ansi Function TEST_StrGet Lib "test.dll" ( _
 ByVal DirName As String, _
 ByVal FileListBuf As String, _  '★String型で受け取る。
 ★「ByVal ・・・ As String」と宣言した場合、内部では「ByRef」扱いとなる。
そして同時にMarshalAs属性がUnmanagedType.VBByRefStrで宣言されている状態になる。) As Integer

Sub Main()
 Dim i rc As Integer
 Dim DirName As String = "C:\"
 Dim FileListBuf As New String(" "c,1000)  '★Stringオブジェクトを作成していますが明確な理由はわかりません

 rc = TEST_StrGet(DirName, FileListBuf)

'終端の二連nullを以降を取り除く
 '★Stringオブジェクトを作成していますが明確な理由はわかりません
Dim Term As New String(ChrW(0), 2)
FileListBuf = Split(FileListBuf & Term, Term)(0)

'nullごとに区切って配列化
Dim SectionNames() As String = Split(FileListBuf, ChrW(0))

'配列の中身を確認
For Each X As String In SectionNames
Console.WriteLine("[" & X & "]")
Next
End Sub

------------------------------------------------------------------------
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2005-09-01 16:10
taaさん、こんにちは。

引用:

※separateを"Char.MinValue"に指定しないと分割されない。&H0、Nothing、VbNullでは分割されませんでした。


VBで null 文字を表す定数は、vbNullChar です。
ただ、型を調べてみたら String 型だったので、
Dim strFileListArray() As String = strFileList.Split(vbNullChar.ToCharArray())
ってな感じでしょうか。
#試してません。

スキルアップ/キャリアアップ(JOB@IT)