Question

I ai un tableau d'octets générée par un générateur de nombres aléatoires. Je veux mettre cela dans la 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. Un unsigned long. (Mon tableau d'octets sera plus long)

La seule solution que je peux penser est maintenant à lire le bit de tableau d'octets par bit et faire une chaîne de 1 et 0. Quelqu'un at-il une solution plus efficace?

Était-ce utile?

La solution

Quelque chose comme ça? (Je ne sais pas si la magie modèle fonctionne ici comme je pense. Je suis rouillé en C ++.)

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

    for(int i = 0; i < numBytes; ++i)
    {
        byte 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;
}

Autres conseils

Il y a un 3ème constructeur pour bitset<> - il ne prend aucun paramètre et définit tous les bits à 0. Je pense que vous aurez besoin d'utiliser que puis marcher à travers le réseau appelant set() pour chaque bit dans le tableau d'octets qui est un 1.

Un peu de force brute, mais ça va marcher. Il y aura un peu de complexité pour convertir l'octet index et décalage de bit dans chaque octet à un indice de bitset, mais il n'y a rien un peu de la pensée (et peut-être une course à travers sous le débogueur) ne résoudra pas. Je pense qu'il est très probablement plus simple et plus efficace que d'essayer d'exécuter le tableau par une conversion de chaîne ou un flux.

Les gars, j'ai passé beaucoup de temps en écrivant une fonction inverse (bitset -> octet / tableau de caractères). Il est:

    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")

Eh bien, soyons honnête, je me suis ennuyé et a commencé à penser qu'il devait y avoir une façon légèrement plus rapide que le réglage de chaque bit.

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;
}

est en effet un peu plus rapide, au moins aussi longtemps que le tableau d'octets est inférieur à 30 éléments (en fonction de votre optimisation des drapeaux transmis au compilateur). Agrandir tableau et que le temps utilisé en déplaçant le bitset rend chaque réglage plus vite.

vous pouvez initialiser le bitset à partir d'un flux. Je ne me souviens pas comment un octet Wrangle [] dans 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;
  }

Voici ma mise en œuvre en utilisant méta-modèle de programmation.
Les boucles sont faites dans la compilation.
Je pris @strager version, il modifiée afin de se préparer à TMP:

  • a changé l'ordre d'itération (pour que je puisse faire de lui récursivité);
  • nombre réduit de variables utilisées.

Version modifiée avec des boucles dans une exécution:

template <size_t nOfBytes>
void bytesToBitsetRunTimeOptimized(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) {
  for(int i = nOfBytes - 1; i >= 0; --i) {
    for(int bit = 0; bit < CHAR_BIT; ++bit) {
      result[i * CHAR_BIT + bit] = ((arr[i] >> bit) & 1);
    }
  }
}

Version TMP sur cette base:

template<size_t nOfBytes, int I, int BIT> struct LoopOnBIT {
  static inline void bytesToBitset(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) {
    result[I * CHAR_BIT + BIT] = ((arr[I] >> BIT) & 1);
    LoopOnBIT<nOfBytes, I, BIT+1>::bytesToBitset(arr, result);
  }
};
// stop case for LoopOnBIT
template<size_t nOfBytes, int I> struct LoopOnBIT<nOfBytes, I, CHAR_BIT> {
  static inline void bytesToBitset(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) { }
};

template<size_t nOfBytes, int I> struct LoopOnI {
  static inline void bytesToBitset(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) {
    LoopOnBIT<nOfBytes, I, 0>::bytesToBitset(arr, result);
    LoopOnI<nOfBytes, I-1>::bytesToBitset(arr, result);
  }
};
// stop case for LoopOnI
template<size_t nOfBytes> struct LoopOnI<nOfBytes, -1> {
  static inline void bytesToBitset(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) { }
};

template <size_t nOfBytes>
void bytesToBitset(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) {
  LoopOnI<nOfBytes, nOfBytes - 1>::bytesToBitset(arr, result);
}

Code client:

uint8_t arr[]={0x6A};
  std::bitset<8> b; 
  bytesToBitset<1>(arr,b);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top