如何拆分ASCII字符的hex字节

我基本上想做的是

例如:’a’hex等效数是0x61 ,我可以将61分为61并将它们存储为'6''1'吗?

缓冲区正在接收如下数据:

 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' 

我需要将hex values 0x00,0x31,0x32,0x33转换为char值'0','0','3','1','3','2';'3','3'和将它们存储在tx_buff_data[];的位置tx_buff_data[];

我希望我的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' 

您可以使用按位AND +移位将每个字节分成两个半字节(4位数量):

 unsigned char lo = byte & 0x0f; unsigned char hi = (byte >> 4) & 0x0f; 

然后,您可以通过数组查找将每一半转换为hex字符(因为字符串只是字符数组):

 char loChar = "0123456789ABCDEF"[lo]; char hiChar = "0123456789ABCDEF"[hi]; 

这是一个示例程序,可用作代码的模板

 #include  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; } 

输出是

 00313233 

使用ASCII字符的定义可以实现极其节省时间和代码的解决方案。 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; 

有时小写字母用于’a’到’f’。

因此,如果我们的半字节的值低于10(0000b到1001b),则字符表示将为0x30 + n,或者在c语法中为“0”+ n。
如果n在10到15(1010b到1111b)0x41 + n – 10或’A’+ n-10之间。
使用unsigned int 8bit而不是char类型:

 uint8_t nibble2char( uint8_t n ) { // make sure that ne {0x00,...,0x0F} if( n<10 ) return '0'+n; else return 'A'+n-10; } 

或更短:

 uint8_t nibble2char( uint8_t n ) { // make sure that ne {0x00,...,0x0F} return n<10 ? '0'+n : 'A'+n-10; } 

或者作为一个宏(感谢(n)的chqrlie):

 #define NIBBLE_TO_CHAR(n) ((n)<10 ? '0'+(n) : 'A'+(n)0) // n <= 15 ! 

如果使用小写字母,请将'A'替换​​为'a'。

将带有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; } 

编辑:
通过将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; } 
 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]; } 

我建议你另一种变体,转换固定大小的输入,并检查输出的大小:

 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'; } 

就像微控制器一样,可以避免任何像sprintf()这样的开销。 你可以这样称呼它:

  convert(tx_buff_data, sizeof(tx_buff_data), your_input_buffer, number_of_bytes); 

您可以使用sprintf将整数值转换为字符串,然后从字符串中提取单个字符。

 #include  char *str; sprintf(str, "%02x", 61) char digitLow = str[0]; // '6' char dightHigh = str[1]; // '1' 

转换你可以做:

  uint8_t lo = byte & 0x0F uint8_t hi = (byte >> 4) & 0x0F char loChar = "0123456789ABCDEF"[lo]; char hiChar = "0123456789ABCDEF"[hi];