将17位数据合并为字节数组

3
我在尝试将17位数据组移动到字节数组中时遇到了一些问题。我不想逐步进行,但我无法找到一个逻辑循环。
我需要这样做是因为我要通过像这样组合它们并添加所有字节值来计算校验和。
所以这就是我正在努力解决的问题。
我有16个字节数组。数组的前3个字节包含我想要的17位。(从[0]中获取8位,从[1]中获取8位,以及从[2]中获取MSB。)
我需要将这16个17位值移动到一个单独的字节数组中。
第一个很容易:
int index = 0;
myArray[index++] = driverData[driver][0];            //First byte
myArray[index++] = driverData[driver][1];            //Second byte
myArray[index] = (driverData[driver][2] & 0x80) << 7;  //First bit of the third byte.

从这里开始,尝试使用任何循环来移动它们变得更加困难。

driver++;<br>
//Take the 7 MSBs from the data array.
myArray[index++] |= (byte)(driverData[driver][0] & 0x7e >> 1);
//This leaves a single bit left over on driverData[driver][0].
myArray[index] = (byte)(driverData[driver][1] & 0x1 << 7);

我想你已经明白了图片的意思。我是不是做错了什么?有没有人可以指点我正确的方向?


1
希望我没有太过破坏你正在进行的编辑,抱歉 :) 我认为使用 driverData[driver][1] 结构比 data1data2 结构更容易,因为你可以迭代 driver++。 (另外,请注意描述中说 [1][2][3],但代码中说 [0][1][3]。) - sarnold
不,你已经大大地改进了它,谢谢。我会快速修复这些问题。谢谢。 - Spenduku
sarnold...我不知道你是如何将代码高亮等格式化的...我想我刚才把你优秀的编辑搞砸了。 - Spenduku
只是为了明确,每个输入数组的前三个字节包含17位信息。而你必须将这些17位一组连续地打包到一个字节数组中?因此,输出的第一个字节具有第一个数组的前8位,输出的第二个字节具有第一个数组的第二个8位,输出的第三个字节具有第一个数组的最后一位和第二个数组的前7位,以此类推? - QuantumMechanic
没错,量子机械师。 - Spenduku
3个回答

2

好的,看起来这似乎正在发挥作用。我可能需要进行更多测试,但到目前为止,这似乎给了我预期的结果。我相信我可以在某种程度上做得更好。

// ... //
void foo()
{
    //Lets start by getting all the 17bit values from each driver for the board.
    int bitIndex = 7;
    int byteIndex = 0;
    int stopIndex = chipIndex + GetChipCount();
    //Now we start the shiftyness.
    for (int driver = chipIndex; driver < stopIndex; driver++) {
        int userBits =
            (driverData[driver][0] & 0xff) << 9 | (driverData[driver][1]
                               & 0xff)
            << 1 | (driverData[driver][2] & 0x80) >> 7;
        AddBitsToArray(userBits, ref bitIndex, ref byteIndex);

    }
}

/// <summary>
/// Takes the 17 bits, and adds them to the byte array.
/// </summary>
private void AddBitsToArray(int userBits, ref int bitIndex, ref int byteIndex)
{
    int bitCount = 17;
    while (bitCount > 0) {
        //First 8 bytes.
        checksumBytes[byteIndex] |=
            (byte) (((userBits & bitValue(bitCount - 1)) >>
                 (bitCount - 1)) << bitIndex);
        //Move up the bit index to be written to.
        bitIndex--;
        //Decrement the number of bits left to shift.
        bitCount--;
        //If we have gone past the 8th bit, reset the bitIndex and increment the byteIndex.
        if (bitIndex >= 0)
            continue;
        bitIndex = 7;
        byteIndex++;
    }
}

/// <summary>
/// Returns the value of a single bit at the given index.
/// </summary>
private int bitValue(int bitIndex)
{
    return (int)(Math.Pow(2, bitIndex));
}

1
这比我想出来的任何东西都要干净 :) 如果它通过了你的测试,我会说你应该对它感到满意。 :) - sarnold
好的,谢谢你的编辑帮助,sarnold。 :) 看起来JYeltons的代码也很好用,可惜我不能选择两个答案。 - Spenduku

2

听起来你有一个素数循环,循环次数太多,逐个编写代码会很糟糕。这是一个经典的打包问题。你需要通过循环遍历目标,并且编写内部代码以获取更多需要打包的位数。你的打包代码应该知道上一轮迭代可用的位数、所需的位数,如果不足则应该能够增加源指针。


2
好的,那你会如何编写代码呢? - Spenduku
3
如果你一次只处理一个二进制位,这个任务会更容易。从输入中出队17个二进制位,并将它们入队到输出中。两边都需要跟踪当前字节和该字节内的当前二进制位。 - bk1e
我应该感谢bk1e,因为你的评论似乎激发了我如何完成这个任务的灵感。 - Spenduku

1
这是我想出来的。方法的第一部分仅设置了一些虚假的输入数据,因此请根据需要删除它并添加参数。 OutputData 数组过大,但我没有花时间计算其实际长度。
我使用了输入值170,它是10101010,有助于验证。
private void BitShift17()
{
    const int NumChunks = 16;
    byte[] DriverData = new byte[]
        {
            170,
            170,
            170
        };
    byte[][] InputData = new byte[NumChunks][];
    for (int n = 0; n < NumChunks; n++)
        InputData[n] = DriverData;

    byte[] OutputData = new byte[NumChunks * 3]; // Unnecessarily large

    int OutputIndex = 0;
    int BitPosition = 0;
    for (int Driver = 0; Driver < InputData.Length; Driver++)
    {
        for (int InputIndex = 0; InputIndex < 3; InputIndex++)
        {
            byte InputByte = InputIndex == 2 ? (byte)(InputData[Driver][InputIndex] & 128) : InputData[Driver][InputIndex];
            if (BitPosition == 0)
            {
                OutputData[OutputIndex] = InputByte;
                if (InputIndex == 2)
                    BitPosition++;
                else
                    OutputIndex++;
            }
            else
            {
                if (InputIndex == 2)
                {
                    OutputData[OutputIndex] |= (byte)(InputByte >> BitPosition);
                    BitPosition++;
                }
                else
                {
                    OutputData[OutputIndex] |= (byte)(InputByte >> BitPosition);
                    OutputIndex++;
                    OutputData[OutputIndex] = (byte)(InputByte << 8 - BitPosition);
                }
            }
        }
        if (BitPosition > 7) BitPosition = 0;
    }
}

嗯...我也会检查一下,看看我能得到什么。只是晚了一会儿! :) 谢谢JYelton。 - Spenduku
我已将您的答案标记为正确答案,因为您也付出了努力。再次感谢。 - Spenduku

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接