Long型をULONG型に変換したい

解決


ウルトラロング  2004-02-06 17:08:05  No: 81868  IP: [192.*.*.*]

ULONG型を使用するアプリにデータを転送したいため
下記のようにプログラミングしましたが
Chr()で表示できないバイナリ値の場合、
szULONGには正しい数値が入りません。
lnLng=5000 の場合 szULONG= 88 13 00 00 の形式で
入ってきて欲しいのですが 00 13 00 00 となります。
どなたか教えてください。

※ちなみにデータ転送はString型でないと送れないため
szULONGは他型で定義出来ません。 
    
Function Lng_to_ULONG(lnLng As Long) 
Dim szStr       As String * 8
Dim szHex(4)    As String * 2
Dim szULONG     As String * 4
Dim nValue(4)   As Integer
Dim I, n        As Integer
Dim nDigit      As Integer
Dim n16         As Long

    'Longを16進に変換し、2バイトづつに分ける
    RSet szStr = Hex(lnLng)
    szHex(1) = Mid(szStr, 7, 2)
    szHex(2) = Mid(szStr, 5, 2)
    szHex(3) = Mid(szStr, 3, 2)
    szHex(4) = Mid(szStr, 1, 2)
    
    '16進を10進(Long)に変換する。
    For n = 4 To 1 Step -1
        n16 = 1
        For I = 2 To 1 Step -1
            If Trim(Mid(szHex(n), I, 1)) <> "" Then
                If Asc(Mid(szHex(n), I, 1)) >= Asc("A") Then
                   nDigit = Asc(Mid(szHex(n), I, 1)) - Asc("A") + 10
                Else
                   nDigit = Asc(Mid(szHex(n), I, 1)) - Asc("0")
                End If
                nValue(n) = nValue(n) + n16 * nDigit
            End If
            n16 = 16 * n16
        Next I
    Next n
    
    szULONG = Chr(nValue(1)) & Chr(nValue(2)) & Chr(nValue(3)) & Chr(nValue(4))

End Function

編集 削除
いちゆ  2004-02-06 17:19:20  No: 81869  IP: [192.*.*.*]

ってーか、この関数、何したいの?
あとULongってUnsigned Longじゃ…?
ウルトラですか。

>ULONG型を使用するアプリにデータを転送したいため
ああ、送りたいのか。

>下記のようにプログラミングしましたが
>Chr()で表示できないバイナリ値の場合、
バイナリ値をChr()で表示ってどーよ?

>szULONGには正しい数値が入りません。
関数最後じゃszULONGは文字なんすけど?


>lnLng=5000 の場合 szULONG= 88 13 00 00 の形式で
こんな形式見たことありません。

>入ってきて欲しいのですが 00 13 00 00 となります。
しかも関数最後じゃ空白だし。

>※ちなみにデータ転送はString型でないと送れないため
>szULONGは他型で定義出来ません。 
タガタ??
あ〜ん〜と〜〜〜〜、まぁわからん。
わからんから、プログラムだけ作っといたぞ。
Msgbox proc1(5000)
とかでためしてみ。

Type tLong
    datus           As Long
End Type

Type tLong_Bytes
    data(1 To 4)    As Byte
End Type

Function proc1(ByVal nLongValue As Long) As String
    
    Dim i           As Long
    Dim v1          As tLong
    Dim v2          As tLong_Bytes
    
    v1.datus = nLongValue
    LSet v2 = v1
    
    For i = 1 To 4
        proc1 = proc1 + Hex(v2.data(i)) + " "
    Next
    
End Function

編集 削除
ウルトラロング  2004-02-06 17:33:26  No: 81870  IP: [192.*.*.*]

いちゆさん、ありがとうございました。

表記したプログラムを実行されるとわかると思いますが
 szULONG= 88 13 00 00 はHEXで見たときの結果と
言う事を書きたかったのです。
言葉不足ですみません。
実際は
 szULONG= ・・・・
の4バイトとなります。

初めての投稿なので言葉がわかりづらく思われると思いますが
もしおわかりになりましたらよろしくお願いします。

編集 削除
いちゆ  2004-02-06 17:45:28  No: 81871  IP: [192.*.*.*]

