Pregunta

Tengo una matriz de bytes generada por un generador de números aleatorios.Quiero poner esto en el conjunto de bits STL.

Desafortunadamente, parece que Bitset solo admite los siguientes constructores:

  1. Una cadena de unos y ceros como "10101011"
  2. Un largo sin firmar.(mi matriz de bytes será más larga)

La única solución que se me ocurre ahora es leer la matriz de bytes poco a poco y crear una cadena de unos y ceros.¿Alguien tiene una solución más eficiente?

¿Fue útil?

Solución

Algo como esto? (No estoy seguro si la magia plantilla funciona aquí como yo esperaría. Estoy oxidado 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;
}

Otros consejos

Hay una tercera constructor para bitset<> - que no toma ningún parámetro y establece todos los bits a 0. Creo que tendrá que usar ese entonces caminar a través de la matriz llamando set() para cada bit en la matriz de bytes que es un 1.

Un poco de fuerza bruta, sino que va a trabajar. Habrá un poco de complejidad para convertir el byte-índice y bit de desplazamiento dentro de cada byte a un índice bitset, pero no es nada un poco de pensamiento (y tal vez un recorrido por debajo del depurador) no resolverán. Creo que es más probable más simple y más eficiente que intentar ejecutar la matriz a través de una conversión de cadenas o una corriente.

Los individuos, que han pasado mucho tiempo escribiendo una función inversa (bitset -> bytes / matriz de caracteres). No es:

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

Bueno, seamos honestos, estaba aburrido y comencé a pensar que tenía que haber una forma un poco más rápida que configurar cada 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;
}

De hecho, esto es un poco más rápido, al menos siempre que la matriz de bytes tenga menos de 30 elementos (dependiendo de los indicadores de optimización pasados ​​al compilador).Una matriz más grande que esa y el tiempo utilizado para cambiar el conjunto de bits hacen que la configuración de cada bit sea más rápida.

se puede inicializar el bitset de una corriente. No puedo recordar como pelearse con un byte [] en una corriente, pero ...

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

Aquí está mi aplicación utilizando la plantilla de meta-programación.
Los bucles se hacen en el tiempo de compilación.
Tomé @strager versión, modificada con el fin de prepararse para TMP:

  • orden de iteración (para que yo pudiera hacer que la recursividad de él) cambió;
  • reducido número de variables utilizadas.

Versión modificada con bucles en un tiempo de ejecución:

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

versión TMP basado en él:

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

código de cliente:

uint8_t arr[]={0x6A};
  std::bitset<8> b; 
  bytesToBitset<1>(arr,b);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top