سؤال

لدي مصفوفة بايت تم إنشاؤها بواسطة مولد أرقام عشوائي.أريد أن أضع هذا في مجموعة بت STL.

لسوء الحظ، يبدو أن Bitset يدعم فقط المنشئات التالية:

  1. سلسلة من 1 و0 مثل "10101011"
  2. طويلة غير موقعة.(ستكون مجموعة البايت الخاصة بي أطول)

الحل الوحيد الذي يمكنني التفكير فيه الآن هو قراءة مصفوفة البايت شيئًا فشيئًا وإنشاء سلسلة من 1 و0.هل لدى أي شخص حل أكثر كفاءة؟

هل كانت مفيدة؟

المحلول

شيء من هذا القبيل؟(لست متأكدًا مما إذا كان سحر القالب يعمل هنا كما أتوقع.أنا صدئ في 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;
}

نصائح أخرى

هناك منشئ ثالث لـ bitset<> - لا يأخذ أي معلمات ويضبط جميع البتات على 0.أعتقد أنك ستحتاج إلى استخدام ذلك ثم المرور عبر استدعاء المصفوفة set() لكل بت في مصفوفة البايت يكون 1.

القليل من القوة الغاشمة، لكنها ستنجح.سيكون هناك القليل من التعقيد لتحويل مؤشر البايت وإزاحة البت داخل كل بايت إلى فهرس مجموعة البتات، ولكن لا يوجد شيء لن يحله القليل من التفكير (وربما يمر عبر مصحح الأخطاء).أعتقد أنه على الأرجح أبسط وأكثر كفاءة من محاولة تشغيل المصفوفة من خلال تحويل سلسلة أو دفق.

يا رفاق، لقد قضيت الكثير من الوقت في كتابة دالة عكسية (مجموعة البت -> مصفوفة البايت/الحرف).ذلك هو:

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

حسنًا، لنكن صادقين، لقد شعرت بالملل وبدأت أعتقد أنه يجب أن تكون هناك طريقة أسرع قليلاً من ضبط كل جزء.

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

وهذا بالفعل أسرع قليلاً، على الأقل طالما أن مصفوفة البايت أصغر من 30 عنصرًا (اعتمادًا على علامات التحسين التي تم تمريرها إلى المترجم).مجموعة أكبر من ذلك والوقت المستخدم في تحويل مجموعة البتات يجعل ضبط كل بتة أسرع.

يمكنك تهيئة مجموعة البت من الدفق.لا أستطيع أن أتذكر كيفية الجدل حول بايت [] في دفق، ولكن ...

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

هذا هو التنفيذ الخاص بي باستخدام البرمجة الفوقية للقالب.
تتم الحلقات في وقت الترجمة.
لقد أخذت إصدار @strager وقمت بتعديله للتحضير لـ TMP:

  • تم تغيير ترتيب التكرار (حتى أتمكن من إجراء التكرار منه)؛
  • انخفاض عدد المتغيرات المستخدمة.

نسخة معدلة مع حلقات في وقت التشغيل:

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 يعتمد عليه:

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

رمز العميل:

uint8_t arr[]={0x6A};
  std::bitset<8> b; 
  bytesToBitset<1>(arr,b);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top