>表記したプログラムを実行されるとわかると思いますが
> szULONG= 88 13 00 00 はHEXで見たときの結果と
>言う事を書きたかったのです。
>言葉不足ですみません。
>実際は
> szULONG= ・・・・
>の4バイトとなります。
ん〜、なんだかなぁ。
とりあえず、LongだろうとUnsignedLongだろうと、バイト数が一致していれば
そのブロックの先頭のメモリアドレスからどんな風に読み取るのかは相手次第で、
Longで送っても大丈夫な気がするんだが…
で、私の作ったのは実行してみたの?

第一、最初の質問の
>lnLng=5000 の場合 szULONG= 88 13 00 00 の形式で
>入ってきて欲しいのですが 00 13 00 00 となります。
だけど、あなたが書いた関数内部じゃ空白にしかなりませんでしたよ?
再現性のあるプログラムのデバッグの質問をしているのに、
再現できないのじゃどうしようもないのですが?

編集 削除
ASC136  2004-02-10 17:49:53  No: 81872  IP: [192.*.*.*]

ウルトラロング様の関数での問題は、CHR(nvalue(1))において
CHR(136)が変換できない文字コードになっている事でしょう。
Chr関数にて文字コードで変換できない値の場合の対応は私も知りたい
所です。
どなたか教えてください。

編集 削除
いちゆ  2004-02-10 18:06:25  No: 81873  IP: [192.*.*.*]

…あ〜、もしかしてウルトラロングって文字列変数で実はUnsignedLong型じゃない…?
で、&h88の文字コード(Chr$(&h88))がVBでは認識できないから困ってると。
…Chr(&h88)が存在して読み取れないのか、Chr(&h88)が存在すらしないのかをしらべてみた。

Sub test()
Dim sbuf()  As Byte
Dim s1      As String
Dim s2      As String
'chr$(&h88)はString型の中に存在できるか?

Debug.Print "TEST1"
'Byte配列に&h88を入れてみる
ReDim sbuf(1 To 1)
sbuf(1) = &H88

'String型(1)に代入してみる(Chr$(&h88)は代入できるか?)
s1 = sbuf
sbuf = s1: debugOut sbuf

'String型(2)に代入してみる(Chr$(&h88)は生存できるか?)
s2 = s1
sbuf = s2: debugOut sbuf

Debug.Print "TEST2"
'String型にChr$(&h88)を入れてみる
s1 = Chr$(&H88)

'Chr$(&h88)は生きているか?
sbuf = s1: debugOut sbuf

'String型(2)に代入してみる(Chr$(&h88)は生存できるか?)
s2 = s1
sbuf = s2: debugOut sbuf

End Sub

Sub debugOut(ByRef buf() As Byte)
Dim va      As Variant
For Each va In buf
    Debug.Print Hex$(va); " ";
Next
Debug.Print
End Sub

イミディエイトウィンドウには
TEST1
88 
88 
TEST2
0 0 
0 0 
と表示された。

つまりChr$関数は特定の文字コードを入れた場合はNullCharを返す。
Chr$関数では特定できない文字がある。
しかし、いったんString型に入ってしまうと、
String型の中身は影響を受けないことがわかった。

…まぁ、自己満足だけどね。

編集 削除
ウルトラロング  2004-02-12 09:01:58  No: 81874  IP: [192.*.*.*]

ASC136様、
わたくしの拙い文章を理解いただけて嬉しく思いました。
(もしかしてわたくしと同じCOBOL経験者ですか?)
いろいろと試しましたが、やはりうまく行かない状態です。
どなたか知ってる方がいらっしゃいましたら宜しくお願いします。

編集 削除
いちゆ  2004-02-13 14:56:24  No: 81875  IP: [192.*.*.*]

>ASC136様、
>わたくしの拙い文章を理解いただけて嬉しく思いました。
>(もしかしてわたくしと同じCOBOL経験者ですか?)
>いろいろと試しましたが、やはりうまく行かない状態です。
>どなたか知ってる方がいらっしゃいましたら宜しくお願いします。
…つっこんで悪いとは思うけど。
どんなコードを書いたのかを示してくれると助かるような気がする。
Stringに&h88を入れることができるのはわかったのだし…

編集 削除
ウルトラロング  2004-02-13 15:17:57  No: 81876  IP: [192.*.*.*]

