我有:
uint8 buf[] = {0, 1, 10, 11};
我想将字节数组转换为字符串,以便我可以使用printf打印字符串:
printf("%s\n", str);
获取(冒号不必要):
"00:01:0A:0B"
任何帮助都将不胜感激。printf("%02X:%02X:%02X:%02X", buf[0], buf[1], buf[2], buf[3]);
更通用的方式:
int i;
for (i = 0; i < x; i++)
{
if (i > 0) printf(":");
printf("%02X", buf[i]);
}
printf("\n");
要将字符串连接起来,可以有几种方法。我可能会保留指向字符串末尾的指针并使用sprintf。你还应该跟踪数组的大小,以确保它不会超过分配的空间:
int i;
char* buf2 = stringbuf;
char* endofbuf = stringbuf + sizeof(stringbuf);
for (i = 0; i < x; i++)
{
/* i use 5 here since we are going to add at most
3 chars, need a space for the end '\n' and need
a null terminator */
if (buf2 + 5 < endofbuf)
{
if (i > 0)
{
buf2 += sprintf(buf2, ":");
}
buf2 += sprintf(buf2, "%02X", buf[i]);
}
}
buf2 += sprintf(buf2, "\n");
\0
字节。 - Mr. Shickadanceprintf("%02X", (unsigned char)buf[i]);
,原始代码会导致无符号字符溢出。 - easytigerprintf("%02hhX", buf[i])
? - Hintron为了完整起见,您也可以轻松地在不调用任何重型库函数(无snprintf,无strcat,甚至无memcpy)的情况下执行此操作。如果您正在编写一些微控制器或OS内核程序,并且没有可用的libc,则可能会很有用。
如果您搜索这个问题,您可以找到类似的代码,这并不是什么高级玩意儿。 它确实比调用snprintf简单得多,而且速度更快。
#include <stdio.h>
int main(){
unsigned char buf[] = {0, 1, 10, 11};
/* target buffer should be large enough */
char str[12];
unsigned char * pin = buf;
const char * hex = "0123456789ABCDEF";
char * pout = str;
int i = 0;
for(; i < sizeof(buf)-1; ++i){
*pout++ = hex[(*pin>>4)&0xF];
*pout++ = hex[(*pin++)&0xF];
*pout++ = ':';
}
*pout++ = hex[(*pin>>4)&0xF];
*pout++ = hex[(*pin)&0xF];
*pout = 0;
printf("%s\n", str);
}
这里有另一个稍微更短的版本。它仅仅避免了中间索引变量 i 并且去除了最后一个情况代码的重复(但是终止字符写了两次)。
#include <stdio.h>
int main(){
unsigned char buf[] = {0, 1, 10, 11};
/* target buffer should be large enough */
char str[12];
unsigned char * pin = buf;
const char * hex = "0123456789ABCDEF";
char * pout = str;
for(; pin < buf+sizeof(buf); pout+=3, pin++){
pout[0] = hex[(*pin>>4) & 0xF];
pout[1] = hex[ *pin & 0xF];
pout[2] = ':';
}
pout[-1] = 0;
printf("%s\n", str);
}
以下是另一种回答评论的版本,评论中说我使用了一个“技巧”来知道输入缓冲区的大小,但实际上这不是技巧,而是必要的输入知识(需要知道要转换的数据的大小)。通过将转换代码提取到单独的函数中,我使这一点更加清晰。我还为目标缓冲区添加了边界检查代码,如果我们知道我们在做什么,这并不是真正必要的。
#include <stdio.h>
void tohex(unsigned char * in, size_t insz, char * out, size_t outsz)
{
unsigned char * pin = in;
const char * hex = "0123456789ABCDEF";
char * pout = out;
for(; pin < in+insz; pout +=3, pin++){
pout[0] = hex[(*pin>>4) & 0xF];
pout[1] = hex[ *pin & 0xF];
pout[2] = ':';
if (pout + 3 - out > outsz){
/* Better to truncate output string than overflow buffer */
/* it would be still better to either return a status */
/* or ensure the target buffer is large enough and it never happen */
break;
}
}
pout[-1] = 0;
}
int main(){
enum {insz = 4, outsz = 3*insz};
unsigned char buf[] = {0, 1, 10, 11};
char str[outsz];
tohex(buf, insz, str, outsz);
printf("%s\n", str);
}
以上已经有类似的答案了,我之所以添加这个答案是为了解释下面这行代码的具体工作原理:
ptr += sprintf(ptr, "%02X", buf[i])
这个问题有点棘手,理解起来并不容易。我将解释放在下面的注释中:
uint8 buf[] = {0, 1, 10, 11};
/* Allocate twice the number of bytes in the "buf" array because each byte would
* be converted to two hex characters, also add an extra space for the terminating
* null byte.
* [size] is the size of the buf array */
char output[(size * 2) + 1];
/* pointer to the first item (0 index) of the output array */
char *ptr = &output[0];
int i;
for (i = 0; i < size; i++) {
/* "sprintf" converts each byte in the "buf" array into a 2 hex string
* characters appended with a null byte, for example 10 => "0A\0".
*
* This string would then be added to the output array starting from the
* position pointed at by "ptr". For example if "ptr" is pointing at the 0
* index then "0A\0" would be written as output[0] = '0', output[1] = 'A' and
* output[2] = '\0'.
*
* "sprintf" returns the number of chars in its output excluding the null
* byte, in our case this would be 2. So we move the "ptr" location two
* steps ahead so that the next hex string would be written at the new
* location, overriding the null byte from the previous hex string.
*
* We don't need to add a terminating null byte because it's been already
* added for us from the last hex string. */
ptr += sprintf(ptr, "%02X", buf[i]);
}
printf("%s\n", output);
这里有一种方法,速度要快得多:
#include <stdlib.h>
#include <stdio.h>
unsigned char * bin_to_strhex(const unsigned char *bin, unsigned int binsz,
unsigned char **result)
{
unsigned char hex_str[]= "0123456789abcdef";
unsigned int i;
if (!(*result = (unsigned char *)malloc(binsz * 2 + 1)))
return (NULL);
(*result)[binsz * 2] = 0;
if (!binsz)
return (NULL);
for (i = 0; i < binsz; i++)
{
(*result)[i * 2 + 0] = hex_str[(bin[i] >> 4) & 0x0F];
(*result)[i * 2 + 1] = hex_str[(bin[i] ) & 0x0F];
}
return (*result);
}
int main()
{
//the calling
unsigned char buf[] = {0,1,10,11};
unsigned char * result;
printf("result : %s\n", bin_to_strhex((unsigned char *)buf, sizeof(buf), &result));
free(result);
return 0
}
ca9e3c972f1c5db40c0b4a66ab5bc1a20ca4457bdbe5e0f8925896d5ed37d726
进行二进制编码,你会得到 ÌaÌe3cÌ72f1c5dÌ40c0b4a66Ìb5bÌ1Ì20cÌ4457bÌbÌ5Ì0Ì8Ì258Ì6Ì5Ìd37Ì726
的输出。要修复这个问题,需要将循环的第一行中 hex_str
内部的位改为 (input[i] >> 4) & 0x0F
,就像 @kriss 的答案一样。这样就可以正常工作了。 - niemirobtox
函数将任意数据*bb
转换为一个由n
个十六进制数字组成的未终止字符串*xp
:
void btox(char *xp, const char *bb, int n)
{
const char xx[]= "0123456789ABCDEF";
while (--n >= 0) xp[n] = xx[(bb[n>>1] >> ((1 - (n&1)) << 2)) & 0xF];
}
#include <stdio.h>
typedef unsigned char uint8;
void main(void)
{
uint8 buf[] = {0, 1, 10, 11};
int n = sizeof buf << 1;
char hexstr[n + 1];
btox(hexstr, buf, n);
hexstr[n] = 0; /* Terminate! */
printf("%s\n", hexstr);
}
结果:00010A0B
。
实时运行:Tio.run。
printk
也具有格式说明符,可以通过单个格式说明符“直接”输出数组/内存内容:
https://www.kernel.org/doc/Documentation/printk-formats.txt
Raw buffer as a hex string:
%*ph 00 01 02 ... 3f
%*phC 00:01:02: ... :3f
%*phD 00-01-02- ... -3f
%*phN 000102 ... 3f
For printing a small buffers (up to 64 bytes long) as a hex string with
certain separator. For the larger buffers consider to use
print_hex_dump().
(s)printf
中。基于 Yannuth 的 答案,但简化了。
这里,dest[]
的长度暗示为len
的两倍,并且其分配由调用者管理。
void create_hex_string_implied(const unsigned char *src, size_t len, unsigned char *dest)
{
static const unsigned char table[] = "0123456789abcdef";
for (; len > 0; --len)
{
unsigned char c = *src++;
*dest++ = table[c >> 4];
*dest++ = table[c & 0x0f];
}
}
#include<stdio.h>
#include<stdlib.h>
#define l_word 15
#define u_word 240
char *hex_str[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
main(int argc,char *argv[]) {
char *str = malloc(50);
char *tmp;
char *tmp2;
int i=0;
while( i < (argc-1)) {
tmp = hex_str[*(argv[i]) & l_word];
tmp2 = hex_str[*(argv[i]) & u_word];
if(i == 0) { memcpy(str,tmp2,1); strcat(str,tmp);}
else { strcat(str,tmp2); strcat(str,tmp);}
i++;
}
printf("\n********* %s *************** \n", str);
}
typedef struct {
size_t len;
uint8_t *bytes;
} vdata;
char* vdata_get_hex(const vdata data)
{
char hex_str[]= "0123456789abcdef";
char* out;
out = (char *)malloc(data.len * 2 + 1);
(out)[data.len * 2] = 0;
if (!data.len) return NULL;
for (size_t i = 0; i < data.len; i++) {
(out)[i * 2 + 0] = hex_str[(data.bytes[i] >> 4) & 0x0F];
(out)[i * 2 + 1] = hex_str[(data.bytes[i] ) & 0x0F];
}
return out;
}
/**
* @fn
* get_hex
*
* @brief
* Converts a char into bunary string
*
* @param[in]
* buf Value to be converted to hex string
* @param[in]
* buf_len Length of the buffer
* @param[in]
* hex_ Pointer to space to put Hex string into
* @param[in]
* hex_len Length of the hex string space
* @param[in]
* num_col Number of columns in display hex string
* @param[out]
* hex_ Contains the hex string
* @return void
*/
static inline void
get_hex(char *buf, int buf_len, char* hex_, int hex_len, int num_col)
{
int i;
#define ONE_BYTE_HEX_STRING_SIZE 3
unsigned int byte_no = 0;
if (buf_len <= 0) {
if (hex_len > 0) {
hex_[0] = '\0';
}
return;
}
if(hex_len < ONE_BYTE_HEX_STRING_SIZE + 1)
{
return;
}
do {
for (i = 0; ((i < num_col) && (buf_len > 0) && (hex_len > 0)); ++i )
{
snprintf(hex_, hex_len, "%02X ", buf[byte_no++] & 0xff);
hex_ += ONE_BYTE_HEX_STRING_SIZE;
hex_len -=ONE_BYTE_HEX_STRING_SIZE;
buf_len--;
}
if (buf_len > 1)
{
snprintf(hex_, hex_len, "\n");
hex_ += 1;
}
} while ((buf_len) > 0 && (hex_len > 0));
}
代码
#define DATA_HEX_STR_LEN 5000
char data_hex_str[DATA_HEX_STR_LEN];
get_hex(pkt, pkt_len, data_hex_str, DATA_HEX_STR_LEN, 16);
// ^^^^^^^^^^^^ ^^
// Input byte array Number of (hex) byte
// to be converted to hex string columns in hex string
printf("pkt:\n%s",data_hex_str)
输出
pkt:
BB 31 32 00 00 00 00 00 FF FF FF FF FF FF DE E5
A8 E2 8E C1 08 06 00 01 08 00 06 04 00 01 DE E5
A8 E2 8E C1 67 1E 5A 02 00 00 00 00 00 00 67 1E
5A 01
buf[i]
must be casted tounsigned char
, or it will overflow ifbuf[i] > 127
, that is:buf_ptr += sprintf(buf_ptr, "%02X", (unsigned char)buf[i]);
- whatacold