我有:
uint8 buf[] = {0, 1, 10, 11};
我想将字节数组转换为字符串,以便我可以使用printf打印字符串:
printf("%s\n", str);
获取(冒号不必要):
"00:01:0A:0B"
任何帮助都将不胜感激。你可以使用snprintf和malloc解决问题。
char c_buff[50];
u8_number_val[] = { 0xbb, 0xcc, 0xdd, 0x0f, 0xef, 0x0f, 0x0e, 0x0d, 0x0c };
char *s_temp = malloc(u8_size * 2 + 1);
for (uint8_t i = 0; i < u8_size; i++)
{
snprintf(s_temp + i * 2, 3, "%02x", u8_number_val[i]);
}
snprintf(c_buff, strlen(s_temp)+1, "%s", s_temp );
printf("%s\n",c_buff);
free(s);
bbccdd0fef0f0e0d0c
我知道这个问题已经有答案了,但我认为我的解决方案可能会对某些人有所帮助。
在我的情况下,我有一个表示密钥的字节数组,并且我需要将这个字节数组转换为十六进制值的字符数组,以便在一行中打印出来。我将我的代码提取到一个函数中,像这样:
char const * keyToStr(uint8_t const *key)
{
uint8_t offset = 0;
static char keyStr[2 * KEY_SIZE + 1];
for (size_t i = 0; i < KEY_SIZE; i++)
{
offset += sprintf(keyStr + offset, "%02X", key[i]);
}
sprintf(keyStr + offset, "%c", '\0');
return keyStr;
}
Serial.print("Public key: ");
Serial.println(keyToStr(m_publicKey));
Serial
对象是Arduino库的一部分,m_publicKey
是我的类的成员,具有以下声明:uint8_t m_publicKey[32]
。
ZincX的解决方案已经适配包含冒号分隔符:
char buf[] = {0,1,10,11};
int i, size = sizeof(buf) / sizeof(char);
char *buf_str = (char*) malloc(3 * size), *buf_ptr = buf_str;
if (buf_str) {
for (i = 0; i < size; i++)
buf_ptr += sprintf(buf_ptr, i < size - 1 ? "%02X:" : "%02X\0", buf[i]);
printf("%s\n", buf_str);
free(buf_str);
}
我会在这里添加C++版本,供有兴趣的人参考。
#include <iostream>
#include <iomanip>
inline void print_bytes(char const * buffer, std::size_t count, std::size_t bytes_per_line, std::ostream & out) {
std::ios::fmtflags flags(out.flags()); // Save flags before manipulation.
out << std::hex << std::setfill('0');
out.setf(std::ios::uppercase);
for (std::size_t i = 0; i != count; ++i) {
auto current_byte_number = static_cast<unsigned int>(static_cast<unsigned char>(buffer[i]));
out << std::setw(2) << current_byte_number;
bool is_end_of_line = (bytes_per_line != 0) && ((i + 1 == count) || ((i + 1) % bytes_per_line == 0));
out << (is_end_of_line ? '\n' : ' ');
}
out.flush();
out.flags(flags); // Restore original flags.
}
它将打印长度为count
的buffer
的十六进制转储到std::ostream
out
(您可以将其默认设置为std::cout
)。每行将包含bytes_per_line
字节,每个字节都用大写两位十六进制表示。字节之间会有一个空格。在行尾或缓冲区末尾,它将打印一个换行符。如果将bytes_per_line
设置为0,则不会打印新行。请自行尝试。
为了简单使用,我编写了一个函数来对输入的字符串(二进制数据)进行编码:
/* Encodes string to hexadecimal string reprsentation
Allocates a new memory for supplied lpszOut that needs to be deleted after use
Fills the supplied lpszOut with hexadecimal representation of the input
*/
void StringToHex(unsigned char *szInput, size_t size_szInput, char **lpszOut)
{
unsigned char *pin = szInput;
const char *hex = "0123456789ABCDEF";
size_t outSize = size_szInput * 2 + 2;
*lpszOut = new char[outSize];
char *pout = *lpszOut;
for (; pin < szInput + size_szInput; pout += 2, pin++)
{
pout[0] = hex[(*pin >> 4) & 0xF];
pout[1] = hex[*pin & 0xF];
}
pout[0] = 0;
}
使用方法:
unsigned char input[] = "This is a very long string that I want to encode";
char *szHexEncoded = NULL;
StringToHex(input, strlen((const char *)input), &szHexEncoded);
printf(szHexEncoded);
// The allocated memory needs to be deleted after usage
delete[] szHexEncoded;
ostringstream
,这是一种更通用的解决方案,但仅针对单个情况可能并不值得增加额外的复杂性。/**
* @brief Convert an arbitrary length byte array to a hex representation
*
* @param bytes
* @param array_length
* @param output
*/
void bytes_to_hex(uint8_t *bytes, uint8_t array_length, char *output)
{
for (int i = 0, j = 0; i < array_length; i++, j+=2)
{
uint8_t bottom = bytes[i] % 16;
uint8_t top = bytes[i] / 16;
output[j] = (top > 9 ? 'A' - 10 : '0') + top;
output[j+1] = (bottom > 9 ? 'A' - 10 : '0') + bottom;
}
}
如果您想将十六进制值存储在char *
字符串中,可以使用snprintf
。您需要为所有打印的字符分配空间,包括前导零和冒号。
扩展Mark的答案:
char str_buf* = malloc(3*X + 1); // X is the number of bytes to be converted
int i;
for (i = 0; i < x; i++)
{
if (i > 0) snprintf(str_buf, 1, ":");
snprintf(str_buf, 2, "%02X", num_buf[i]); // need 2 characters for a single hex value
}
snprintf(str_buf, 2, "\n\0"); // dont forget the NULL byte
现在str_buf
将包含十六进制字符串。
这些是多么复杂的解决方案啊!
Malloc、sprints和casts,哦,我的天。(来自OZ的引用)
丝毫没有任何遗漏。哇
那么像这样怎么样?
main()
{
// the value
int value = 16;
// create a string array with a '\0' ending ie. 0,0,0
char hex[]= {0,0,'\0'};
char *hex_p=hex;
//a working variable
int TEMP_int=0;
// get me how many 16s are in this code
TEMP_int=value/16;
// load the first character up with
// 48+0 gives you ascii 0, 55+10 gives you ascii A
if (TEMP_int<10) {*hex_p=48+TEMP_int;}
else {*hex_p=55+TEMP_int;}
// move that pointer to the next (less significant byte)<BR>
hex_p++;
// get me the remainder after I have divied by 16
TEMP_int=value%16;
// 48+0 gives you ascii 0, 55+10 gives you ascii A
if (TEMP_int<10) {*hex_p=48+TEMP_int;}
else {*hex_p=55+TEMP_int;}
// print the result
printf("%i , 0x%s",value,hex);
}
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