【问题标题】:Extract a bit sequence from a character从字符中提取位序列
【发布时间】:2017-02-25 03:28:01
【问题描述】:

所以我有一个字符数组,如下所示 {h,e,l,l,o,o} 所以我需要先把它翻译成它的位表示,所以我会得到这个

h = 01101000
e = 01100101
l = 01101100
l = 01101100
o = 01101111
o = 01101111

我需要将所有这些位分成五个一组并将其保存到一个数组中 所以例如所有这些字符的联合将是

011010000110010101101100011011000110111101101111

现在我把它分成五个一组,所以

01101 00001 10010 10110 11000 11011 00011 01111 01101 111

最后一个序列应该用零完成,所以它应该是 00111。注意:每组 5 位将用一个标题完成,以便有 8 位。

所以我还没有意识到如何做到这一点,因为我可以提取每个字符的 5 位并得到每个字符的二进制表示,如下所示

 for (int i = 7; i >= 0; --i)
  {
     printf("%c", (c & (1 << i)) ? '1' : '0');
  }

问题是如何组合两个字符,所以如果我有两个字符 00000001 和 11111110 当我分成五组时,我将有字符的第一部分的 5 位,而对于第二组,我将有 3 位最后一个字符和第二个字符的 2。如何进行这种组合并将所有这些组保存在一个数组中?

【问题讨论】:

  • 你想要实现的东西没有意义。
  • 这个和base64差不多。 Base64 每个字符存储 6 位。与您想要的非常相似,除了 base64 从每 3 个字节中收集额外的 2 位,并使用前 3 个字节中的 6 个额外位来制作每个第 4 个字节。
  • @doug65536 对于每组 5 位,我会添加一个标题来完成 8 位,问题是我无法弄清楚如何获得所有这五个组
  • 你不能只是通过连接'h' = "01101000" .... 的结果来构建一个字符串,然后将字符分成五个一组,直到剩下的字符少于 5 个,然后填充最后一个组。
  • 一个循环,一些用于跟踪位偏移的变量,一些移位和屏蔽,以及一个输出缓冲区。

标签: c binary character ascii bits


【解决方案1】:

假设一个字节由 8 位组成(注意:C 标准不保证这一点),您必须遍历字符串并使用位操作来完成它:

  • &gt;&gt; n右移去掉n个最低位
  • &lt;&lt; n 在最低位置注入 n 次 0 位
  • &amp; 0x1f 只保留 5 个最低位并重置更高位
  • |合并高位和低位,当重叠位为0时

可以这样编码:

char s[]="helloo";

unsigned char last=0;          // remaining bits from previous iteration in high output part
size_t j=5;                    // number of high input bits to keep in the low output part 
unsigned char output=0; 
for (char *p=s; *p; p++) {     // iterate on the string 
    do {
        output = ((*p >> (8-j)) | last) & 0x1f;  // last high bits set followed by j bits shifted to lower part; only 5 bits are kept 
        printf ("%02x ",(unsigned)output);
        j += 5;                                  // take next block  
        last = (*p << (j%8)) & 0x1f;             // keep the ignored bits for next iteration 
    } while (j<8);                               // loop if second block to be extracted from current byte
    j -= 8;                                      
}
if (j)                                           // there are trailing bits to be output
   printf("%02x\n",(unsigned)last); 

online demo

您的示例的显示结果将是(十六进制):0d 01 12 16 18 1b 03 0f 0d 1c,它与您列出的 5 个位组中的每一个完全对应。请注意,如果最后一个块不是 5 位长,则此代码在最后一个块中添加 0 右填充(例如,这里最后 3 位填充到 11100,即 0x1C 而不是 111,即 0x0B)

您可以轻松修改此代码以将输出存储在缓冲区中,而不是打印出来。唯一微妙的事情是预先计算输出的大小,它应该是原始大小的 8/5 倍,如果它不是 5 的倍数,则增加 1,如果您希望添加终止符,则再次增加 1。

