0

我有一个包含字符的向量。这些字符只能是字母表中的 26 个大写字母,因此表示这些字符的位数可以从 8 位减少到 5 位。然后我需要将结果写入文件,以备后用。

我目前的想法是 A..Z 的 3 个最高有效位都是相同的,因此我可以使用 5 个最低有效位来唯一标识字符吗?但是我正在努力将这些未格式化的数据写入文件。

我将如何执行此操作并将结果写入文件?

4

5 回答 5

1

要将字符减少到 5 位,您可以使用ch & 0x1Fch - 'A'; 两者都不适用于EBCDIC,但这可能不是问题。(如果是:在所有大写字母的字符串中查找表,返回索引,可以使用。)

在那之后,它变得复杂。最简单的解决方案是定义一个位数组,例如:

class BitArray
{
    std::vector<unsigned char> myData;
    int byteIndex( int index ) { return index / 8; }
    unsigned char bitMask( int index ) { return 1 << (index % 8); }
    int byteCount( int bitCount )
    { 
        return byteIndex( bitCount )
            + (bitIndex( bitCount) != 0 ? 1 : 0);
    }
public:
    BitArray( int size ) : myData( byteCount( size ) ) {}
    void set( index )
    {
        myData[byteIndex( index )] |= bitMask( index );
    }
    void reset( index )
    {
        myData[byteIndex( index )] &= ~bitMask( index );
    }
    bool test( index )
    {
        return (myData[byteIndex( index ) & bitMask( index )) != 0;
    }
};

(你需要更多的数据来提取数据,但我不确定你需要什么格式。)

然后你循环你的字符串:

BitArray results( 5 * s.size() );
for ( int index = 0; index != s.size(); ++ index ) {
    for ( int pos = 0; pos != 5; ++ pos ) {
        results.set( 5 * index + pos );
    }
}

这将毫无问题地工作。当我在遥远的过去尝试使用它(或更确切地说是等效的)时(对于霍夫曼编码,在 C 中,因为这是在 1980 年代),它也太慢了。如果您的琴弦相当短,那么今天可能就足够了。否则,您将需要一个更复杂的算法,它会跟踪最后一个字节中已经使用了多少位,并进行适当的移位和掩码以一次性插入尽可能多的位:最多两个移位和或每次插入操作,而不是这里的 5 次。这就是我最终使用的。(但我没有代码了,所以我不能轻易发布一个例子。)

于 2014-05-01T08:37:49.247 回答
0

你可以试试我的PackedArray代码。

它实现了一个随机访问容器,其中项目以位级别打包。换句话说,它的作用就像您能够操作 eguint9_tuint17_t数组一样:

PackedArray principle:
  . compact storage of <= 32 bits items
  . items are tightly packed into a buffer of uint32_t integers

PackedArray requirements:
  . you must know in advance how many bits are needed to hold a single item
  . you must know in advance how many items you want to store
  . when packing, behavior is undefined if items have more than bitsPerItem bits

PackedArray general in memory representation:
  |-------------------------------------------------- - - -
  |       b0       |       b1       |       b2       |
  |-------------------------------------------------- - - -
  | i0 | i1 | i2 | i3 | i4 | i5 | i6 | i7 | i8 | i9 |
  |-------------------------------------------------- - - -

  . items are tightly packed together
  . several items end up inside the same buffer cell, e.g. i0, i1, i2
  . some items span two buffer cells, e.g. i3, i6
于 2014-05-08T12:58:29.490 回答
0

您可以使用的最小数据单位是 8 位。您将不得不使用位移,但您只能以 8 位为一组读取/写入数据,因此您将需要额外的逻辑来处理它。如果您的输入至少有 8 个 5 位字母,则一次将 8 个字母合并在一起以形成总共 40 位,并将其作为 5 个 8 位字节写入文件。根据需要继续,直到剩下的 5 位字母少于 8 个,然后将它们合并在一起,并将剩余部分填充为 8 的偶数倍,并将其写入文件。

于 2014-04-30T17:54:13.050 回答
0

你能做到吗?当然。

我认为您只需使用 gzip 编写压缩文件就会获得更大的成功和轻松。

于 2014-04-30T18:25:29.360 回答
0

我有一个向量 [of chars that] 只能是字母表的 26 个大写字母

您可以相对容易地对其进行编码:将文本拆分为 8 个字符的块,并将编码后的文本写入 5 个字节的块,如下所示:

          76543210 76543210 76543210 76543210 76543210 76543210 76543210 76543210
ORIGINAL: 000AAAAA 000BBBBB 000CCCCC 000DDDDD 000EEEEE 000FFFFF 000GGGGG 000HHHHH

          76543210 76543210 76543210 76543210 76543210
ENCODED:  AAAAABBB BBCCCCCD DDDDEEEE EFFFFFGG GGGHHHHH

如果您的最后一个块没有足够的字符,请使用不用于对 26 个字母中的任何一个进行编码的“填充”字符(所有字符)。

于 2014-04-30T18:14:31.473 回答