• 締切済み

charからの型変換

現在,計測機からUDP通信で送信される計測データをwinsockを用いて受信し解析するプログラムを書いています.受信データは16進数の数値群です. http://www.geekpage.jp/programming/winsock/udp.php こちらのコードを参考に作成し,buf配列内をdatファイルで書き出すことで受信データの確認も出来ました. しかし,解析にあたりいくつか私では解決できない問題に悩んでいるので質問させていただきます. recv関数の第二引数で指定する配列がchar型しか指定できないようで受信データが文字データとなってしまうことに悩んでいます. これをint型などの計算しやすい型に変換したいのですが,strtolやatol関数を用いても失敗してしまいます.(ASCIIに準拠していない為?) printf("%s %x",buf , buf)でbufを表示しようとしてもやはり文字化けが起こってしまいます. int型やdoubleなどの数値の型へ変化する方法をアドバイスいただけないでしょうか? datファイルで保存した受信データはこんな感じです(一部) FF EE 3D 75 62 00 C3 00 00 FF 55 00 D7 00 00 FF 5E 00 D7 00 00 FF 5A 00 C3 00 00 FF 64 00 C3 00 00 FF 62 00 EB 00 00 FF 71 00 FF 00 00 FF 69 00 FF 00 00 FF 6E 00 FF 00 00 FF 65 00 FF 00 00 FF A1 00 EB 00 00 FF A3 00 D7 00 00 FF 8C 00 FF 5C 00 FF B3 00 EB 63 00 FF AA 00 C3 00 00 FF 8F 00

みんなの回答

回答No.4

調べるべき単語は次の2つ ・バイトアライメント ・エンディアン ポイントは次の2点 ・「計測機からUDP通信で送信される計測データ」の型は何か? 0x10というデータを送信するには、 - char型で'1'という文字、'0'という文字を送信する - int型で数値を送信する ・計測データ以外の情報は送られているか? ヘッダ情報や、計測データに必要な数値以外が送られていないか 以下、データがintで、計測データ以外の不要情報が含まれていない場合についてです。 他の方が答えられているように、通信ではエンディアンなどの関係から、 char型(つまり1Byte単位)でデータをやり取りします。 したがって第二引数はchar型となります。 (1).リトルエンディアンでint型(4Byte数値データ)を1つだけ送信する場合、 送信元PCのメモリ上で0x12345678 というデータは、 78 56 34 12 と配置されます。 そのままエンディアン変換せず送信するとします。 これをchar* cDataとして受け取った先で、 リトルエンディアンのint nDataに戻す(memcpy(&nData, cData, sizeof(int)))と、 元の値に復帰することができます。 (2).送信元と受取先がエンディアンが異なる場合、 受取先でエンディアン変換が必要になります。 (3).通信の規約上、intデータをビッグエンディアン(通信用エンディアン)に変換している場合 受取先でエンディアン変換が必要になります。

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.3

>キャストしてdwDataのポインタへ渡していると理解しましたがdwDataは普通のchar変数なんでしょうか? ハンガリアン表記は確実に廃れていっている…んですね。 dwDataはDWORD型の変数の場合…で想定しています。 # まぁ、本来の問題とは関係ないでしょうね。

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.2

>recv関数の第二引数で指定する配列がchar型しか指定できないようで受信データが文字データとなってしまうことに悩んでいます. 1バイトを受け取るのに都合がいいからchar型へのポインタになっているだけです。 ・エンディアンが送信側と受信側で同じ。 ・データの欠落は発生しない。 のであれば、 recv(Socket, (char *)&dwData, sizeof(DWORD), 0); なんてのも可能です。 # まぁ欠落(というかsizeof(DWORD))なしで受け取れる保証がないのでこんなコトやりませんが。 # sizeof(DWORD)くらいなら1回で受信できるとは思いますけどね…保証はない。 >これをint型などの計算しやすい型に変換したいのですが,strtolやatol関数を用いても失敗してしまいます.(ASCIIに準拠していない為?) こちらに関しては既に回答されている内容を勉強してくださいな。 その上で「エンディアン」について勉強してください。 同じ値でも(char型以外だと)リトルエンディアンなのかビッグエンディアンなのかで結果が変わります。 # なので…「ネットワークバイトオーダー」に揃えるのが確実なんですけどね。

thinking_
質問者

補足

>recv(Socket, (char *)&dwData, sizeof(DWORD), 0); >なんてのも可能です。 キャストしてdwDataのポインタへ渡していると理解しましたがdwDataは普通のchar変数なんでしょうか? >同じ値でも(char型以外だと)リトルエンディアンなのかビッグエンディアンなのかで結果が変わります。 送信機はリトルエンディアンですので受信側もこれに合わせようと考えています

  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.1

・あなたのプログラミングに関する知識の不足 ・計測器からのデータに関しての説明不足 で、簡単なアドバイスは難しいですね。 「コンピュータ内部では、文字も数値も2進数で表されている」から始めて、データがどのように表現されるかあたりを学習するとすこし道が見えるかと思います。 ・ A という文字データは、メモリ上でどのように表現されているか ・ 10進数の 100 はint型だと、メモリ上でどのように表現されているか ・ 10進数の 100 はchar型だと、メモリ上でどのように表現されているか ・ 10進数の 100 はdouble型だと、メモリ上でどのように表現されているか ・ 0x20 というデータは一体何を表しているのか あたりが、わかるようになってください。

thinking_
質問者

補足

アドバイスありがとうございます. 少し調べてみました http://www.pro.or.jp/~fuji/mybooks/cpro/cpro.4.2.1.html どれもメモリ内では同じ取扱いなんですね. コンピュータ内ではすべてビットとして扱われていることは知っていたのでそこからどうにか変換できると考えたのですが,その手立てが思いつかず立ち止まってます.

関連するQ&A