从字符中提取位序列

Extract a bit sequence from a character

所以我有一个字符数组,如下所示 {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 位将用 header 完成,以便有 8 位。

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

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

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

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

  • >> n右移去掉n个最低位
  • << n在最低位置注入n次0位
  • & 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。

下面是一些应该可以解决您的问题的代码:

#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] = '[=10=]';
        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  
#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] == '[=10=]') {
            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] = '[=10=]';
    return i;
}