Làm cách nào để bạn chuyển đổi một mảng byte thành một chuỗi thập lục phân trong C?


88

Tôi có:

uint8 buf[] = {0, 1, 10, 11};

Tôi muốn chuyển đổi mảng byte thành một chuỗi để tôi có thể in chuỗi bằng printf:

printf("%s\n", str);

và nhận được (dấu hai chấm không cần thiết):

"00:01:0A:0B"

Mọi sự trợ giúp sẽ rất được trân trọng.


buf[i]phải được đúc để unsigned char, hoặc nó sẽ tràn nếu buf[i] > 127, đó là:buf_ptr += sprintf(buf_ptr, "%02X", (unsigned char)buf[i]);
whatacold

Câu trả lời:


93
printf("%02X:%02X:%02X:%02X", buf[0], buf[1], buf[2], buf[3]);

cho một cách chung chung hơn:

int i;
for (i = 0; i < x; i++)
{
    if (i > 0) printf(":");
    printf("%02X", buf[i]);
}
printf("\n");

để nối với một chuỗi, có một số cách bạn có thể thực hiện việc này ... tôi có thể giữ một con trỏ đến cuối chuỗi và sử dụng sprintf. bạn cũng nên theo dõi kích thước của mảng để đảm bảo rằng nó không lớn hơn không gian được phân bổ:

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");

Cảm ơn Mark - vấn đề của tôi phức tạp hơn một chút. Tôi thực sự có một bộ đệm với độ dài X byte. Tôi đã hy vọng tìm ra một cách chung để thực hiện việc này cho X byte và kết quả là có một chuỗi.
Steve Walsh

Vừa được cập nhật để thêm mã xử lý bất kỳ số byte nhất định nào ... giả sử x là độ dài.
Mark Synowiec

Cảm ơn Mark một lần nữa, nhưng điều tôi thấy khó khăn nhất cho vấn đề này là làm thế nào để in nó thành một chuỗi.
Steve Walsh

5
printf("%02X", (unsigned char)buf[i]);nên được sử dụng như bản gốc sẽ gây ra tràn cho chars unsigned
easytiger

3
Tại sao không printf("%02hhX", buf[i])?
Hintron

32

Đối với hoàn chỉnh, bạn cũng có thể dễ dàng làm điều đó mà không cần gọi bất kỳ hàm thư viện nặng nào (không có snprintf, không có strcat, thậm chí không phải memcpy). Nó có thể hữu ích, giả sử nếu bạn đang lập trình một số vi điều khiển hoặc nhân hệ điều hành mà libc không có sẵn.

Không có gì thực sự ưa thích, bạn có thể tìm thấy mã tương tự xung quanh nếu bạn google cho nó. Thực sự nó không phức tạp hơn nhiều so với gọi snprintf và nhanh hơn nhiều.

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

Đây là một phiên bản khác ngắn hơn một chút. Nó chỉ tránh biến chỉ số trung gian i và sao chép mã trường hợp laste (nhưng ký tự kết thúc được viết hai lần).

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

Dưới đây là một phiên bản khác để trả lời một bình luận nói rằng tôi đã sử dụng một "thủ thuật" để biết kích thước của bộ đệm đầu vào. Thực ra đó không phải là một thủ thuật mà là một kiến ​​thức đầu vào cần thiết (bạn cần biết kích thước của dữ liệu mà bạn đang chuyển đổi). Tôi đã làm rõ hơn điều này bằng cách trích xuất mã chuyển đổi sang một hàm riêng biệt. Tôi cũng đã thêm mã kiểm tra ranh giới cho bộ đệm đích, điều này không thực sự cần thiết nếu chúng ta biết mình đang làm gì.

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

1
Nó không phải là một thủ thuật, chỉ đơn thuần là một hằng số. Trong ngữ cảnh của câu hỏi, rõ ràng là độ dài của nguồn mà chúng ta muốn chuyển đổi sang hệ thập lục phân đã được biết rõ (tôi có thể đã đặt một số mã cứng 4 thay vì sizeof). Trong trường hợp chung, hàm nên được gọi trên một số đầu vào có độ dài đã biết và bộ đệm đích có sẵn 3 lần + 1 byte. Điều này phải được đảm bảo bởi người gọi, không có lý do gì để hàm chuyển đổi thực hiện nhiệm vụ đó. Gọi strlen () có thể là một cách để tìm kích thước nguồn trong một số trường hợp, nhưng không phải lúc nào cũng vậy. Điều gì sẽ xảy ra nếu số cần chuyển đổi thành hex chứa các số 0?
kriss

Lấy cảm hứng từ chức năng của bạn, tôi đã viết một phiên bản mà cũng trả về số byte ghi vào bộ đệm đầu ra, tương tự như snprintf vv gist.github.com/cellularmitosis/0d8c0abf7f8aa6a2dff3
Jason Pepas

Tôi nghĩ bạn nên tự động tạo bộ đệm đầu ra có kích thước chính xác bằng cách sử dụng char str [sizeof (buf) * 3 + 1];
Cecil Ward,

