C语言 将两个 ASCII 十六进制字符(两个 ASCII 字节)转换为一个字节

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6933039/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:18:25  来源:igfitidea点击:

Convert two ASCII Hexadecimal Characters (Two ASCII bytes) in one byte

casciihexavr-gcc

提问by Lo?c G.

I want to convert two ASCII bytes to one hexadecimal byte. eg.

我想将两个 ASCII 字节转换为一个十六进制字节。例如。

0x30 0x43 => 0x0C , 0x34 0x46 => 0x4F...

0x30 0x43 => 0x0C , 0x34 0x46 => 0x4F...

The ASCII bytes are a number between 0and 9or a letter between Aand F(upper case only), so between 0x30... 0x39and 0x41... 0x46

ASCII 字节是介于0and之间的数字9或介于Aand之间的字母F(仅限大写),因此介于0x30...0x390x41...0x46

I know how "to construct" 0x4Fwith the numbers 0x34and 0x46 : 0x4F = 0x34 * 0x10 + 0x46

我知道如何0x4F用数字0x340x46 : 0x4F = 0x34 * 0x10 + 0x46

So, in fact, i would to convert one ASCII byte in hexadecimal value.

所以,事实上,我想将一个 ASCII 字节转换为十六进制值。

For that, i can build and array to assign the hexadecimal value to the ASCII char :

为此,我可以构建和数组以将十六进制值分配给 ASCII 字符:

0x30 => 0x00
0x31 => 0x01
...
0x46 => 0x0F

But, maybe it have a most ??proper ??solution.

但是,也许它有一个最合适的解决方案。

The program will be run on an AVR μC and is compiled with avr-gcc, so scanf()/ printf()solutions aren't suitable.

该程序将在 AVR μC 上运行并使用 编译avr-gcc,因此scanf()/printf()解决方案不合适。

Have you got an idea ? Thanks

你有什么想法吗?谢谢

回答by nos

i can't make sense of your examples, but if you want to convert a string containing hexadecimal ascii characters to its byte value (e.g. so the string "56" becomes the byte 0x56, you can use this (which assumes your system is using ASCII)

我无法理解您的示例,但是如果您想将包含十六进制 ascii 字符的字符串转换为其字节值(例如,字符串“56”变为字节 0x56,您可以使用它(假设您的系统正在使用) ASCII)

uint8_t*
hex_decode(const char *in, size_t len,uint8_t *out)
{
        unsigned int i, t, hn, ln;

        for (t = 0,i = 0; i < len; i+=2,++t) {

                hn = in[i] > '9' ? in[i] - 'A' + 10 : in[i] - '0';
                ln = in[i+1] > '9' ? in[i+1] - 'A' + 10 : in[i+1] - '0';

                out[t] = (hn << 4 ) | ln;
        }

        return out;
}

You'd use it like e.g.

你会像这样使用它

char x[]="1234";
uint8_t res[2];
hex_decode(x,strlen(x),res);

And res (which must be at least half the length of the inparameter) now contains the 2 bytes 0x12,0x34

并且 res(必须至少是in参数长度的一半)现在包含 2 个字节 0x12,0x34

Note also that this code needs the hexadecimal letters A-F to be capital, a-f won't do (and it doesn't do any error checking - so you'll have to pass it valid stuff).

另请注意,此代码需要十六进制字母 AF 为大写,af 不会这样做(并且它不进行任何错误检查 - 因此您必须传递有效内容)。

回答by Carl Norum

You can use strtol(), which is part of avr-libc, or you can write just your specific case pretty easily:

您可以使用strtol(),它是avr-libc 的一部分,或者您可以很容易地只编写您的特定案例:

unsigned char charToHexDigit(char c)
{
  if (c >= 'A')
    return c - 'A' + 10;
  else
    return c - '0';
}

unsigned char stringToByte(char c[2])
{
  return charToHexDigit(c[0]) * 16 + charToHexDigit(c[1]);
}

回答by sg7

The task:

任务:

Convert a string containing hexadecimal ascii characters to its byte values so ascii "FF"becomes 0xFFand ascii "10" (x31x30x00)becomes 0x10

将包含十六进制 ascii 字符的字符串转换为其字节值,使 ascii"FF"变为0xFFascii"10" (x31x30x00)变为0x10

char asciiString[]="aaAA12fF";// input ascii hex string 
char result[4];               // byte equivalent of the asciiString (the size should be at half of asciiString[])

// the final result should be:

// 最终结果应该是:

result[0] = 0xAA;
result[1] = 0xAA;       
result[2] = 0x12;
result[3] = 0xFF;

//1. Firt step: convert asciiString so it contains upper cases only:

//1. 第一步:转换 asciiString 使其只包含大写:

// convert string to upper cases:
stringToUpperCases(asciiString);

use:

用:

