• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C言語で2桁Hex文字列を10進数値に変換する方法)

C言語で2桁Hex文字列を10進数値に変換する方法

このQ&Aのポイント
  • C初心者のため、C言語で2桁Hex文字列を10進数値に変換する方法がわからない。
  • ネットでの調査や既存のプログラムを参考にして試したが、結果が期待通りにならずに困っている。
  • 質問者は、受信データの処理中に何が問題なのかを知りたいと思っている。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.5

>d[0], d[1], d[2] は間違いなく入っています。例えばd[0]=E5、d[1]=03という具合です。 なるほど、そういうことですね。 質問のところにあるプログラムは、HEX文字列を数値に変換するためのものです。 一方、測定器から送られてくるデータは、数値そのものです。 補足にあった配列の場合、リトルエンディアンですから、 0x03E5が、送信されたデータですね。 リトルエンディアンなので、プログラム的には面倒なのですが 2バイト固定ならば int n ; n = d [0]; n += d[1] << 8; こんな感じで、変換できます。 (チェックはしていないので、不具合があったらフォローします。)

NamakeGamo
質問者

お礼

早速有り難うございます。基本的にint型の変数に代入するだけで良いんですか! 早朝からまた現場がありますので、帰ってから早速試してみます。 有り難うございました。

その他の回答 (8)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.9

すみません。 一つ間違い、というか仕様の不備といいますかがありました。 下位8bitが0の場合、(例: 0x0100)上位8bitが無視されてしまいます。 使用するバイト数が決まってるなら /* whileではなく */ for(i=0;i<2; i++){ .... /* i ++ ; は削除*/ } とかした方がいいですね。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.8

ちなみにシフトやビット演算では強制的に int に変換されるので, 明示的なキャストはなくてもいいです. まあ, 「読んだ人に親切」という点ではキャストした方がいいでしょうが. あと, 「出来上がった値」が符号付きの場合にはしかるべく処理する必要がありますね. あれ? 「受信データ」を char にする必然性がそもそもないような....

NamakeGamo
質問者

お礼

ご指摘有り難うございます。実は送られてくるデータにはASCII、Hexデータが混在しています。そこで、一旦charに全部取り込んで、必要なデータを切り出して・・・という具合にやっています。具体的には先頭3バイトがASCIIで、次の4バイトがHexデータです。 受信データの検査もあるので、一旦全部取り込むようにしています。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.7

charが符号有りの可能性も考えて、元のを生かして作ればこんな感じでしょうか。 /* 0に初期化を忘れずに */ n=0; while(d[i] != '\0'){ /* char→intに型変換し、&で8bitだけにする */ /* d[i]が負のとき、下から9bit目以降に1が入るため */ c = (int)(d[i]) & 0xff ; /* 1文字当り8bitシフトして、|でビット毎の or を取る */ n |= c << (i * 8) ; /* 現在のiを使いたいので、加算するのは最後 */ i ++ ; }

NamakeGamo
質問者

お礼

kmee 様 ほんとに丁寧な説明有り難うございます。 早朝から現場がありますので、帰ってから早速試してみたいと思います。 また、判らない時は質問させて頂きます。その節はまたよろしくお願いいたします。

回答No.6

A#5です。 左シフトでキャストしわすれていました。 このままだと、上位バイトが0になると思います。 プログラムは以下のように訂正してください。 int n ; n = d [0]; n += (int) d[1] << 8;

NamakeGamo
質問者

お礼

有り難うございました。上手くいきました。ここ数日間の苦闘(?)がいったい何だったんだ!という感じです。

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.4

No. 1 です。 > d[0], d[1], d[2] は間違いなく入っています。例えばd[0]=E5、d[1]=03という具合です。 ああ、やっぱり(^^; d に入っているデータは値を文字列に変換したものではなく値そのものです。 データのフォーマットは回答 No.3 の kmee 氏が解説しているので、そのフォーマットを基に値を計算すればいいだけです。

NamakeGamo
質問者

お礼

ご指摘ほんとに有り難うございました。これまでもバイナリーデータとテキストデータの違いがわからず何度も参考書で調べていたのですが、ついに今回やっと判りました。 目からウロコとはこのことです(ちょっと違うかな?)。雲が晴れました!!

NamakeGamo
質問者

補足

>d に入っているデータは値を文字列に変換したものではなく値そのものです。 そーなんですか!やっと少しほぐれてきました。 >フォーマットを基に値を計算すればいいだけです。 どうプログラムすれば良いのでしょうか?1バイト目はE5ですから16*14+5、2バイト目は03ですから256*3で、229+768=997 とアスキー表を眺めながら考えるのですが、d[0]を上下4バイトずつに分けて計算するしかないように思うのですが、d[]を分割するなんて事出来るのでしょうか? 済みませんが、もう少しそこのところをお願い致します。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

> 2桁のHexデータ(リトルエンディアン) とはどんなデータでしょうか? リトルエンディアンは何についてなのでしょうか? d[0] : '0','1',...'9','A','B',...'F'の16進を表わす文字(4bit分:下位?上位?) d[1] : '0','1',...'9','A','B',...'F'の16進を表わす文字(4bit分:上位?下位?) d[2] : '\0' という16進数文字列なのでしょうか? リトルエンディアンがビットの並びについてなら 「80」が「最下位ビットのみ1」ということにならないでしょうか?この場合、このプログラムでは正しく求まりません。 それとも、4bit単位の上下についてリトルエンディアンなのでしょうか?「10」が「最下位ビットのみ1」となるような。この場合もプログラムは正しくありません。 一般的な上位4bit+下位4bitという並びならば、 sscanfで%xを指定するとか、 strtolを使うとかするのが楽ではないでしょうか。 d[0] : 0x00~0xffまでの数値(8bit分:下位) d[1] : 0x00~0xffまでの数値(8bit分:上位) d[2] : '\0' というデータなのでしょうか?(一般に、リトルエンディアンと言われたら、こういうデータを思い浮べますが) これだとプログラムが変わってきます。 資料をよく調べる、デバッガを使う、途中経過をprintf等で出力してみる、等で、d[*]にどんな値が入っているのか、nがどんな変化するのかよく調べるのがよいでしょう。 細かいことを言えば、 > n += c - 'A' + 10; これが期待通りに動くかどうかは、処理系依存です。

NamakeGamo
質問者

お礼

早速有り難うございます。大変申し訳ありませんが、hitomura 様への補足で更に補足質問させて頂きます。

回答No.2

ぱっとみですが、特におかしそうなところはないかな(^^;; 必ず、0になってしまうと言うことなので、 ループが一回も回っていない?と考えてます。 ブレイクポイントを打てるなら、whileループに入るところで配列の内容のチェック。 あと、if文での分岐で n+=.....の部分をきちんと通過しているか? をチェックすべきかと。

NamakeGamo
質問者

お礼

早速有り難うございます。

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.1

回答(というか補足要求)の前にまず一言、ループに入る前に n を初期化しましょう。 さて、d[0], d[1], d[2] の値はどうなっているか確認しましたか? 確認できたなら一例でかまわないのでそれを補足に記述願います。

NamakeGamo
質問者

補足

早速有り難うございます。 d[0], d[1], d[2] は間違いなく入っています。例えばd[0]=E5、d[1]=03という具合です。 d[2]には必ずNULLが入ります。 よろしくお願いします。

関連するQ&A