【讨论】:

    【解决方案2】:

    这里有一些代码可以解决你的问题:

    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char arr[6] = {'h', 'e', 'l', 'l', 'o', 'o'};
        char charcode[9];
        char binarr[121] = "";
        char fives[24][5] = {{0}};
        int i, j, n, numchars, grouping = 0, numgroups = 0;
    
        /* Build binary string */
        printf("\nCharacter encodings:\n");
        for (j = 0; j < 6; j++) {
            for (i = 0, n = 7;  i < 8; i++, n--)
                charcode[i] = (arr[j] & (01 << n)) ? '1' : '0';
            charcode[8] = '\0';
            printf("%c = %s\n", arr[j], charcode);
            strcat(binarr, charcode);
        }
    
        /* Break binary string into groups of 5 characters */
        numchars = strlen(binarr);
        j = 0;
        while (j < numchars) {
            i = 0;
            if ((numchars - j) < 5) {                 // add '0' padding
                for (i = 0; i < (5 - (numchars - j)); i++)
                    fives[grouping][i] = '0';
            }
            while (i < 5) {                           // write binary digits
                fives[grouping][i] = binarr[j];
                ++i;
                ++j;
            }
            ++grouping;
            ++numgroups;
        }
    
        printf("\nConcatenated binary string:\n");
        printf("%s\n", binarr);
    
        printf("\nGroupings of five, with padded final grouping:\n");
        for (grouping = 0; grouping <= numgroups; grouping++) {
            for (i = 0; i < 5; i++)
                printf("%c", fives[grouping][i]);
            putchar(' ');
        }
        putchar('\n');
    
        return 0;
    }
    

    按原样运行时,输出为:

    Character encodings:
    h = 01101000
    e = 01100101
    l = 01101100
    l = 01101100
    o = 01101111
    o = 01101111
    
    Concatenated binary string:
    011010000110010101101100011011000110111101101111
    
    Groupings of five, with padded final grouping:
    01101 00001 10010 10110 11000 11011 00011 01111 01101 00111  
    

    【讨论】:

      【解决方案3】:
      #include <limits.h>
      #include <stdio.h>
      
      #define GROUP_SIZE 5
      
      static int nextBit(void);
      static int nextGroup(char *dest);
      
      static char str[] = "helloo";
      
      int main(void) {
          char bits[GROUP_SIZE + 1];
          int firstTime, nBits;
      
          firstTime = 1;
          while ((nBits = nextGroup(bits)) == GROUP_SIZE) {
              if (!firstTime) {
                  (void) putchar(' ');
              }
              firstTime = 0;
              (void) printf("%s", bits);
          }
          if (nBits > 0) {
              if (!firstTime) {
                  (void) putchar(' ');
              }
              while (nBits++ < GROUP_SIZE) {
                  (void) putchar('0');
              }
              (void) printf("%s", bits);
          }
          (void) putchar('\n');
          return 0;
      }
      
      static int nextBit(void) {
          static int bitI = 0, charI = -1;
      
          if (--bitI < 0) {
              bitI = CHAR_BIT - 1;
              if (str[++charI] == '\0') {
                  return -1;
              }
          }
          return (str[charI] & (1 << bitI)) != 0 ? 1 : 0;
      }
      
      static int nextGroup(char *dest) {
          int bit, i;
      
          for (i = 0; i < GROUP_SIZE; ++i) {
              bit = nextBit();
              if (bit == -1) {
                  break;
              }
              dest[i] = '0' + bit;
          }
          dest[i] = '\0';
          return i;
      }
      

      【讨论】:

        猜你喜欢
        • 2018-12-06
        • 2021-01-22
        • 2016-03-14
        • 1970-01-01
        • 2021-11-07
        • 2020-04-18
        • 2019-01-17
        • 2023-04-10
        • 2019-03-21
        相关资源
        最近更新 更多