4.12. Класс bitset
Как мы уже говорили, необходимость создавать сложные выражения для манипуляции битовыми векторами затрудняет использование встроенных типов данных. Класс bitset упрощает работу с битовым вектором. Вот какое выражение нам приходилось писать в предыдущем разделе для того, чтобы “взвести” 27-й бит: quiz1 |= 1<<27; При использовании bitset то же самое мы можем сделать двумя способами: quiz1[27] = 1; или quiz1.set(27); (В нашем примере мы не используем нулевой бит, чтобы сохранить “естественную”
нумерацию. На самом деле, нумерация битов начинается с 0.) #include <bitset> Объект типа bitset может быть объявлен тремя способами. В определении по умолчанию мы просто указываем размер битового вектора: bitset<32> bitvec; Это определение задает объект bitset, содержащий 32 бита с номерами от 0 до 31. Все биты инициализируются нулем. С помощью функции any() можно проверить, есть ли в векторе единичные биты. Эта функция возвращает true, если хотя бы один бит отличен от нуля. Например: bool is_set = bitvec.any(); Переменная is_set получит значение false, так как объект bitset по умолчанию инициализируется нулями. Парная функция none() возвращает true, если все биты равны нулю: sbool is_not_set = bitvec.none(); Изменить значение отдельного бита можно двумя способами: воспользовавшись функциями set() и reset() или индексом. Так, следующий цикл выставляет в 1 каждый четный бит: for ( int index=0; index<32; ++index ) if ( index % 2 == 0 ) bitvec[ index ] = 1; Аналогично существует два способа проверки значений каждого бита – с помощью функции test() и с помощью индекса. Функция () возвращает true, если соответствующий бит равен 1, и false в противном случае. Например: if ( bitvec.test( 0 )) // присваивание bitvec[0]=1 сработало!; Значения битов с помощью индекса проверяются таким образом: cout << "bitvec: включенные биты:\n\t"; for ( int index = 0; index < 32; ++-index ) if ( bitvec[ index ] ) cout << index << " "; cout << endl; Следующая пара операторов демонстрирует сброс первого бита двумя способами: bitvec.reset(0); bitvec[0] = 0; Функции set() и reset() могут применяться ко всему битовому вектору в целом. В этом случае они должны быть вызваны без параметра. Например: // сброс всех битов bitvec.reset(); if (bitvec.none() != true) // что-то не сработало // установить в 1 все биты вектора bitvec if ( bitvec.any() != true ) // что-то опять не сработало Функция flip() меняет значение отдельного бита или всего битового вектора: bitvec.f1ip( 0 ); // меняет значение первого бита bitvec[0].flip(); // тоже меняет значение первого бита bitvec.flip(); // меняет значения всех битов Существуют еще два способа определить объект типа bitset. Оба они дают возможность проинициализировать объект определенным набором нулей и единиц. Первый способ – явно задать целое беззнаковое число как аргумент конструктору. Начальные N позиций битового вектора получат значения соответствующих двоичных разрядов аргумента. Например: bitset< 32 > bitvec2( Oxffff ); инициализирует bitvec2 следующим набором значений: 00000000000000001111111111111111 В результате определения 00000000000000000000000000001010 В качестве аргумента конструктору может быть передано и строковое значение, состоящее из нулей и единиц. Например, следующее определение инициализирует bitvec4 тем же набором значений, что и bitvec3: // эквивалентно bitvec3 string bitva1( "1010" ); bitset< 32 > bitvec4( bitval ); Можно также указать диапазон символов строки, выступающих как начальные значения для битового вектора. Например: // подстрока с шестой позиции длиной 4: 1010 string bitval ( "1111110101100011010101" ); bitset< 32 > bitvec5( bitval, 6, 4 ); Мы получаем то же значение, что и для bitvec3 и bitvec4. Если опустить третий
параметр, подстрока берется до конца исходной строки: bitset<32> bitvec7 = bitvec2 & bitvec3; Объект bitvec7 инициализируется результатом побитового И двух битовых векторов bitvec2 и bitvec3. bitset<32> bitvec8 = bitvec2 | bitvec3; Здесь bitvec8 инициализируется результатом побитового ИЛИ векторов bitvec2 и bitvec3. Точно так же поддерживаются и составные операции присваивания и сдвига. Упражнение 4.15Допущены ли ошибки в приведенных определениях битовых векторов? (a) bitset<64> bitvec(32); (b) bitset<32> bv( 1010101 ); (c) string bstr; cin >> bstr; bitset<8>bv( bstr ); (d) bitset<32> bv; bitset<16> bvl6( bv ); Упражнение 4.16Допущены ли ошибки в следующих операциях с битовыми векторами? extern void bitstring(const char*); bool bit_on (unsigned long, int); bitset<32> bitvec; (a) bitsting( bitvec.to_string().c_str() ); (b) if ( bit_on( bitvec.to_1ong(), 64 )) ... (c) bitvec.f1ip( bitvec.count() ); Упражнение 4.17Дана последовательность: 1,2,3,5,8,13,21. Каким образом можно инициализировать
объект bitset<32> для ее представления? Как присвоить значения для представления
этой последовательности пустому битовому вектору? Напишите вариант инициализации
и вариант с присваиванием значения каждому биту. Содержание |
2022-04-21 13:04:50 MV в таблице в 3-х строкax flip/set/reset(pos) часть текста из третьего столбца оказалась во втором Оставить комментарий: |