文字を 5 ビットに減らすには、ch
& 0x1F
またはch - '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 );
}
}
これは問題なく動作します。私が遠い過去にそれ(または同等のもの)を使用しようとしたとき(これは1980年代だったので、Cでのハフマンエンコーディング用)、それも遅すぎました。ひもがかなり短い場合は、今日、それで十分かもしれません。それ以外の場合は、最後のバイトで既に使用されているビット数を追跡し、適切なシフトとマスクを実行して、一度にできるだけ多くのビットを挿入する、より複雑なアルゴリズムが必要になります。最大 2 つのシフトまたはここの場合のように 5 回ではなく、挿入あたりの操作数です。これが私が最終的に使用したものです。(しかし、私はもうコードを持っていないので、例を簡単に投稿することはできません.)