Ngoài ra còn có nhiều khuyết điểm hơn sẽ bảo vệ bạn. Ví dụ: "const unsigned char const * p" để bạn có thể đảm bảo rằng bộ đệm đầu vào không được ghi vào. Một làm cho địa chỉ (hoặc 'con trỏ') không đổi hoặc biến, và một làm cho bộ nhớ tại địa chỉ đó ở chế độ chỉ đọc hoặc không. Thường khiến bạn không bị lẫn lộn các con trỏ. Ngoài ra, có những cái tên có ý nghĩa ghi lại bộ đệm và con trỏ cho đầu vào và đầu ra cũng sẽ hữu ích.
Cecil Ward,

@Cecil War: trừ khi mã của tôi không có thật bằng cách sử dụng const sẽ không bảo vệ nhiều trừ khi bạn nói trộn các con trỏ hoặc sử dụng cùng một con trỏ cho đầu vào và đầu ra (ok, vẫn có thể). Nhưng nó cũng sẽ giúp trình biên dịch tối ưu hóa mã. Thậm chí tốt hơn là sử dụng từ khóa hạn chế (quá tệ C99 không phải C ++, nhưng thường tồn tại dưới dạng một phần mở rộng trình biên dịch). Bạn muốn gì nhiều hơn khi gọi bộ đệm đầu vào invà bộ đệm đầu ra out? Tôi cũng có thể chọn sử dụng một chuỗi và trả lại một bản sao thay vì cung cấp bộ đệm đầu ra, trong các trình tối ưu hóa C ++ hiện đại đủ tốt để không cần quan tâm nhiều.
kriss

15

Đây là một phương pháp nhanh hơn:

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

3
Mã này chứa một lỗi chỉ xuất hiện trên các đầu vào lạ không thể in được (chưa có thời gian để tìm hiểu chính xác những gì đang xảy ra về mặt toán học). Hãy thử mã hóa hệ nhị phân của hệ thập lục phân ca9e3c972f1c5db40c0b4a66ab5bc1a20ca4457bdbe5e0f8925896d5ed37d726và bạn sẽ nhận ÌaÌe3cÌ72f1c5dÌ40c0b4a66Ìb5bÌ1Ì20cÌ4457bÌbÌ5Ì0Ì8Ì258Ì6Ì5Ìd37Ì726ra. Để khắc phục điều này, bit bên hex_strtrong dòng đầu tiên của vòng lặp for cần được thay đổi thành (input[i] >> 4) & 0x0Fnhư trong câu trả lời của @ kriss. Sau đó, nó hoạt động tốt.
niemiro

Lỗi - không kiểm tra lỗi malloc ().
Cecil Ward,

Tốt hơn hết là sử dụng ký tự không dấu hoàn toàn ở mọi nơi vì không ai muốn rủi ro về ký tự đã ký (một tính năng phần cứng DEC PDP11 điên rồ) và bằng cách đó bạn không có nguy cơ so sánh đã ký bị sai hoặc có ký thay đổi bên phải làm hỏng giá trị. Trong trường hợp này, công bằng mà nói, mã bảo vệ & 0x0F ở mọi nơi để bảo vệ bạn ở đây.
Cecil Ward,

Tham số đầu vào bin phải là const unsigned char const * bin, để khai báo bộ nhớ là chỉ đọc cho các mục đích của quy trình này.
Cecil Ward,

1
Tôi đã tích hợp các kiến nghị của Cecil Phường, nhờ thông tin phản hồi
Yannuth

14

Các câu trả lời tương tự đã tồn tại ở trên, tôi đã thêm câu trả lời này để giải thích cách dòng mã sau hoạt động chính xác:

ptr += sprintf(ptr, "%02X", buf[i])

Nó khá phức tạp và không dễ hiểu, tôi giải thích ở phần bình luận bên dướ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);

Logic tuyệt vời. Đã tìm kiếm một giờ cho một câu trả lời không phải chuỗi C ++ thanh lịch cho thử thách này!
Mark Terrill,

6

Tôi chỉ muốn thêm phần sau, ngay cả khi nó hơi lạc đề (không phải tiêu chuẩn C), nhưng tôi thấy mình thường xuyên tìm kiếm nó và tình cờ gặp câu hỏi này trong số lần truy cập tìm kiếm đầu tiên. Hàm in hạt nhân Linux printk, cũng có các mã định dạng để xuất nội dung mảng / bộ nhớ "trực tiếp" thông qua một mã định dạng số ít:

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(). 

... tuy nhiên, các mã định dạng này dường như không tồn tại cho không gian người dùng, tiêu chuẩn (s)printf.


4

Giải pháp

Chức năng btoxchuyển đổi dữ liệu tùy ý *bbđể một chuỗi unterminated *xpcủa nchữ số thập lục phân:

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

Thí dụ

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

Kết quả: 00010A0B.

Trực tiếp: Tio.run .


1

Đây là một cách để thực hiện chuyển đổi:

#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);

}

1

