[英]Convert two ASCII Hexadecimal Characters (Two ASCII bytes) in one byte
我想將兩個 ASCII 字節轉換為一個十六進制字節。 例如。
0x30 0x43 => 0x0C , 0x34 0x46 => 0x4F
...
ASCII 字節是0
到9
之間的數字或A
和F
之間的字母(僅限大寫),因此介於0x30
... 0x39
和0x41
... 0x46
我知道如何用數字0x34
和0x46 : 0x4F = 0x34 * 0x10 + 0x46
來“構建” 0x4F
0x46 : 0x4F = 0x34 * 0x10 + 0x46
所以,事實上,我想將一個 ASCII 字節轉換為十六進制值。
為此,我可以構建和數組以將十六進制值分配給 ASCII 字符:
0x30 => 0x00
0x31 => 0x01
...
0x46 => 0x0F
但是,也許它有一個最“適當”的解決方案。
該程序將在 AVR µC 上運行並使用avr-gcc
,因此scanf()
/ printf()
解決方案不合適。
你有什么想法嗎? 謝謝
我無法理解您的示例,但是如果您想將包含十六進制 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;
}
你會像這樣使用它
char x[]="1234";
uint8_t res[2];
hex_decode(x,strlen(x),res);
並且 res(必須至少是in
參數長度的一半)現在包含 2 個字節 0x12,0x34
另請注意,此代碼需要十六進制字母 AF 為大寫,af 不會這樣做(並且它不進行任何錯誤檢查 - 因此您必須傳遞有效內容)。
您可以使用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]);
}
任務:
將包含十六進制 ascii 字符的字符串轉換為其字節值,使 ascii "FF"
變為0xFF
而 ascii "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[])
// 最終結果應該是:
result[0] = 0xAA;
result[1] = 0xAA;
result[2] = 0x12;
result[3] = 0xFF;
//1. 第一步:轉換 asciiString 使其只包含大寫:
// convert string to upper cases:
stringToUpperCases(asciiString);
采用:
void stringToUpperCases(char *p)
{
for(int i=0; *(p+i) !='\0'; i++)
{
*(p+i) = (unsigned char) toupper( *(p+i) );
}
}
//2. 將包含十六進制 ascii 字符的字符串轉換為其字節值:
// 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. 打印結果:
printNrOfBytes(nrOfBytes, result);
// 采用:
void printNrOfBytes(int nr, char *p)
{
for(int i= 0; i < nr; i++)
{
printf( "0x%02X ", (unsigned char)*(p+i) );
}
printf( "\n");
}
//4. 結果應該是:
0xAA 0xAA 0x12 0xFF
//5. 這是測試程序:
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
它有效,但可以優化很多!
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;
}
這是一個適用於大寫和小寫十六進制字符串的版本:
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;
}
}
將 2 個十六進制字符轉換為一個字節分兩步完成:
將char
a
和b
轉換為它們的數字(例如'F'
-> 0xF
),這在兩個大的 if else 分支中完成,檢查字符是否在'0'
到'9'
, 'A'
到'F'
或'a'
到'f'
。
在第二步中,這兩個數字通過將a
(最大值是0xF
( 0b0000_FFFF
)) 4
向左移動( a << 4
-> 0b1111_0000
)來連接,然后對a
和b
應用按位或運算( (a << 4) | b
):
a: 0000_1111
b: 1111_0000
-> 1111_1111
#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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.