从字符中提取位序列
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);
您的示例的显示结果将是(十六进制):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;
}
所以我有一个字符数组,如下所示 {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);
您的示例的显示结果将是(十六进制):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;
}