いちゆ様色々と回答ありがとうございます。
今回の内容はC言語で開発されている機械に対して
接続を行なう際に色々な情報(Uchar・UShort・Ulong)
などの相手方にあわした情報を1バッファ内に設定を行なう
必要があります。
Uchar及びUSHortに対しては1バッファ内に設定ができ
Ulong型のデータについてのみ相手方でエラーとなる状態です。
ちなみにUlong方についてもASC文字コードで変換可能な値での
変換は正常値として判断されます。
最初の書込み時はULongの変換方法を記述しています。

実際にバッファに設定したい情報はChr(136)の1文字です。

編集 削除
しゅう  2004-02-13 21:52:43  No: 81877  IP: [192.*.*.*]

>※ちなみにデータ転送はString型でないと送れないため
>szULONGは他型で定義出来ません。 
と、最初の書込みでString型以外は使用できませんと書込みされていますが、
機械に送信する方法がシリアル通信である場合は(他の通信方法でも)、
下記の通りバイト配列でも送信できます。
(いちゆさんが何度か(もかな?)確認していますが。)
参考意見として受け止めて頂ければ幸いです。

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Sub Command1_Click()
Dim lnLng As Long
Dim szULONG(3) As Byte
    lnLng = 5000
    Call CopyMemory(szULONG(0), lnLng, 4)
    MSComm1.Output = szULONG
End Sub

編集 削除
ウルトラロング  2004-02-17 12:06:22  No: 81878  IP: [192.*.*.*]

しゅう様書き込みありがとうございます。
いちゆ様もありがとうございます。

前回、いちゆ様の書き込みにて確認を行ってみました。
内容をASCBで確認を行うと私の意図している結果となりましたが、
一回目の発信情報で記述した文字列(string * 4)への設定方法はないでしょうか?
送信バッファの一部として設定を行いたいのです。
(ちなみに)送信バッファへの設定は
szBuf = szBuf & XXXX で行っています。
馬鹿な質問をしているのかな?

編集 削除
しゅう  2004-02-17 21:12:31  No: 81879  IP: [192.*.*.*]

String型として&H00001388を連結する方法はわかりませんが、
Byte配列であれば下記の通り簡単に文字列と連結できます。
送信バッファをByte配列にした方が良いと思います。

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Sub Form_Load()
Dim A As Long
Dim B As String * 4
Dim C(7) As Byte
Dim i As Long
    A = 5000
    B = "TEST"
    Call CopyMemory(C(0), A, 4)
    For i = 0 To 3
        C(i + 4) = Asc(Mid(B, i + 1, 1))
    Next
    For i = 0 To 7
        Debug.Print Hex(C(i))
    Next
End Sub

編集 削除
しゅう  2004-02-18 02:22:37  No: 81880  IP: [192.*.*.*]

上の訂正します。
Long型→Byte配列→String型が可能な様です。
(いちゆさんのテスト参考にしました。)
詳しくは調べていませんが、試してみて下さい。

Private Sub Command1_Click()
Dim lnLng As Long
Dim ByteAry(3) As Byte
Dim szULONG As String * 4
    lnLng = 5000
    Call CopyMemory(ByteAry(0), lnLng, 4)
    szULONG = ByteAry
    For i = 1 To 4
        Debug.Print AscB(MidB(szULONG, i, 4))
    Next
End Sub

編集 削除
しゅう  2004-02-18 12:41:36  No: 81881  IP: [192.*.*.*]

ウルトラロング様、うまくいきましたでしょうか?
現在、シリアル通信の環境がなくテストできませんが、
代わりにファイル操作でテストしてみました。
しかし、|88|13|00|00|という出力を得る事が出来ておりません。

MSDNに下記記載がありました。
やっぱり、バイト配列じゃないとだめなのかと思い始めています。

VBA では、新しいデータ型としてバイト型 (Byte) が追加されています。バイナリデータを操作する際に文字列変数を使うと入出力時に ANSI - Unicode 変換がおこなわれてバイナリデータが変更されてしまいます。バイナリデータを扱う場合は、バイト型の変数を利用するようにしてください。

編集 削除
ウルトラロング  2004-02-18 15:35:42  No: 81882  IP: [192.*.*.*]

しゅう様、いろいろと親切にわかりやすく教えていただき
ありがとうございました。

送信バッファをByte配列にする方法で試した所
成功しました。
いろいろ試しましたが、やはりバイト配列じゃないと
だめだと言うことですね。
勉強になりました。
本当にありがとうございました。

編集 削除