2009-04-02 7 views
6

J'ai un tableau d'octets généré par un générateur de nombres aléatoires. Je veux mettre cela dans le bitet STL.Conversion d'un tableau d'octets en jeu de bits

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 maintenant est de lire le tableau d'octets bit par bit et de faire une chaîne de 1 et 0. Est-ce que quelqu'un a une solution plus efficace?

Répondre

7

Quelque chose comme ça? (Je ne sais pas si la magie modèle fonctionne ici comme je pense que 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; 
} 
0

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

Je viens essayé, et il nécessite une entrée pour être seulement 1 ou 0 – Unknown

3

Il y a un 3ème constructeur pour bitset<> - il pas de paramètres et définit prend tous les bits 0. Je pense que vous aurez besoin d'utiliser cela puis parcourir le tableau appelant set() pour chaque bit dans le tableau d'octets qui est un 1.

Un peu de force brute, mais ça va fonctionner. Il y aura un peu de complexité pour convertir l'octet-indice et le décalage de bit dans chaque octet en un index de bitset, mais ce n'est pas un peu de réflexion (et peut-être un passage dans le débogueur) ne résoudra pas. Je pense qu'il est probablement plus simple et plus efficace que d'essayer d'exécuter le tableau via une conversion de chaîne ou un flux.

2

Les gars, j'ai passé beaucoup de temps en écrivant une fonction inverse (bitset -> octet/char tableau). 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") 
2

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

Ceci 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). Un plus grand tableau que celui-ci et le temps utilisé pour déplacer le bitset rend chaque bit plus rapide.

0

Voici ma mise en œuvre en utilisant la méta-programmation de gabarit.
Les boucles sont effectuées au moment de la compilation.
Je pris @strager version, il modifiée afin de préparer TMP:

  • ordre modifié d'itération (pour que je puisse faire récursion de lui);
  • 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); 
Questions connexes