パック十進数に変換するには?


てつこ  2005-07-06 02:55:27  No: 90828

はじめまして。てつこと申します。
こんな事で質問しては申し訳ないかとは思いましたが、
万策つきてしまいましたので、お力をお貸しください。

SQLサーバからデータを抽出し、固定長テキストファイルにはきだすのですが、
テキストファイルにはきだす際、数値をパック十進数に変換しなければなりません。

現在はFTRANを使用して返還しているのですが、このツールを使用せずに
変換する必要が出た為、方法を探したのですがどうしてもみつかりません。

方法をご存知な方がいらっしゃいましたら、ぜひご教授ください。

OSはWin2000/XPです。VBは6.0を使用しています。

よろしくお願い致します。


ガッ  2005-07-06 05:24:53  No: 90829

まず、私はパック十進数なるものをしらないので、Google先生に聞いてみました。
→結果: http://tinyurl.com/a5jll

得られた結果からすると、以外と簡単にゴリゴリ書ける気がします。
まぁ、それだけですが。(ぇ


ねろ  2005-07-06 06:09:49  No: 90830

こういうのは意外とテーブル参照が楽だったりします。
合ってるかどうか判らんし、どう見ても醜いコードがけど
参考に。
Private Function Pack10(ByVal iData As Long) As String
    Dim ss As String
    Dim pData As String
    Dim sData As String
    Dim d(11) As String
    Dim i As Long
    
    d(0) = "0000": d(1) = "0001": d(2) = "0010"
    d(3) = "0011": d(4) = "0100": d(5) = "0101"
    d(6) = "0110": d(7) = "0111": d(8) = "1000"
    d(9) = "1001": d(10) = "1100": d(11) = "1101"
    
    sData = CStr(iData)
    If Left(sData, 1) <> "-" And Left(sData, 1) <> "+" Then
        sData = "+" & sData
    End If
    
    For i = Len(sData) To 1 Step -1
        ss = Mid(sData, i, 1)
        If ss = "+" Then
           pData = pData & " " & d(10)
        ElseIf ss = "-" Then
            pData = pData & " " & d(11)
        Else
            pData = d(Val(ss)) & " " & pData
        End If
    Next
    Pack10 = pData
End Function


てつこ  2005-07-07 00:51:56  No: 90831

ガッ様、ねろ様 ご回答ありがとうございました。
おかげ様でパック十進数なるものが大分わかりました。

そこで更なる質問なのですが、
以下の様な出力文字列を編集するロジックを組んだ時、
[rs.Fields(1)]に[432]という値が入っていた場合、
パック十進数に置き換えると[0100001100101100]となる事は
分かりましたが、実際に[0100001100101100]という値を
パック十進数の値として出力する方法がわかりません。

ご教授の程、よろしくお願い致します。

Function sLinStr(rs As Recordset) As String
    Dim sStr As String
    
    '変数クリア
    sStr = ""
    '8桁の値を日付表示に変換
    sStr = Format(rs.Fields(0), "0000/00/00") & ";"
    'パック十進数に変換
    sStr = rs.Fields(1) & ";"
    '後ろにスペースを5桁を追加
    sStr = rs.Fields(2) & String$(5, " ")
    
    sLinStr = sStr
End Function


ねろ  2005-07-07 16:47:48  No: 90832

先ず私が書いた関数に好きな数字を入れて何が返って来るか見てから
再度質問して下さい。


てつこ  2005-07-07 18:08:18  No: 90833

ねろ様

先日ロジックを提示して頂いた時に、即実行してみました。
[432]という値を入れて実行すると[0100 0011 0010  1100]が
帰ってくる事は確認しております。
(折角提示して頂いたものを確認もしないような失礼は致しません。)

この[432]を[0100 0011 0010  1100]に変換した後、
2バイトの領域に格納する為に更に変換が必要なのではないかと
思うのですが、その方法がわからず困っています。

「そんな初歩的な事もわからんのか!」とお叱りを受けるかも
しれませんが、現実にわからないのです。

どうぞ、よろしくご教授ください。


ねろ  2005-07-07 19:12:22  No: 90834

>SQLサーバからデータを抽出し、固定長テキストファイルにはきだすのですが、
>テキストファイルにはきだす際、数値をパック十進数に変換しなければなりません。
データーを固定長のパック十進数にしてテキストファイルにした、元のデーターと
変換されたテキストのサンプルは有りませんか?


てつこ  2005-07-07 19:47:33  No: 90835

残念ながら、今手元には変換後のデータしかありません。


特攻隊長まるるう  2005-07-07 21:07:00  No: 90836

何が問題なのか理解してないね(^^;)。とりあえず
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200506/05060170.txt
を読んでみて?。
>Dental 2005/06/29(水) 16:49:12
で Dental さんがリンク貼ってくれてるような認識が必要です。

最初の質問で
>SQLサーバからデータを抽出し、固定長テキストファイルにはきだすのですが、
>テキストファイルにはきだす際、数値をパック十進数に変換しなければなりません。
とありますが、テキストファイルというと、Notepad なんかで開いて読める文字、
…つまりVBで扱うなら String 型の『文字列』に変換したい…という質問になります。
ですから、ねろさんはわざわざ String 型の『文字列』を返してくれてるサンプルを
提示して下さいました。N進数の文字列が欲しい。つまり"0100 0011 0010 1100"と
いう文字列データが最終結果として欲しいという質問だからです。

>この[432]を[0100 0011 0010  1100]に変換した後、
>2バイトの領域に格納する為に更に変換が必要なのではないかと
>思うのですが、その方法がわからず困っています。
ここで、2バイトという表現で書き出すのがテキストファイルでなく、
バイナリファイルである可能性が出てきてしまいました。更に、2バイトの
『何』が欲しいのか分からなくなってしまいました。

>現在はFTRANを使用して返還しているのですが、このツールを使用せずに
>変換する必要が出た為、方法を探したのですがどうしてもみつかりません。
そのFTRANとやらの前後で入力と出力のデータ型を明らかにして下さい。
また、その具体的なデータを示して下さい。
例えば
    Dim wInputData As Integer
    Dim wOutputData(1) As Byte
    wInputData = 432  '入力(数値型[2Byte]10進数表現で 432)
    wOutputData = FTRAN(wInputData) 'パック十進数変換
    'wOutputData(0) は2進数表現で 01000011(10進数表現で 67)
    'wOutputData(1) は2進数表現で 00101100(10進数表現で 44)


ねろ  2005-07-08 02:17:59  No: 90837

特攻隊長まるるうさんのレス完璧で、これ以上付け加えることは有りませんが、
>残念ながら、今手元には変換後のデータしかありません
変換後のデーターが有れば目的の96.3%位は達成できますが。
と言うか、八百屋に行って「大根と人参下さい」と言ったら
人参が無いんでと言って、大根も出てこないような。。。。。


てつこ  2005-07-08 02:49:48  No: 90838

こんな感じになります。
[  ]の部分が変換後の文字です。

01○○株式会社    ○○株式会社△支店


。。。  2005-07-08 04:19:21  No: 90839

>[    ]の部分が変換後の文字です。
>01○○株式会社      ○○株式会社△支店

括弧はどこ?


ねろ  2005-07-08 04:38:29  No: 90840

要するに表現できない文字ですね。
   Dim s As String
   Dim i As Integer
   Dim ss As String
   s = ". ."
   For i = 1 To Len(s)
        ss = ss & " " & CStr(Asc(Mid(s, i, 1)))
   Next
   Debug.Print ss
「. .」の替わりに変換後の文字を入れて
ssを教えてください。


魔界の仮面弁士  2005-07-08 04:56:30  No: 90841

この場合の結果は、「バイナリデータ」になりますよね。
可読文字になるとは限らないので、テキストデータとしては
扱えないでしょう。Stringではなく、Byte配列で処理してください。

パック10進数は、私も(聞いたことはあれど)内容までは知らなかったので、
下記の説明記事を参考にして、VB6のコードに起こしてみましたが……
これで良いのかな。
http://www.jtw.zaq.ne.jp/kayakaya/new/kihon/text/zonepack.htm

'-------------
Public Function Pack(ByVal Value As Long) As Byte()
    Dim BCD() As Byte
    Dim sDec As String
    Dim Length As Integer, Limit As Integer
    Dim Pos As Integer, C As Byte
    Dim Index As Integer

    sDec = StrReverse(CStr(Abs(Value)))
    Length = Len(sDec)
    Limit = Length \ 2
    ReDim BCD(Limit)
    BCD(Limit) = IIf(Value >= 0, &HC, &HD)
    Index = Limit
    For Pos = 1 To Length
        C = CByte(Mid(sDec, Pos, 1))
        If Pos Mod 2 = 1 Then
            BCD(Index) = C * &H10 + BCD(Index)
            Index = Index - 1
        Else
            BCD(Index) = C
        End If
    Next
    Pack = BCD
End Function


ねろ  2005-07-09 07:12:32  No: 90842

>この[432]を[0100 0011 0010  1100]に変換した後、
>2バイトの領域に格納する為に更に変換が必要なのではないかと
>思うのですが、その方法がわからず困っています。

ビットイメージをByte配列に格納するのはそんなに
難しいことではない。

'呼び出し方
Dim byt() As Byte
byt = GetPack10Byte(432)

Private Function GetPack10Byte(ByVal Value As Long) As Byte()
    s = Pack10(Value)
    s = Replace(s, " ", "") '空白行の削除
    GetPack10Byte = BitToByte(s)
End Function

Private Function BitToByte(s)
    'ビットイメージをByte配列に
    Dim byt() As Byte
    Dim i As Integer
    Dim s1 As String
    If Len(s) Mod 8 <> 0 Then
        s = "0000" & s        'Byteに揃える
    End If
    ReDim byt(Len(s) \ 8 - 1) 'Byte配列の確保
    Do
        s1 = Left(s, 8)
        byt(i) = BitToLong(s1)
        s = Right(s, Len(s) - 8)
        i = i + 1
    Loop While (Len(s) <> 0)
    BitToByte = byt
End Function

Private Function BitToLong(ByVal s As String) As Long
   'ビット表示をLongに変換
   Dim i As Integer
   Dim t As Long
   For i = 1 To Len(s)
        If Mid(s, i, 1) = "1" Then
            t = t + 2 ^ (Len(s) - i)
        End If
    Next
    BitToLong = t
End Function
これで多分魔界の仮面弁士さんの処理結果と同じになるはずだが。。。。
まあこんな回りくどい方法にすることは無いのだが、行きがかり上やむおえず。orz


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加