バイナリデータ2バイトを10進に変換してセット – プログラミング – Home

バイナリデータ2バイトを10進に変換し...
 
通知
すべてクリア

[解決済] バイナリデータ2バイトを10進に変換してセット


ピースケ
 ピースケ
(@ピースケ)
ゲスト
結合: 18年前
投稿: 25
Topic starter  

いつもお世話になります。
よろしくお願い致します。

環境VC++6.0
Windows XP

下記のバイナリーデータを読込んで10進に変換します。

バイナリーデータ16進
56 08 C6 62 4E 42 8F F3-33 49 A8 72 B0 3F 57 08

#int nByteSizeには取得するバイト数1or2が入る

// 構造体の実体化 及びメモリー領域確保
COOR_STR *pstrCoorXY;
pstrXY = (COOR_STR* ) malloc(sizeof(COOR_STR) * nNumOfData);

// データを読み込む
ReadFile(hF, chBuf, sizeof(chBuf), &dwResult, NULL);

for(count = 0; count < 5 ; count++)
{
// バイナリデータを格納
memcpy(chDataX, &chBuf[nX], nByteSize);
memcpy(chDataY, &chBuf[nY], nByteSize);

// データを変換およびセット
pstrXY->m_lX = (long)chDataX[0];
pstrXY->m_lY = (long)chDataY[0];

pstrXY++;
}

chDataXに56,chDataYに08と1バイトはpstrXY->m_lXに86,pstrXY->m_lYに8と
上手く取れるのですが chDataXに56 08,chDataYにC6 62と2バイトをいれても
pstrXY->m_lXには1バイトしかセットされません。

理由は (long)chDataX[0]; だからなんですが、格納した2バイトを
pstrXY->m_lXセットするにはどうすればいいでしょうか。
これだけの問題ではなく、もしかしたらバイナリーデータの取得方法のやり方
がおかしいのでしょうか。

デバックウィンドウのメモリーを見ますと
chDataXのアドレス 0x0012f3cc には56 20 と入っていますのでビックエンディアンと理
解しています。

どなたかご教授お願い致します。


引用未解決
トピックタグ
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

long*型にキャストして入れるか、long型変数にmemcpyするかしてできないでしょうか?

> memcpy(chDataX, &chBuf[nX], nByteSize);
// nByteSizeが何ものか?nXって?ループの中では同じ値を指し続けているか?
memcpy(&pstrXY->m_lX, &chBuf[nX], sizeof(long));


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

あ~すいません。
> // nByteSizeが何ものか?

>nByteSizeには取得するバイト数1or2が入る
にありましたね。

となると、1バイトの時もありうるならば、memcpy の前に明確に初期化処理が必要か
も。


返信引用
ピースケ
 ピースケ
(@ピースケ)
ゲスト
結合: 18年前
投稿: 25
Topic starter  

Blueさんありがとうございます。

for(count2 = 0; count2< nCoorCount; count2++)
{
 memset(chDataX,'\0',sizeof(chDataX)); // chDataX を初期化
 memset(chDataY,'\0',sizeof(chDataY)); // chDataY を初期化

で初期化処理はしています。

nXは取得するバイトの先頭をさしています。
書き忘れましたがfor文の最後でこのように場所移動させています
nDaiSize はバイト(1 or 2バイト)すうによってかわるので可変です。

pstrXY++;
nX = nX + nDaiSize; // データ位置カウントアップ(X)
nY = nY + nDaiSize; // データ位置カウントアップ(Y)

1バイト時
nXの初期値は0で 0バイト目から1バイトを取得するので 56を指す
nYの初期値は1で 1バイト目から1バイトを取得するので 08を指す

2バイト時
nXの初期値0で 0バイト目から2バイトを取得するので 56 08を指す
nYの初期値2で 2バイト目から2バイトを取得するので C6 62を指す

バイナリーデータも実際には256バイトあります
説明不足で済みません。


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

で、もう回答は書いたつもりなんですけど。

pstrXY->m_lX = 0;
pstrXY->m_lY = 0;

memcpy( &pstrXY->m_lX, &chBuf[ nX ], nByteSize );
memcpy( &pstrXY->m_lY, &chBuf[ nY ], nByteSize );

一応わかりやすいSample)

char s[ 2 ] = { 0x56, 0x08 };
long l;

l = 0;
memcpy( &l, &s[ 0 ], 2 );// 2134

l = 0;
memcpy( &l, &s[ 0 ], 1 );// 86


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

メモリ上でlongのデータがどのように配置されているかをきちんと理解していれば、
答えは出ると思いますよ。
この部分でまだうまく処理がかけないというのはその部分の理解が足りないからです。
メモリ上のlongやshortのデータがどのように配置されているのかをデバッガ等で
確認してみてください。また、メモリコピーがどのようにデータをコピーしているのかも
きちんと抑えておくべきです。


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

> long*型にキャストして入れるか
これ大間違いでした。sizeof( long ) == 4 の環境ではまずかったです。

sizeof( short ) == 2 の環境であるならば、2バイトの値を取得するときは
unsigned short* でキャストして取得ですね。

char s[ 2 ] = { 0x56, 0x08 };
long l;

// 2バイト
l = *( ( unsigned short* )&s[ 0 ] );

// 1バイト
l = *( ( unsigned char* )&s[ 0 ] );


返信引用
ピースケ
 ピースケ
(@ピースケ)
ゲスト
結合: 18年前
投稿: 25
Topic starter  

Blueさん丁寧な説明ありがとうございます。
PATIOさんアドバイスありがとうございます。

Blueさんのを参考にして下記のように解決しました。

for(count = 0; count< 5; count++)
{
 // 初期化
 pstrXY->m_lX = 0;
 pstrXY->m_lY = 0;

 // バイナリデータを格納
 memcpy(&pstrXY->m_lX, &chBuf[nX], nByteSize);
 memcpy(&pstrXY->m_lY, &chBuf[nY], nByteSize);

 pstrXY++;
 nX = nX + nDaiSize; // データ位置カウントアップ(X)
 nY = nY + nDaiSize; // データ位置カウントアップ(Y)
}


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

ちなみに、malloc した領域は free しないのですかね?
まぁしなくても、プログラムが終われば、システムが解放してくれますけど。

freeするときはmalloc関数の戻り値を指定しないといけないので、

>pstrXY = (COOR_STR* ) malloc(sizeof(COOR_STR) * nNumOfData);
>pstrXY++;
のように、malloc関数の戻り値を書き換えて使っているようですと、freeするときに
進めた分ポインタを戻すような作業が必要になります。

配列のように

pstrXY[ 0 ]

というようにアクセスするか、free用にmalloc関数の戻り値を保持する変数をもう1つ
用意するようにしたほうがいくらか簡単です。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました