【问题标题】:Convert hex values to char array in C在C中将十六进制值转换为char数组
【发布时间】:2011-10-09 17:24:06
【问题描述】:

我正在尝试实现一个返回一串十六进制值的函数。我使用这个函数打印出十六进制值:

void print_hex(unsigned char *hash, const hashid type) {

    int i;
    for (i = 0; i < mhash_get_block_size(type); i++) {
        printf("%.2x", hex[i]);
    }
    printf("\n");
}

这会输出一些十六进制值,例如71c092a79cf30c4c7e7baf46a4af3c78cedec9ae3867d1e2600ffc39d58beaf2

如何修改此函数以使其返回字符串?即

unsigned char *get_hash_str(unsigned char *hash, const hashid type) { /* ?? */ }

(目标是稍后比较这两个值)

【问题讨论】:

  • 您可能应该使用:int n = mhash_get_block_size(type);,然后是 for (int i = 0; i &lt; n; i++)(或者,如果您坚持使用 C89,则在循环外声明 i)。

标签: c hash hex format-specifiers


【解决方案1】:
char * print_hex(const unsigned char *hash, const hashid type)
{
    const char lookupTable[]="0123456789abcdef";
    const size_t hashLength=mhash_get_block_size(type);
    size_t i;
    char * out=malloc(hashLength*2+1);
    if(out==NULL)
        return NULL;
    for (i = 0; i < hashLength; i++)
    {
        out[i*2]=lookupTable[hash[i]>>4];
        out[i*2+1]=lookupTable[hash[i]&0xf];
    }
    out[hashLength*2]=0;
    return out;
}

显然调用者负责freeing 返回的字符串。

不过,正如@K-Ballo 在他的回答中正确所说,您不需要将两个哈希值转换为字符串形式来比较它们,在这种情况下您只需要一个 memcmp

int compare_hashes(const unsigned char * hash1, const hashid hash1type, const unsigned char * hash2, const hashid hash2type)
{
    if(hash1type!=hash2type)
        return 0;
    return memcmp(hash1, hash2, mhash_get_block_size(hash1type))==0;
}

【讨论】:

  • 冠军!正是我要找的东西 - 谢谢 :) 我需要以这种方式比较它们的原因(我忘了提及)是它们最初使用十六进制存储在一个文件中。
  • @destructo_gold:谢谢,但它们最初以十六进制存储的事实并不相关,比较将是相同的,无论它们是作为十六进制字符串还是作为原始字节进行比较。
【解决方案2】:

如何修改这个函数,让它返回一个字符串?

您可以使用sprintf 打印到字符串变量。我假设哈希大小是固定的,所以你知道你的字符串的大小是number-of-chars-in-hash * 2 + 1。如何返回该信息是 C 中的一个典型问题,您可以将用户必须记住的 malloced 字符串返回到 free,或者返回将被下一次调用函数替换的静态字符串 (并使函数不可重入)。就我个人而言,我倾向于避免返回字符串,而是让函数采用 char* 目标和大小。

(目标是我以后可以比较这两个值)

只需比较原始形式的两个哈希变量,您不需要字符串。

【讨论】:

    【解决方案3】:

    sprintf() 函数与printf() 做同样的事情,除了它“打印”到一个字符缓冲区。这样,您的函数可能如下所示:

    void sprint_hex(char *outbuf, unsigned char *hash, const hashid type) {
        int i;
        for (i = 0; i < mhash_get_block_size(type); i++) {
            sprintf(outbuf, "%.2x", hex[i]);
            outbuf += 2;
        }
    }
    

    请注意,这假定一个大小合适的缓冲区以outbuf 的形式传入。

    【讨论】:

      【解决方案4】:

      让用户传入要写入的缓冲区以及大小。显然,该函数必须重命名。即使这有点通用。由于hashid 参数,它可能应该是format_hash_to_hex_string()

      int format_hex_string(unsigned char const *hash, hashid type, char *buffer, size_t buflen)
      {
          size_t n = mhash_get_block_size(type);
          if (buflen < 2 * n + 1)
              return -1;
          for (size_t i = 0; i < n; i++)
              sprintf(&buffer[2*i], "%.2X", hash[i]);
          return 0;
      }
      

      或者,如果您相信您的用户能够提供足够大的缓冲区:

      format_hex_string(unsigned char const *hash, hashid type, char *buffer)
      {
          size_t n = mhash_get_block_size(type);
          for (size_t i = 0; i < n; i++)
              sprintf(&buffer[2*i], "%.2X", hash[i]);
      }
      

      或者,如果您更喜欢玩弄游戏(这可能比调用sprintf() 更快):

      int format_hex_string(unsigned char const *hash, hashid type, char *buffer, size_t buflen)
      {
          static char const hexdigits[] = "0123456789ABCDEF";
          size_t n = mhash_get_block_size(type);
          if (buflen < 2 * n + 1)
              return -1;
          for (size_t i = 0; i < n; i++)
          {
              *buffer++ = hexdigits[hash[i] >>  4];
              *buffer++ = hexdigits[hash[i] & 0xF];
          }
          *buffer = '\0';
          return 0;
      }
      

      为了证明通用名称的合理性,最好将hashid type 参数替换为简单的长度(然后您可以合理地假设程序员知道缓冲区长度必须至少是哈希长度的 2 倍):

      int format_hex_string(unsigned char const *binbuffer, size_t binlen, char *hexbuffer)
      {
          static char const hexdigits[] = "0123456789ABCDEF";
          for (size_t i = 0; i < binlen; i++)
          {
              *hexbuffer++ = hexdigits[binbuffer[i] >>  4];
              *hexbuffer++ = hexdigits[binbuffer[i] & 0xF];
          }
          *hexbuffer = '\0';
      }
      

      现在这是一个通用功能。如果你愿意,你可以将它包装成专门用于你的哈希格式;包装器可能会节省您编写一些对 mhash_get_block_size() 函数的调用。

      【讨论】:

        猜你喜欢
        • 2011-05-25
        • 2013-05-07
        • 2018-03-28
        • 2011-08-12
        • 2018-02-24
        • 2023-03-13
        • 2015-06-04
        • 2020-08-06
        相关资源
        最近更新 更多