Frage

Ich habe ein Byte-Array durch einen Zufallszahlengenerator erzeugt wird. Ich möchte diese in die STL bitset setzen.

Leider sieht es so aus Bitset nur die folgenden Konstrukteure unterstützt:

  1. Eine Reihe von 1 und 0 wie "10101011"
  2. Ein unsigned long. (Mein Byte-Array länger sein wird)

Die einzige Lösung, die ich jetzt denken kann, ist den Byte-Array Bit für Bit zu lesen und eine Reihe von 1 und 0 machen. Hat jemand eine effizientere Lösung?

War es hilfreich?

Lösung

So etwas wie das? (Nicht sicher, ob Vorlage Magie funktioniert hier wie ich erwarten würde. Ich bin rostig 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;
}

Andere Tipps

Es gibt einen dritten Konstruktor für bitset<> - es braucht keine Parameter und setzt alle Bits auf 0 glaube ich Sie verwenden müssen, dass dann durch das Feld gehen für jedes Bit in dem Byte-Array Aufruf set(), die ein 1. ist

Ein bisschen Brute-Force, aber es wird funktionieren. Es wird ein wenig Komplexität, die Byte-Index und Bit in jedem Byte zu einem bitset Index-Offset zu konvertieren, aber es ist nichts, was ein wenig Gedanken (und vielleicht auch ein Lauf durch unter dem Debugger) nicht lösen. Ich denke, es ist sehr wahrscheinlich einfacher und effizienter als zu versuchen, das Array durch eine String-Konvertierung oder einen Strom zu laufen.

Leute, ich habe viel Zeit damit verbracht, durch eine umgekehrte Funktion (bitset -> Byte / char-Array) zu schreiben. Da ist 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")

Nun, seien sie ehrlich, ich war gelangweilt und begann zu denken, hatte eine etwas schnellere Art und Weise sein, als jedes Bit zu setzen.

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

Das ist in der Tat etwas schneller, zumindest so lange, wie das Byte-Array kleiner als 30 Elementen (je nach Optimierungs-Flags übergeben Compiler). Größere Array als das, und die Zeit, die von den bitset Verschiebung machen jedes Bit schneller einstellen.

können Sie die bitset aus einem Stream initialisieren. Ich kann mich nicht daran erinnern, wie ein Byte hadern [] in einen Strom, aber ...

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

Hier ist meine Implementierung mit Vorlage Meta-Programmierung.
Loops werden in der Übersetzungszeit getan.
Ich nahm @strager Version, modifiziert sie, um für TMP vorzubereiten:

  • geändert Reihenfolge der Iteration (so dass ich Rekursion von ihm machen könnte);
  • reduzierte Anzahl von verwendeten Variablen.

Modifizierte Version mit Schleifen in einer Laufzeit:

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

TMP-Version basiert auf sie:

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

Client-Code:

uint8_t arr[]={0x6A};
  std::bitset<8> b; 
  bytesToBitset<1>(arr,b);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top