[英]How to split hex byte of an ASCII character
What basically i want to do is 我基本上想做的是
For eg: 'a' hex equivalant is 0x61
, can i split 61
in to 6
and 1
and store them as '6'
and '1'
? 例如:'a'hex hexalant是
0x61
,我可以将61
分为6
和1
并将它们存储为'6'
和'1'
吗?
A buffer is receiving data like this: 缓冲区正在接收如下数据:
rx_dataframe.data[0] is H'00,'.'// H' is Hex equivalant and '' is ASCII value
rx_dataframe.data[0] is H'31,'1'
rx_dataframe.data[0] is H'32,'2'
rx_dataframe.data[0] is H'33,'3'
I need to to convert hex values 0x00,0x31,0x32,0x33
in to char value '0','0','3','1','3','2';'3','3'
and to store them at the locations of tx_buff_data[];
我需要将
hex values 0x00,0x31,0x32,0x33
转换为char值'0','0','3','1','3','2';'3','3'
和将它们存储在tx_buff_data[];
的位置tx_buff_data[];
I want my tx_buff_data
look like this 我希望我的
tx_buff_data
看起来像这样
tx_buff_data[0] have H'30,'0'
tx_buff_data[1] have H'30,'0'
tx_buff_data[2] have H'33,'3'
tx_buff_data[3] have H'31,'1'
tx_buff_data[4] have H'33,'3'
tx_buff_data[5] have H'32,'2'
tx_buff_data[6] have H'33,'3'
tx_buff_data[7] have H'33,'3'
You can split each byte into two nibbles (4-bit quantities) using bitwise AND + shifts: 您可以使用按位AND +移位将每个字节分成两个半字节(4位数量):
unsigned char lo = byte & 0x0f;
unsigned char hi = (byte >> 4) & 0x0f;
Then, you can convert each half into a hex character by an array lookup (since strings are just character arrays): 然后,您可以通过数组查找将每一半转换为十六进制字符(因为字符串只是字符数组):
char loChar = "0123456789ABCDEF"[lo];
char hiChar = "0123456789ABCDEF"[hi];
Here is a sample program that can be used as a template for your code 这是一个示例程序,可用作代码的模板
#include <stdio.h>
int main(void)
{
char in[] = { '\0', '1', '2', '3' };
char out[2 * sizeof( in )];
size_t i;
char *p;
p = out;
for ( i = 0; i < sizeof( in ) / sizeof( *in ); i++ )
{
*p = ( ( unsigned char )in[i] & 0xF0 ) >> 4;
*p +=( *p < 10 ) ? '0' : 'A' - 10;
++p;
*p = ( ( unsigned char )in[i] & 0x0F );
*p +=( *p < 10 ) ? '0' : 'A' - 10;
++p;
}
for ( i = 0; i < sizeof( out ) / sizeof( *out ); i++ )
{
printf( "%c", out[i] );
}
puts( "" );
return 0;
}
The output is 输出是
00313233
Using the definition of the ASCII characters leads to an extremely time- and code saving solution. 使用ASCII字符的定义可以实现极其节省时间和代码的解决方案。 The ASCII-table shows that
ASCII表显示了这一点
values 0... 9 <=> figures '0'...'9' <=> 0x30...0x39 in ASCII code;
values 10...15 <=> figures 'A'...'F' <=> 0x41...0x46 in ASCII code;
or 'a'...'f' <=> 0x61...0x66 in ASCII code;
Sometimes lower case letters are used for 'a' to 'f'. 有时小写字母用于'a'到'f'。
So if the value of our nibble is below 10 (0000b to 1001b) the character representation would be 0x30 + n or, in c-syntax '0'+n. 因此,如果我们的半字节的值低于10(0000b到1001b),则字符表示将是0x30 + n,或者在c语法'0'+ n中。
If n is between 10 and 15 (1010b to 1111b) 0x41 + n - 10 or 'A'+n-10. 如果n在10到15(1010b到1111b)0x41 + n - 10或'A'+ n-10之间。
Using unsigned int 8bit instead of type char: 使用unsigned int 8bit而不是char类型:
uint8_t nibble2char( uint8_t n ) {
// make sure that n e {0x00,...,0x0F}
if( n<10 ) return '0'+n;
else return 'A'+n-10;
}
or shorter: 或更短:
uint8_t nibble2char( uint8_t n ) {
// make sure that n e {0x00,...,0x0F}
return n<10 ? '0'+n : 'A'+n-10;
}
or as a macro (thanks to chqrlie for the (n) ): 或者作为宏(感谢(n)的chqrlie):
#define NIBBLE_TO_CHAR(n) ((n)<10 ? '0'+(n) : 'A'+(n)0) // n <= 15 !
If lower case letters should be used replace 'A' by 'a'. 如果使用小写字母,请将'A'替换为'a'。
Converting a byte with 2 nibbles to a 2-byte 0-terminated string you could use: 将带有2个半字节的字节转换为2字节的0终止字符串,您可以使用:
void byte2str( uint8_t* s, uint8_t n ) {
// s points to a string of at least 3 Bytes length !
uint8_t hi = ( n >> 4 ) & 0x0F ;
uint8_t lo = n & 0x0F ;
s[0] = NIBBLE_TO_CHAR( hi ); // high byte
s[1] = NIBBLE_TO_CHAR( lo ); // low byte
s[2] = 0;
}
EDIT: 编辑:
With correction of chqrlie to the macro, the function becomes more compact: 通过将chqrlie校正到宏,函数变得更紧凑:
void byte2str( uint8_t* s, uint8_t n ) {
// s points to a string of at least 3 Bytes length !
s[0] = NIBBLE_TO_CHAR( ( n >> 4 ) & 0x0F ); // high byte
s[1] = NIBBLE_TO_CHAR( n & 0x0F ); // low byte
s[2] = 0;
}
to convert you can do: 转换你可以做:
uint8_t lo = byte & 0x0F
uint8_t hi = (byte >> 4) & 0x0F
char loChar = "0123456789ABCDEF"[lo];
char hiChar = "0123456789ABCDEF"[hi];
for(int i = 0, j = 0; i < data_input_size; i++, j += 2)
{
int value = rx_dataframe.data[i];
char str[10]; // really only need 3 but extra space in case of bugs
sprintf(str, "%02X", value);
tx_buff_data[j] = str[0];
tx_buff_data[j + 1] = str[1];
}
You can use sprintf to convert an integer value to a string, from the string you can then extract the individual chars. 您可以使用sprintf将整数值转换为字符串,然后从字符串中提取单个字符。
#include <stdlib.h>
char *str;
sprintf(str, "%02x", 61)
char digitLow = str[0]; // '6'
char dightHigh = str[1]; // '1'
I propose you another variant, doing conversion of a fixed size input, and checking the size of the output: 我建议你另一种变体,转换固定大小的输入,并检查输出的大小:
void convert(char *output, int size_out, char *input, int size_in)
{
static char hexdigit[] = "0123456789ABCDEF";
while (size_in-- && size_out>2) { // if not enough space, truncate
*output++ = hexdigit[(*input >> 4) & 0x0F]; // because char could be signed
*output++ = hexdigit[*input & 0x0F];
input++;
size_out -= 2;
}
*output++ = '\0';
}
As it is for a microcontroper, any overhead like sprintf() is avoided. 就像微控制器一样,可以避免任何像sprintf()这样的开销。 You can call it like this:
你可以这样称呼它:
convert(tx_buff_data, sizeof(tx_buff_data), your_input_buffer, number_of_bytes);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.