循环C中的位

时间:2018-06-17 16:14:32

标签: c

我是C新手,我想根据以下程序将输入位存储到输出数组。

input           MSB                  LSB MSB                  LSB MSB              
[169,48,0] =     1  0  1  0  1  0  0  1   0  0  1  1  0  0  0  0   0  0  0  0  0  0  0  0 

程序应循环输入数据以查找起始索引所在的字节,并从起始索引到结束索引提取位并将其存储在输出[]中。举个例子,我的起始索引是4,它出现在input [0]中,我的结束索引是13.所以我需要从位位置4到13中提取并将它放在output []中。

当我说位位置4到13时我的意思是 - 我需要来自输入[0]的位[4 - 7] = {0 1 0 0 1}和位[8 - 13] = {1 1 0 0 0 0}来自输入[1]

expected
output
[9, 48,0] =     0  0  0  0  1  0  0  1   0  0  1  1  0  0  0  0   0  0  0  0  0  0  0  0

我尝试用C编程但不幸的是我没有成功,循环比特是通过LSB到MSB。我需要循环第一个字节并继续到下一个字节并重复直到结束位置所在的字节索引。

#include<stdio.h>
int main()
{
    unsigned char input[3] = {169,48,0};
    unsigned char output[3]= {0};
    int i, start = 4, end = 13;
    for(i=0; i<3; i++)
    {
        output[i] = (input[i] >> (start)) & ((1u << (end)) -1u);
        printf("%u\n",output[i]);
    }
    return 0;
}

程序循环所有3个输入字节,并从位索引4存储到该特定字节的结束索引,即7.

output
[10, 3, 0] =     0  0  0  0  1  0  1  0   0  0  0  0  0  0  1  1   0  0  0  0  0  0  0  0 

我想检查输入[0]或输入[1]或输入中是否存在我的起始索引。 。 。 input [n],根据开头所示的预期输出,从开始索引到结束索引(可能存在于任何字节位置)进行复制和存储。

如果你能纠正程序逻辑,我会很高兴,因为我是C的新手。

1 个答案:

答案 0 :(得分:0)

欢迎来到论坛。

  

如果你能纠正程序逻辑,我会很高兴,因为我是C的新手。

这是一个尝试性的尝试。您的主要逻辑如下:

output[i] = (input[i] >> (start)) & ((1u << (end)) -1u);

通过将其简化为以下(并使用临时unsigned char变量tmp),可以更轻松地进行分析:

tmp = input[i] >> start; // (1)
tmp &= (1u << end) - 1u; // (2)
// etc.

我不清楚你到底想要做什么。我相信你应该尝试做的是从8-startinput[i]start位中提取input[i+1]位并放置这些位的逻辑或临时变量中的值(适当移位)。如果是这样,那么我的建议如下。

在第一行(1)中你正在改变错误的方向:它应该是

tmp = input[i] << start;

下一行(2)没有完成任何事情。 (你实际上是和零的。)另外,你应该使用|而不是&amp;,第二个操作数应该是从下一个字节中选择的位(适当移位)。

tmp |= input[i+1] >> (8-start);

然后,这是提取阶段。接下来是输出流中的插入阶段。上面没有讨论过更多的细微差别,但这提供了一般的想法。 (有关处理更多详细信息的实现,请参阅下文。)

  

我想检查输入[0]或输入[1]或输入中是否存在我的起始索引。 。 。输入[N]

用于此用途

int idx = start / 8; // byte index
int offset = start % 8; // bit position within byte

P.S。您的原始问题表明,提取位的偏移量在输出流中可能与输入流中的偏移量不同。您的编辑隐藏了这一事实,但下面的实现允许这种可能性('转置')。

可能的实施

void transpose_bits(unsigned char *a, unsigned char *b, int start, int end, int dest, size_t array_len) {
    unsigned char tmp = '\0', tmp2 = '\0';
    int offset = 0, idx = 0, len = 0, next_bits = 0;
    char bitmask = 0x80;

    len = end - start;
    while (len > 0) {
        // Single pass - transpose up to 8 bits ...
        tmp = tmp2 = '\0';

        // Determine the byte index and offset in the input byte array.
        idx = start / 8;
        offset = start % 8;
        tmp = a[idx] << offset;
        next_bits = offset + len - 8;
        if (next_bits < 0) {
            // Don't even need all of current byte  => remove trailing bits ...
            tmp &= bitmask >> (len - 1);
        } else if (next_bits > 0) {
            // Need to include part of next byte ...
            tmp2 = a[idx + 1] & (bitmask >> (next_bits - 1));
            tmp |= tmp2 >> (8 - offset);
        }

        // Determine byte index and offset in output byte array
        idx = dest / 8;
        offset = dest % 8;
        b[idx] |= tmp >> offset;
        b[idx + 1] |= tmp << (8 - offset);
        // Update start position and length for next pass ...
        if (len > 8) {
            len -= 8;
            dest += 8;
            start += 8;
        } else
            len -= len;
    }
}

样本使用:

// Extract bits: 'start' and 'dest' are the same.
transpose_bits(input, output, 4, 13, 4, 3); // Assume arrays are of length '3'

// Transpose bits: 'start' and 'dest' not the same.
transpose_bits(input, output, 4, 13, 10, 3);

备注

  • char[]数组必须是无符号的(正如您所选择的那样) - 因为右移位运算符对带符号值的工作方式不同。
  • 您应该检查数组的边界(将idxarray_len进行比较);为简洁起见,我在此处略过了
  • while()函数的transpose_bits()循环中的每次迭代最多可处理8位。通过使用多次传递,它可以处理任意数量。