9 votes

Convertir un tableau d'octets en jeu de bits

J'ai un tableau d'octets généré par un générateur de nombres aléatoires. Je veux le mettre dans le STL bitset.

Malheureusement, il semble que Bitset ne supporte que les constructeurs suivants :

  1. Une chaîne de 1 et de 0 comme "10101011".
  2. Une longueur non signée. (mon tableau d'octets sera plus long)

La seule solution à laquelle je pense maintenant est de lire le tableau d'octets bit par bit et de créer une chaîne de 1 et de 0. Quelqu'un a-t-il une solution plus efficace ?

8voto

strager Points 41713

Quelque chose comme ça ?

#include <bitset>
#include <climits>

template<size_t numBytes>
std::bitset<numBytes * CHAR_BIT> bytesToBitset(uint8_t *data)
{
    std::bitset<numBytes * CHAR_BIT> b;

    for(int i = 0; i < numBytes; ++i)
    {
        uint8_t cur = data[i];
        int offset = i * CHAR_BIT;

        for(int bit = 0; bit < CHAR_BIT; ++bit)
        {
            b[offset] = cur & 1;
            ++offset;   // Move to next bit in b
            cur >>= 1;  // Move to next bit in array
        }
    }

    return b;
}

Et un exemple d'utilisation :

int main()
{
    std::array<uint8_t, 4> bytes = { 0xDE, 0xAD, 0xBE, 0xEF };
    auto bits = bytesToBitset<bytes.size()>(bytes.data());
    std::cout << bits << std::endl;
}

3voto

Michael Burr Points 181287

Il y a un troisième constructeur pour bitset<> - elle ne prend aucun paramètre et met tous les bits à 0. Je pense que vous devrez utiliser cette fonction puis parcourir le tableau en appelant set() pour chaque bit du tableau d'octets qui est un 1.

Un peu de force brute, mais ça marchera. Il y aura un peu de complexité pour convertir l'index d'octet et le décalage de bit dans chaque octet en un index de jeu de bits, mais ce n'est rien qu'un peu de réflexion (et peut-être un passage sous le débogueur) ne puisse résoudre. Je pense que c'est très probablement plus simple et plus efficace que d'essayer de faire passer le tableau par une conversion de chaîne ou un flux.

2voto

Honza Javorek Points 871

Les gars, j'ai passé beaucoup de temps à écrire une fonction inverse (bitset -> byte/char array). Voilà :

    bitset<SIZE> data = ...

    // bitset to char array
    char current = 0;
    int offset = 0;
    for (int i = 0; i < SIZE; ++i) {
        if (data[i]) { // if bit is true
            current |= (char)(int)pow(2, i - offset * CHAR_BIT); // set that bit to true in current masked value
        } // otherwise let it to be false
        if ((i + 1) % CHAR_BIT == 0) { // every 8 bits
            buf[offset++] = current; // save masked value to buffer & raise offset of buffer
            current = 0; // clear masked value
        }
    }

    // now we have the result in "buf" (final size of contents in buffer is "offset")

1voto

asheidan Points 21

Eh bien, soyons honnêtes, je m'ennuyais et j'ai commencé à penser qu'il devait y avoir un moyen un peu plus rapide que de régler chaque mèche.

template<int numBytes>
std::bitset<numBytes * CHARBIT bytesToBitset(byte *data)
{
    std::bitset<numBytes * CHAR_BIT> b = *data;

    for(int i = 1; i < numBytes; ++i)
    {
        b <<= CHAR_BIT;  // Move to next bit in array
        b |= data[i];    // Set the lowest CHAR_BIT bits
    }

    return b;
}

Cette méthode est en effet légèrement plus rapide, du moins tant que le tableau d'octets est inférieur à 30 éléments (en fonction de vos drapeaux d'optimisation passés au compilateur). Si le tableau est plus grand que cela, le temps utilisé pour décaler le jeu de bits rend la mise en place de chaque bit plus rapide.

0voto

Pitarou Points 121

Vous pouvez initialiser le bitset à partir d'un flux. Je ne me souviens pas comment transformer un byte[] en un flux, mais...

de http://www.sgi.com/tech/stl/bitset.html

  bitset<12> x;

  cout << "Enter a 12-bit bitset in binary: " << flush;
  if (cin >> x) {
    cout << "x =        " << x << endl;
    cout << "As ulong:  " << x.to_ulong() << endl;
    cout << "And with mask: " << (x & mask) << endl;
    cout << "Or with mask:  " << (x | mask) << endl;
  }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X