Phiên bản Yannith sửa đổi một chút. Tôi chỉ muốn có nó như một giá trị trả lại

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


1

Hàm này phù hợp khi người dùng / người gọi muốn chuỗi hex được đặt trong một mảng / bộ đệm đặc trưng. Với chuỗi hex trong bộ đệm ký tự, người dùng / người gọi có thể sử dụng macro / chức năng của riêng nó để hiển thị hoặc đăng nhập nó vào bất kỳ nơi nào họ muốn (ví dụ: vào một tệp). Chức năng này cũng cho phép người gọi kiểm soát số byte (hex) để đưa vào mỗi dòng.

/**
 * @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));

}

Ví dụ: Mã

#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) 

ĐẦU RA

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 

0

Không có nguyên thủy nào cho điều này trong C. Tôi có lẽ sẽ malloc (hoặc có lẽ là alloca) một bộ đệm đủ dài và lặp qua đầu vào. Tôi cũng đã thấy nó được thực hiện với một thư viện chuỗi động với ngữ nghĩa (nhưng không phải cú pháp!) Tương tự như C ++ ostringstream, đây là một giải pháp chung chung hợp lý hơn nhưng nó có thể không đáng để tăng thêm độ phức tạp chỉ đối với một trường hợp đơn lẻ.


0

Nếu bạn muốn lưu trữ các giá trị hex trong một char *chuỗi, bạn có thể sử dụng snprintf. Bạn cần phân bổ không gian cho tất cả các ký tự được in, bao gồm các số 0 ở đầu và dấu hai chấm.

Mở rộng câu trả lời của 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

Vì vậy, bây giờ str_bufsẽ chứa chuỗi hex.


cái này ghi đè 2 ký tự đầu tiên nhiều lần .. phải không?
xordon,

0

Giải pháp của ZincX được điều chỉnh để bao gồm các dấu phân cách ruột kết:

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

0

Tôi sẽ thêm phiên bản C ++ ở đây cho bất kỳ ai quan tâm.

#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.
}

Nó sẽ in hexdump có bufferđộ dài countđến std::ostream out(bạn có thể đặt nó làm mặc định std::cout). Mỗi dòng sẽ chứa các bytes_per_linebyte, mỗi byte được biểu diễn bằng cách viết hoa hai chữ số hex. Sẽ có một khoảng cách giữa các byte. Và ở cuối dòng hoặc cuối bộ đệm, nó sẽ in ra một dòng mới. Nếu bytes_per_lineđược đặt thành 0, thì nó sẽ không in new_line. Cố gắng cho chính mình.


0

Để sử dụng đơn giản, tôi đã tạo một hàm mã hóa chuỗi đầu vào (dữ liệu nhị phân):

/* 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;
}

Sử dụng:

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;

0

Dựa trên câu trả lời của Yannuth nhưng được đơn giản hóa.

Ở đây, chiều dài của dest[]được ngụ ý là gấp đôi lenvà phân bổ của nó được quản lý bởi người gọi.

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

0

Tôi biết câu hỏi này đã có câu trả lời nhưng tôi nghĩ giải pháp của tôi có thể giúp ích cho ai đó.

Vì vậy, trong trường hợp của tôi, tôi có một mảng byte đại diện cho khóa và tôi cần chuyển mảng byte này thành mảng char của các giá trị thập lục phân để in nó ra trong một dòng. Tôi đã trích xuất mã của mình thành một hàm như sau:

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

Bây giờ, tôi có thể sử dụng chức năng của mình như sau:

Serial.print("Public key: ");
Serial.println(keyToStr(m_publicKey));

Serialđối tượng là một phần của thư viện Arduino và m_publicKeylà thành viên của lớp tôi với khai báo sau uint8_t m_publicKey[32].


0

Bạn có thể giải quyết bằng snprintf và 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);

RA: bbccdd0fef0f0e0d0c


-2

Những giải pháp phức tạp!
Malloc và chạy nước rút và lao đi ôi chao. (OZ trích dẫn)
và không có một rem duy nhất ở bất cứ đâu. Gosh

Làm thế nào về một cái gì đó như thế này?

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);

}

OK, bây giờ bạn có hai chữ số hex. Nó vẫn còn để thêm dấu phân cách và chăm sóc các byte khác để chuyển đổi. Có thể với một vòng lặp? Hãy biến nó thành một hàm và bạn sẽ có một cái gì đó tương tự như của tôi (nhưng khá dài dòng và khó đọc). Có lẽ ít nhất bạn nên hoàn thành công việc trước khi gọi tên trên các áp phích khác?
kriss

1
Và một từ về nhận xét trong mã nguồn (không phải từ khóa REM, đó là từ khóa CƠ BẢN cho nhận xét, vui lòng tránh điều đó): các nhận xét nói bằng tiếng Anh những gì mã đang làm là rất tệ! Có, các lập trình viên phải biết các toán tử modulo có nghĩa là gì (cho phần còn lại) và phép chia đó đếm số lần một số xuất hiện trong một số khác ... và printf in ra kết quả. Ôi trời!
kriss
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.