void stringToUpperCases(char *p)
{   
    for(int i=0; *(p+i) !='
// convert string to bytes:

int nrOfBytes = stringToBytes(asciiString,result);

//use:  
unsigned char charToHexDigit(char c)
{
if (c >= 'A')
    return (c - 'A' + 10);
else
    return (c - '0');
}

unsigned char ascii2HexToByte(char *ptr)
{
    return charToHexDigit( *ptr )*16 + charToHexDigit( *(ptr+1) );
}

int stringToBytes(char *string, char *result)
{
    int k=0;
    int strLen = strlen(string);

    for(int i = 0; i < strLen; i = i + 2)
    {
        result[k] = ascii2HexToByte( &string[i] );
        k++;
    }

    return k; // number of bytes in the result array 
}   
'; i++) { *(p+i) = (unsigned char) toupper( *(p+i) ); } }

//2. Convert a string containing hexadecimal ascii characters to its byte values:

//2. 将包含十六进制 ascii 字符的字符串转换为其字节值:

printNrOfBytes(nrOfBytes, result);

//3. print result:

//3. 打印结果:

void printNrOfBytes(int nr, char *p)
{
   for(int i= 0; i < nr; i++)
    {
        printf( "0x%02X ", (unsigned char)*(p+i) );
    }
    printf( "\n");
}

// use:

// 用:

char asciiString[]="aaAA12fF"; // input ascii hex string 
char result[4];                // result  
// convert string to upper cases:
stringToUpperCases(asciiString);

// convert string to bytes
int nrOfBytes = stringToBytes(asciiString,result);

// print result:
printNrOfBytes(nrOfBytes, result);

// result:
//  0xAA 0xAA 0x12 0xFF

//4. The result should be:

//4. 结果应该是:

0xAA 0xAA 0x12 0xFF

0xAA 0xAA 0x12 0xFF

//5. This is the test program:

//5. 这是测试程序:

inline uint8_t  twoAsciiByteToByte(const std::string& s)
{
    uint8_t r = 0;

    if (s.length() == 4)
    {
        uint8_t a = asciiToByte(s[0]);
        uint8_t b = asciiToByte(s[1]);
        uint8_t c = asciiToByte(s[2]);
        uint8_t d = asciiToByte(s[3]);

        int h = (a * 10 + b);
        int l = (c * 10 + d);

        if (s[0] == '3')
            h -= 30;
        else if (s[0] == '4')
            h -= 31;

        if (s[2] == '3')
            l -= 30;
        else if (s[2] == '4')
            l -= 31;

        r = (h << 4) | l;
    }

    return r;
}

回答by Dmitry

It's works, but could be much optimized !

它有效,但可以优化很多!

void hex_decode(const char *in, size_t len, uint8_t *out)
{
  unsigned int i, hn, ln;
  char hc, lc;

  memset(out, 0, len);

  for (i = 0; i < 2*len; i += 2) {

    hc = in[i];
    if ('a' <= hc && hc <= 'f') hc = toupper(hc);
    lc = in[i+1];
    if ('a' <= lc && lc <= 'f') lc = toupper(lc);

    hn = hc > '9' ? hc - 'A' + 10 : hc - '0';
    ln = lc > '9' ? lc - 'A' + 10 : lc - '0';

    out[i >> 1] = (hn << 4 ) | ln;
  }
}

回答by Sapient Hetero

Here's a version that works with both upper and lower-case hex strings:

这是一个适用于大写和小写十六进制字符串的版本:

a: 0000_1111
b: 1111_0000
-> 1111_1111

回答by Luro02

Converting 2 hex chars to a byte is done in two steps:

将 2 个十六进制字符转换为一个字节分两步完成:

  1. Convert charaand bto their number (e.g. 'F'-> 0xF), which is done in two big if else branches, that check if the char is in the range '0'to '9', 'A'to 'F'or 'a'to 'f'.

  2. In the 2nd step the two numbers are joined by shifting a(largest value is 0xF(0b0000_FFFF)) 4to the left (a << 4-> 0b1111_0000) and then apply the bitwise or operation on aand b((a << 4) | b):

  1. chara和转换b为它们的数字(例如'F'-> 0xF),这在两个大的 if else 分支中完成,检查字符是否在'0'to '9''A'to'F''a'to范围内'f'

  2. 在第 2 步中,通过向左移动a(最大值是0xF( 0b0000_FFFF))4来连接两个数字(a << 4-> 0b1111_0000),然后对ab( (a << 4) | b)应用按位或运算:

#include <stdio.h>
#include <stdint.h>

#define u8 uint8_t
#define u32 uint32_t

u8 to_hex_digit(char a, char b) {
    u8 result = 0;

    if (a >= 0x30 && a <= 0x39) {
        result = (a - 0x30) << 4;
    } else if (a >= 0x41 && a <= 0x46) {
        result = (a - 0x41 + 10) << 4;
    } else if (a >= 0x61 && a <= 0x7A) {
        result = (a - 0x61 + 10) << 4;
    } else {
        printf("invalid hex digit: '%c'\n", a);
    }

    if (b >= 0x30 && b <= 0x39) {
        result |= b - 0x30;
    } else if (b >= 0x41 && b <= 0x46) {
        result |= b - 0x41 + 10;
    } else if (b >= 0x61 && b <= 0x7A) {
        result |= b - 0x61 + 10;
    } else {
        printf("invalid hex digit: '%c'\n", b);
    }

    return result;
}

u32 main() {
    u8 result = to_hex_digit('F', 'F');
    printf("0x%X (%d)\n", result, result);

    return 0;
}
##代码##