【问题标题】:Strip parity bits in C剥离 C 中的奇偶校验位
【发布时间】:2011-06-30 16:31:28
【问题描述】:

假设我有一个包含 8 位数据的位流,后跟 2 个奇偶校验位(模式重复)。

示例(x 是奇偶校验位):

0001 0001 xx00 0100 01xx 0001 0001 xx00 ...

应该变成

0001 0001 0001 0001 0001 0001 ...

我觉得这应该很容易,但我只是想多了,但是你如何剥离这些奇偶校验位?

【问题讨论】:

  • 您的数据是如何存储的?
  • @Phonon 数据被读入缓冲区,数据长度已知。

标签: c


【解决方案1】:

这里的棘手之处在于 C 不允许您轻松使用位,只能使用字节。我将假设您的 char 包含 8 位(检查 limits.h 中的 CHAR_BIT)——几乎所有现代系统都是这种情况。 8 和 10 的最小公倍数是 40,因此您希望在至少 40 位的缓冲区中工作,您可以将其作为一个整体进行整数运算——实际上这意味着 64 位类型。所以这是一种方法,从标准输入读取并写入标准输出。处理长度不是 40 位倍数的流留作练习。

#include <stdint.h>
#include <stdio.h>

int main(void)
{
    int c;
    uint_least64_t buffer;

    for (;;)
    {
       buffer = 0;
       /* read in 4 10-bit units = 5 8-bit units */
       c = getchar(); if (c == EOF) break;
       buffer = ((buffer << 8) | c);
       c = getchar(); if (c == EOF) break;
       buffer = ((buffer << 8) | c);
       c = getchar(); if (c == EOF) break;
       buffer = ((buffer << 8) | c);
       c = getchar(); if (c == EOF) break;
       buffer = ((buffer << 8) | c);
       c = getchar(); if (c == EOF) break;
       buffer = ((buffer << 8) | c);

       /* write out the non-parity bits */
       putchar((buffer & 0xFF00000000ULL) >> 32);
       putchar((buffer & 0x003FC00000ULL) >> 22);
       putchar((buffer & 0x00000FF000ULL) >> 12);
       putchar((buffer & 0x00000003FCULL) >>  2);
    }
    /* deal with incomplete block here */
    return 0;
}

...如果你想变得非常聪明,你会在扔掉它们之前检查这些奇偶校验位,尽管那时你必须想出一些建设性的事情来做(而不是如果)校验和失败。

【讨论】:

  • 达夫的设备是否适用于处理不完整的块? en.wikipedia.org/wiki/Duff%27s_device
  • @josec,请不要在生产代码中使用类似的东西。
  • @josec,除了 Carl 的警告之外,我看不出这样的结构会有什么帮助。一个常规的 switch 语句,以读取的 8 字节单元的计数为关键,并使用 fall-through 就可以了。
  • Duff 的设备在其原始形式中不适用,因为您在最后处理的是短读,而不是开始时的错位。 Jump-into-the-middle-of-a-sequence 控制逻辑(也许用gotos 替换breaks)可能是可用的,但我没有立即看到如何防止它发出不完整的块错误的顺序(LIFO 而不是 FIFO)。
  • 我有同样的问题,但在 32 位机器上。我有 8 个数据位,后跟 1 个奇偶校验位,并且在 OP 的问题中重复模式
【解决方案2】:

我会在 C 中定义一个位域结构,然后用它来“构架”数据缓冲区,只提取有用的位。像这样的:

struct tframe {
     unsigned data: 8;
     unsigned control: 2;
}

struct tframe * frames = &buf;

/* Iterate and write 'data' field to wherever */
...

您正在使用自己的数据,因此代码可移植性不会成为问题。

【讨论】:

  • 除了您提到的可移植性问题之外,这种使用位域的尝试甚至都行不通-您仍然只能将其指向字节边界。对象不能有分数大小。
  • 如果扩展为四个“数据”+“控制”项的序列,它会起作用,这样整体就是一个 8 位字节的整数。模结构封装问题,如果您问我,这些问题本身就是不使用此技术的原因。
  • 当然,如果你这样做,它不会让你摆脱短读问题。
  • 是的,我认为字节边界可能是个问题,但有一段时间没有做 C 了! OP 没有提及他的数据缓冲区的大小或存储类型是什么,所以我假设他知道他将有短读问题,不管(最后 0 位/字节填充?)。
猜你喜欢
  • 2015-06-29
  • 2017-03-01
  • 2015-04-04
  • 1970-01-01
  • 1970-01-01
  • 2015-06-05
  • 2012-04-20
  • 1970-01-01
相关资源
最近更新 更多