Получить байты из std :: vector <bool> - PullRequest
2 голосов
/ 16 февраля 2009

У меня есть что-то вроде следующего, и после заполнения его произвольным числом битов мне нужно получить байты для записи в файл. Я не вижу способа сделать это, и это кажется полезным, поэтому я должен что-то упустить. Есть идеи?

std::vector<bool> a;

a.push_back(true);
a.push_back(false);
a.push_back(false);
a.push_back(true);

a.push_back(false);
a.push_back(true);
a.push_back(true);
a.push_back(false);

Ответы [ 9 ]

7 голосов
/ 16 февраля 2009

std::vector <bool> на самом деле не содержит bools (т.е. байты), он содержит биты! В большинстве случаев это ошибка, и вам рекомендуется использовать std::deque <bool>, у которого нет этой «функции».

А если вы хотите, чтобы хранилище было непрерывным, используйте std::vector <char>.

2 голосов
/ 16 февраля 2009

Попробуйте это

void WriteOut(fstream& stream, const vector<bool>& data) {
  for (vector<bool>::const_iterator it = data.begin(); it != data.end(); it++) {
    stream << *it;
  }
}
1 голос
/ 16 февраля 2009

Почему бы вам не использовать вместо этого набор битов STL? У него есть специальные методы для преобразования значений набора битов в эквивалентное длинное значение или строковое представление:

http://www.cppreference.com/wiki/stl/bitset/start

1 голос
/ 16 февраля 2009

Сделай что-нибудь подобное

std::vector<bool> a;
a.push_back(true);
a.push_back(false);
//...
for (auto it = a.begin(); it != a.end();) // see 0x for meaning of auto
{
    unsigned b = 0;
    for (int i = 0; i < 8*sizeof(b); ++i)
    {
        b |= (*it & 1) << (8*sizeof(b) - 1 - i);
        ++it;
    }
    // flush 'b'
}

Итак, в итоге вы группируете куски битов, здесь я решил сгруппировать биты в собственные целые числа (что является оптимальным для целевой платформы). Я не проверяю индексы здесь, но это то, что вам придется сделать. Что я хотел бы сделать, так это проверить, сколько полных кусков я мог бы извлечь сначала, сделать это, а затем обработать любой остаток.

Также обратите внимание, что я заполняю биты слева направо (предполагая, что целевая архитектура имеет младший порядок), это означает, что сначала нужно заполнить msb.

Если вы делаете битовые манипуляции и все в таком духе, определите схему упаковки битов, и пусть это будет ваша структура данных. std :: bit_vector, std :: vector или :: dequeue на самом деле не имеют значения. Осторожно упакуйте свои биты в собственный целочисленный тип целевой платформы, что обеспечит наилучшую производительность.

1 голос
/ 16 февраля 2009

Обычно bool - это байт - вы можете просто перебирать вектор, используя vector :: iterator, и таким образом получать доступ к каждому значению.

std::vector<bool> a;

a.push_back(true);
a.push_back(false);

for(std::vector<bool>::iterator iter = a.begin(); iter != a.end(); ++iter)
{
    std::cout << *iter << std::endl;
}

Итерирует по каждому bool и выводит его в командную строку. Печать в файл относительно проста.

0 голосов
/ 30 июня 2018

Посмотрев на предложенные решения выше, я просто написал полностью работающую функцию.

  // Count number of bytes needed to contain the bits
  // and then copy 8 bit block as bytes.

  void writeAsBytes(const vector<bool> & inBits, vector<uint8_t> & outBytes) {
    int bitOffset = 0;
    const int maxBitOffset = (int) inBits.size();

    const bool emitMSB = true;

    int numBytes = (int)inBits.size() / 8;
    if ((inBits.size() % 8) != 0) {
      numBytes += 1;
    }

    for (int bytei = 0; bytei < numBytes; bytei++) {
      // Consume next 8 bits

      uint8_t byteVal = 0;

      for (int biti = 0; biti < 8; biti++ ) {
        if (bitOffset >= maxBitOffset) {
          break;
        }

        bool bit = inBits[bitOffset++];

        // Flush 8 bits to backing array of bytes.
        // Note that bits can be written as either
        // LSB first (reversed) or MSB first (not reversed).

        if (emitMSB) {
          byteVal |= (bit << (7 - biti));
        } else {
          byteVal |= (bit << biti);
        }
      }

      outBytes.push_back(byteVal);
    }
  }
0 голосов
/ 09 апреля 2010

Не помню, если std::vector<bool> требуется для упаковки, скорее всего это не так. Если бы это было так, вы могли бы получить доступ к члену :: data (), чтобы получить доступ к необработанным байтам.

0 голосов
/ 15 июля 2009

На самом деле вы могли бы сделать это:

copy(yourvector.begin(), yourvector.end(), std::ostreambuf_iterator<char>(outputstream));
0 голосов
/ 16 февраля 2009

Во-первых, вы хотите использовать bit_vector вместо вектора.

Во-вторых, нет способа сделать именно то, что вы хотите, используя bit_vector или vector. Они предназначены для коллекций, и их основной формат скрыт от вас (поэтому может быть решено хранить каждый тип bool как отдельный байт, а не упаковывать как 8 бит на байт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...