可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want to convert two ASCII bytes to one hexadecimal byte.
eg.
0x30 0x43 => 0x0C , 0x34 0x46 => 0x4F
...
The ASCII bytes are a number between 0
and 9
or a letter between A
and F
(upper case only), so between 0x30
... 0x39
and 0x41
... 0x46
I know how "to construct" 0x4F
with the numbers 0x34
and 0x46 : 0x4F = 0x34 * 0x10 + 0x46
So, in fact, i would to convert one ASCII byte in hexadecimal value.
For that, i can build and array to assign the hexadecimal value to the ASCII char :
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.
Have you got an idea ?
Thanks
回答1:
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)
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 in
parameter) now contains the 2 bytes 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).
回答2:
You can use strtol()
, which is part of avr-libc, or you can write just your specific case pretty easily:
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]);
}
回答3:
The task:
Convert a string containing hexadecimal ascii characters to its byte values
so ascii "FF"
becomes 0xFF
and ascii "10" (x31x30x00)
becomes 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:
// convert string to upper cases:
stringToUpperCases(asciiString);
use:
void stringToUpperCases(char *p)
{
for(int i=0; *(p+i) !='\0'; i++)
{
*(p+i) = (unsigned char) toupper( *(p+i) );
}
}
//2. Convert a string containing hexadecimal ascii characters to its byte values:
// 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
}
//3. print result:
printNrOfBytes(nrOfBytes, result);
// use:
void printNrOfBytes(int nr, char *p)
{
for(int i= 0; i < nr; i++)
{
printf( "0x%02X ", (unsigned char)*(p+i) );
}
printf( "\n");
}
//4. The result should be:
0xAA 0xAA 0x12 0xFF
//5. This is the test program:
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:
It's works, but could be much optimized !
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;
}
回答5:
Here's a version that works with both upper and lower-case hex strings:
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;
}
}