ASCII → HEX 変換について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
udai

ASCII → HEX 変換について

#1

投稿記事 by udai » 13年前

アスキーゴードで設定された
char配列があります。
char as[3] = {0x31,0x32,0}

この配列の要素をそれぞれ
0x31→0001
0x32→0010

と判 断し、

1byteのchar型データ
char hex = 0x12(00010010)

に変換する方法をご教授願います。

下記リンクのarainさん回答の逆の考え方で出来そうなきがするのですが、
逆の考え方がわからない状態です。

組み込み分野で使用する為、標準ライブラリは使用できません。

http://okwave.jp/qa/q4389139.html

かずま

Re: ASCII → HEX 変換について

#2

投稿記事 by かずま » 13年前

udai さんが書きました:char as[3] = {0x31,0x32,0}
as[0] と as[1] は、
0x30~0x39 ('0'~'9')、0x41~0x46 ('A'~'F')、0x61~0x66 ('a'~'f')
だけだと仮定してよいのでしょうか?

コード:

#define conv2(x) (((x) >> 6 & 1) * 9 + (x) & 15)

unsigned char conv(const char *as)
{
    return conv2(as[0])<<4 | conv2(as[1]);
}

// 以下、テストプログラム
#include <stdio.h>

int main(void)
{
    char as[4][3] = {
        { 0x31, 0x32, 0 },
        { 0x41, 0x42, 0 },
        { 0x65, 0x66, 0 },
        { 0x43, 0x39, 0 },
    };
    int i;
    unsigned char hex;
    for (i = 0; i < 4; i++) {
        hex = conv(as[i]);
        printf("%s -> %02x\n", as[i], hex);
    }
    return 0;
}

かずま

Re: ASCII → HEX 変換について

#3

投稿記事 by かずま » 13年前

かずま さんが書きました:

コード:

#define conv2(x) (((x) >> 6 & 1) * 9 + (x) & 15)
やっぱり、次のほうがオブジェクトが短くなりますね。

コード:

#define conv2(x) (((x) & 64 ? (x) + 9 : (x)) & 15)

たかぎ
記事: 328
登録日時: 14年前
住所: 大阪
連絡を取る:

Re: ASCII → HEX 変換について

#4

投稿記事 by たかぎ » 13年前

この手のものは、速度優先なのか、サイズ優先なのか、可読性優先なのか、移植性優先なのかをはっきりさせる必要があります。
速度やサイズを優先するのであれば、プロセッサやコンパイラを明記してください。
また、すでに指摘があるのように、エラーチェックをどの程度行うのかによっては話が変わってきます。

かずま

Re: ASCII → HEX 変換について

#5

投稿記事 by かずま » 13年前

たかぎ さんが書きました:この手のものは、速度優先なのか、サイズ優先なのか、可読性優先なのか、移植性優先なのかをはっきりさせる必要があります。
速度やサイズを優先するのであれば、プロセッサやコンパイラを明記してください。
ごもっとも。

元の質問に「組み込み分野で使用する為」とあるので、サイズが重要かなと思っていましたが、
よく考えると、マクロを展開したらコードが大きくなりますね。
かと言って、関数にすると入口と出口のコードがオーバヘッドとなります。
やっぱり、ループにするほうがよいと考え直して、次のように書き換えてみました。

コード:

int conv(const char *s)
{
    int c, v = 0;
    while (c = *s++)
        v = (c & 0x10 ? c : c + 9) & 0x0f | (v << 4);
    return v;
}

#include <stdio.h>

int main(void)
{
    char as[4][3] = {
        { 0x31, 0x32, 0 },
        { 0x41, 0x42, 0 },
        { 0x65, 0x66, 0 },
        { 0x43, 0x39, 0 },
    };
    int i;
    unsigned char hex;
    for (i = 0; i < 4; i++) {
        hex = conv(as[i]);
        printf("%s -> %02x\n", as[i], hex);
    }
    return 0;
}
バージョンは、gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3
$ gcc -c -Os x.c
$ objdump -d x.o

コード:

x.o:     file format elf32-i386


Disassembly of section .text:

00000000 <conv>:
   0:   55                      push   %ebp
   1:   31 c0                   xor    %eax,%eax
   3:   89 e5                   mov    %esp,%ebp
   5:   8b 4d 08                mov    0x8(%ebp),%ecx
   8:   eb 10                   jmp    1a <conv+0x1a>
   a:   f6 c2 10                test   $0x10,%dl
   d:   75 03                   jne    12 <conv+0x12>
   f:   83 c2 09                add    $0x9,%edx
  12:   83 e2 0f                and    $0xf,%edx
  15:   c1 e0 04                shl    $0x4,%eax
  18:   09 d0                   or     %edx,%eax
  1a:   0f be 11                movsbl (%ecx),%edx
  1d:   41                      inc    %ecx
  1e:   85 d2                   test   %edx,%edx
  20:   75 e8                   jne    a <conv+0xa>
  22:   5d                      pop    %ebp
  23:   c3                      ret    
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
C:\tmp>cl -c -O1 x.c
C:\tmp>dumpbin /disasm x.obj

コード:

Microsoft (R) COFF/PE Dumper Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file x.obj

File Type: COFF OBJECT

_conv:
  00000000: 8B 54 24 04        mov         edx,dword ptr [esp+4]
  00000004: 33 C0              xor         eax,eax
  00000006: EB 13              jmp         0000001B
  00000008: 42                 inc         edx
  00000009: F6 C1 10           test        cl,10h
  0000000C: 75 03              jne         00000011
  0000000E: 83 C1 09           add         ecx,9
  00000011: C1 E0 04           shl         eax,4
  00000014: 83 E1 0F           and         ecx,0Fh
  00000017: 0B C8              or          ecx,eax
  00000019: 8B C1              mov         eax,ecx
  0000001B: 0F BE 0A           movsx       ecx,byte ptr [edx]
  0000001E: 85 C9              test        ecx,ecx
  00000020: 75 E6              jne         00000008
  00000022: C3                 ret

たかぎ
記事: 328
登録日時: 14年前
住所: 大阪
連絡を取る:

Re: ASCII → HEX 変換について

#6

投稿記事 by たかぎ » 13年前

比較的ローエンドのマイコンで速度優先にするのであれば、次のように表引きにしてもよいでしょう。

コード:

int ascii_to_hex(const char *s)
{
    static const char table[256] =
    {
    	['0'] = 0,
    	['1'] = 1,
    	['2'] = 2,
    	['3'] = 3,
    	['4'] = 4,
    	['5'] = 5,
    	['6'] = 6,
    	['7'] = 7,
    	['8'] = 8,
    	['9'] = 9,
    	['A'] = 10,
    	['B'] = 11,
    	['C'] = 12,
    	['D'] = 13,
    	['E'] = 14,
    	['F'] = 15,
    	['a'] = 10,
    	['b'] = 11,
    	['c'] = 12,
    	['d'] = 13,
    	['e'] = 14,
    	['f'] = 15,
    };
    int result = 0;
    int c;

    for (const char *ss = s; (c = (unsigned char)*ss) != '\0'; ss++)
    {
        result = (result << 4) + table[c];
    }
    return result;
}
ただし、M16Cのように、far領域のメモリアクセスが遅い場合には逆効果になることがあります。
データキャッシュやパイプライン等があるプロセッサでは、ケースバイケースですので一概には言えません。

閉鎖

“C言語何でも質問掲示板” へ戻る