简体   繁体   English

我如何加快十六进制字符到二进制字符的转换

[英]How can i speed up hexadecimal characters conversion to binary characters

I have already a function that convert hex char(input) to binary char(output). 我已经有一个将十六进制char(input)转换为二进制char(output)的函数。 it works perfect, for small amount of data(input length).But when the input is too big, it stuck/not working. 它适用于少量数据(输入长度​​)。但是,当输入太大时,它会卡住/不起作用。 May be strcat take too much time. 可能strcat需要太多时间。 Is there some alternate solution, So i can convert big hex input characters into equivalent binary. 是否有其他替代解决方案,所以我可以将大十六进制输入字符转换为等效的二进制。 My function is: 我的职能是:

void fun_hex_ch_2bin(int len_hex_str,uint8_t *hex,uint8_t *bin){
  /* Extract first digit and find binary of each hex digit */
  int i=0,j=0;

   char array_hex[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
   uint8_t *new_hex=malloc(len_hex_str*2);
   char hex_char1,hex_char2;
   j=0;
   for(i=0;i<len_hex_str;i++)
   {
      hex_char1=array_hex[hex[i]&0x0f];
      hex_char2=array_hex[(hex[i]>>4)&0x0f];
      //printf("%c  %c\n",hex_char1,hex_char2);
      new_hex[j]=hex_char2;
      new_hex[j+1]=hex_char1;
      j=j+2;
   }

    for(i=0; i<len_hex_str*2; i++)
    {
        switch(new_hex[i])
        {
            case '0':
                strcat(bin, "0000");
                break;
            case '1':
                strcat(bin, "0001");
                break;
            case '2':
                strcat(bin, "0010");
                break;
            case '3':
                strcat(bin, "0011");
                break;
            case '4':
                strcat(bin, "0100");
                break;
            case '5':
                strcat(bin, "0101");
                break;
            case '6':
                strcat(bin, "0110");
                break;
            case '7':
                strcat(bin, "0111");
                break;
            case '8':
                strcat(bin, "1000");
                break;
            case '9':
                strcat(bin, "1001");
                break;
            case 'a':
            case 'A':
                strcat(bin, "1010");
                break;
            case 'b':
            case 'B':
                strcat(bin, "1011");
                break;
            case 'c':
            case 'C':
                strcat(bin, "1100");
                break;
            case 'd':
            case 'D':
                strcat(bin, "1101");
                break;
            case 'e':
            case 'E':
                strcat(bin, "1110");
                break;
            case 'f':
            case 'F':
                strcat(bin, "1111");
                break;
            default:
                printf("Invalid hexadecimal input.");
        }
    }

}

Just use sprintf() instead of strcat() 只需使用sprintf()而不是strcat()

char *bin; // points to a long enough buffer
int binlen = 0;
binlen += sprintf(bin + binlen, "something"); // strcat(bin, "something");
binlen += sprintf(bin + binlen, "otherthing"); // strcat(bin, "otherthing");
binlen += sprintf(bin + binlen, "foobar"); // strcat(bin, "foobar");
//...
// you can even do
binlen += sprintf(bin + binlen, "%.2f", 2.71828); // strcat(bin, "2.72");

16 is a power of 2 so converting it to binary is pretty simple. 16是2的幂,因此将其转换为二进制非常简单。 Each hex digit corresponds to exactly 4 binary digits - and you can rely on this fact. 每个十六进制数字正好对应于4个二进制数字-您可以依靠这一事实。 As a first step you need to convert the input characters from ASCII to numeric values. 第一步,您需要将输入字符从ASCII转换为数字值。 That's easily done in one pass over the input hex string and subtracting 48 if the character is between '0' and '9' or subtracting 88 if the character is between 'a' and 'f' (take a look at the ASCII table if need an explanation on why). 只需在输入的十六进制字符串上传递一次即可轻松完成,如果字符在'0''9'之间,则减去48;如果字符在'a''f'之间,则减去88(如果是,请查看ASCII表)需要说明原因)。 After that the conversion is straightforward - go over the hex array and for each hex value take a look at the last bit and proceed to the next bit exactly 4 times, move to the next hex value and repeat the procedure. 之后,转换非常简单-遍历十六进制数组,并为每个十六进制值查看最后一位,然后精确地进行到下一位4次,移至下一个十六进制值并重复该过程。 Something like this: 像这样:

int i = 0, j = 0;
while(i < len_hex_str)
{
   bin[j++]=hex[i] & 1;
   hex[i] >>= 1;
   if(j % 4 == 0) i++;
}

And since you seem to be in need to have it ASCII representation, just pass over the output string and add 48 to each digit. 并且由于您似乎需要使用ASCII表示,因此只需将输出字符串传递过来,并在每个数字后加上48。

How can i speed up hexadecimal characters conversion to binary characters (?) 我如何加快将十六进制字符转换为二进制字符(?)
May be strcat take too much time. 可能strcat需要太多时间。

Yes. 是。 Each call to strcat() takes longer and longer time as code does not take advantage of data already converted. 每次对strcat()调用花费的时间越来越长,因为代码没有利用已转换的数据。

strcat() take n time to traverse the first characters. strcat()需要n时间来遍历第一个字符。

1st strcat call, n = 0    
2st strcat call, n = 8    
3rd strcat call, n = 16    
4th strcat call, n = 24
ith strcat call, n = 8*(i-1)

See how the sum (0+8+16+24+...) goes up by order of i*i as i increases? 看看随着i增加,总和(0 + 8 + 16 + 24 + ...)如何按i*i的顺序增加?


Note that the first call to strcat(bin, ...) is suspect as bin[0] is not certainly a null character - something required when concatenating to a string . 请注意,怀疑对strcat(bin, ...)的首次调用是因为bin[0]不一定是空字符-连接到字符串时需要这样做。


Is there some alternate solution (?) 是否有其他替代解决方案(?)

I recommend a re-write. 我建议重写。 Directly read from hex as binary and skip the in-between conversion to hexadecimal. hex直接读取为二进制,并跳过中间转换为十六进制的过程。

void fun_hex_ch_2bin(int len_hex_str, uint8_t *hex, uint8_t *bin) {
  while (len_hex_str > 0) {
    len_hex_str--;
    // Start with the MSBit
    for (uint8_t mask = 0x80; mask; mask >>=1) {
      *bin++ = mask & *hex ? '1' : '0';
    }
    hex++;
  }
  // Append a null character as `bin` is to point to a _string_.
  *bin = '\0';
}

I'd expect bin , as a string to be char* and not unit8_t * . 我希望bin可以作为char*而不是unit8_t *字符串

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM