C初心者です。よろしくお願いします。
測定器からシリアルで送られてくる2桁のHexデータ(リトルエンディアン)を10進数値に変換したいのですが、ネットでいろいろ調べてもよく解りません。
ネット上にあったプログラムを参考にして、次のようにやっています。
char d[3]; //受信データ
// データ受信処理後
int i=0, c=0, n;
while(d[i] != '\0'){
n = n * 0x10;
c = d[i++];
if((c >= '0') && (c <= '9')){
n += c - '0';
}
else if((c >= 'A') && (c <= 'F')){
n += c - 'A' + 10;
}
}
printf("%d\n",n);
結果を表示すると’0’になってしまいます。
どこがダメなのか、よろしくお願いします。
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;
こんな感じで、変換できます。
(チェックはしていないので、不具合があったらフォローします。)
早速有り難うございます。基本的にint型の変数に代入するだけで良いんですか!
早朝からまた現場がありますので、帰ってから早速試してみます。
有り難うございました。
No.9
- 回答日時:
すみません。
一つ間違い、というか仕様の不備といいますかがありました。
下位8bitが0の場合、(例: 0x0100)上位8bitが無視されてしまいます。
使用するバイト数が決まってるなら
/* whileではなく */
for(i=0;i<2; i++){
....
/* i ++ ; は削除*/
}
とかした方がいいですね。
No.8
- 回答日時:
ちなみにシフトやビット演算では強制的に int に変換されるので, 明示的なキャストはなくてもいいです. まあ, 「読んだ人に親切」という点ではキャストした方がいいでしょうが.
あと, 「出来上がった値」が符号付きの場合にはしかるべく処理する必要がありますね.
あれ? 「受信データ」を char にする必然性がそもそもないような....
ご指摘有り難うございます。実は送られてくるデータにはASCII、Hexデータが混在しています。そこで、一旦charに全部取り込んで、必要なデータを切り出して・・・という具合にやっています。具体的には先頭3バイトがASCIIで、次の4バイトがHexデータです。
受信データの検査もあるので、一旦全部取り込むようにしています。
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 ++ ;
}
kmee 様 ほんとに丁寧な説明有り難うございます。
早朝から現場がありますので、帰ってから早速試してみたいと思います。
また、判らない時は質問させて頂きます。その節はまたよろしくお願いいたします。
No.6
- 回答日時:
A#5です。
左シフトでキャストしわすれていました。
このままだと、上位バイトが0になると思います。
プログラムは以下のように訂正してください。
int n ;
n = d [0];
n += (int) d[1] << 8;
No.4
- 回答日時:
No. 1 です。
> d[0], d[1], d[2] は間違いなく入っています。例えばd[0]=E5、d[1]=03という具合です。
ああ、やっぱり(^^;
d に入っているデータは値を文字列に変換したものではなく値そのものです。
データのフォーマットは回答 No.3 の kmee 氏が解説しているので、そのフォーマットを基に値を計算すればいいだけです。
この回答への補足
>d に入っているデータは値を文字列に変換したものではなく値そのものです。
そーなんですか!やっと少しほぐれてきました。
>フォーマットを基に値を計算すればいいだけです。
どうプログラムすれば良いのでしょうか?1バイト目はE5ですから16*14+5、2バイト目は03ですから256*3で、229+768=997 とアスキー表を眺めながら考えるのですが、d[0]を上下4バイトずつに分けて計算するしかないように思うのですが、d[]を分割するなんて事出来るのでしょうか?
済みませんが、もう少しそこのところをお願い致します。
ご指摘ほんとに有り難うございました。これまでもバイナリーデータとテキストデータの違いがわからず何度も参考書で調べていたのですが、ついに今回やっと判りました。
目からウロコとはこのことです(ちょっと違うかな?)。雲が晴れました!!
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;
これが期待通りに動くかどうかは、処理系依存です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- Excel(エクセル) アウトラインの小計のやり方 1 2023/03/20 11:51
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
教えて下さい
-
配列でデータが入っている要素...
-
VBA 毎日取得するデータを順番...
-
エクセルで1次近似をもとめたい
-
Excelのマクロでワードのテキス...
-
VBA 該当データがない時 ...
-
VBA 空白セルを削除ではない方...
-
C#にてDropDownListの値を動的...
-
マクロVBAについて
-
ミラーデータとは?
-
LoadPictureしたイメージデータ...
-
ADOを使用してExcelデータをAcc...
-
【VB】DataGridViewにテキスト...
-
Android携帯をUSBメモリ代わりに
-
【エクセル】測定時間がバラバ...
-
最大値、最小値
-
シリアル通信でのデータ受信
-
javaでDBからデータを取ってき...
-
シーケンサにパソコンからアク...
-
レコードセットのデータを1行...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
教えて下さい
-
【エクセル】測定時間がバラバ...
-
配列でデータが入っている要素...
-
多量のSUMIF式を軽くしたい
-
エクセルで2つの時系列のデー...
-
Excelのマクロでワードのテキス...
-
メモ帳(テキストデータ)をExc...
-
VBA 空白セルを削除ではない方...
-
VBAを使ってOutlookメール本文...
-
Accessで該当データにフラグを...
-
合計3TBのデータのハッシュ値を...
-
シーケンサにパソコンからアク...
-
S9タイプからXタイプにデータ...
-
カンマからスラッシュに
-
VBAでシートからコンボボックス...
-
VBA 毎日取得するデータを順番...
-
ビットシフトについて
-
ユーザーフォームのテキストボ...
-
EXCELVBAでSQLserverからデータ...
-
特定のデータの抽出方法を教え...
おすすめ情報