Domanda

Ho un array di byte generato da un generatore di numeri casuali. Voglio mettere questo nel bitset STL.

Purtroppo, sembra che BitSet supporta solo i seguenti costruttori:

  1. Una serie di 1 e 0 come "10.101.011"
  2. Un unsigned long. (Il mio array di byte sarà più lungo)

L'unica soluzione che viene in mente ora è quello di leggere il bit di byte a poco e fare una serie di 1 e 0. Qualcuno ha una soluzione più efficiente?

È stato utile?

Soluzione

qualcosa di simile? (Non sono sicuro se la magia modello funziona qui come mi aspetto. Sono arrugginito in 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;
}

Altri suggerimenti

C'è un terzo costruttore per bitset<> - ci vuole alcun parametro e imposta tutti i bit a 0. Credo che avrete bisogno di utilizzare tale poi a piedi attraverso l'array chiamando set() per ogni bit in array di byte che è un 1.

Un po 'a forza bruta, ma funzionerà. Ci sarà un po 'di complessità per convertire il byte-index e il bit di offset all'interno di ogni byte a un indice bitset, ma non è niente un po' di pensiero (e magari una corsa attraverso nel debugger) non risolverà. Penso che sia più probabile più semplice ed efficiente che cercare di eseguire l'array attraverso una conversione stringa o un flusso.

Ragazzi, ho speso un sacco di tempo scrivendo una funzione inversa (bitset -> byte / char array). Eccolo:

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

Bene, cerchiamo di essere onesti, mi annoiavo e ho iniziato a pensare che ci doveva essere un modo leggermente più veloce di impostazione ogni 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;
}

Questo è davvero leggermente più veloce, almeno fino a quando l'array di byte è più piccolo di 30 elementi (a seconda delle vostre ottimizzazione-flag passati al compilatore). matrice più grande di quello e il tempo usato spostando il bitset rende l'impostazione ogni po 'più veloce.

è possibile inizializzare il bitset da un flusso. Non riesco a ricordare come disputare un byte [] in un flusso, ma ...

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

Ecco la mia applicazione utilizza modello di meta-programmazione.
I loop sono fatte nel tempo di compilazione.
Ho preso @strager versione, modificata al fine di prepararsi per TMP:

  • ordine di iterazione (in modo da poter fare ricorsione da esso) modificato;
  • riduzione del numero di variabili utilizzate.

Versione modificata con i cicli in un run-time:

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

Versione TMP basato su di esso:

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

codice client:

uint8_t arr[]={0x6A};
  std::bitset<8> b; 
  bytesToBitset<1>(arr,b);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top