bool hasPassed = quiz1 (127);

При использовании побитовых операций подобным образом очень легко допустить ошибку. Поэтому чаще всего такие операции инкапсулируются в макросы препроцессора или встроенные функции:

inline boo1 bit_on (unsigned int ui, int pos)

{

return u1 ( 1 pos );

}

Вот пример использования:

enum students { Danny = 1, Jeffrey, Ethan, Zev, Ebie, // ...

AnnaP = 26, AnnaL = 27 };

const int student_size = 27;

// наш битовый вектор начинается с 1

bool has_passed_quiz[ student_size+l ];

for ( int index = 1; index = student_size; ++-index )

has_passed_quiz[ index ] = bit_on( quiz1, index );

Раз уж мы начали инкапсулировать действия с битовым вектором в функции, следующим шагом нужно создать класс. Стандартная библиотека С++ включает такой класс bitset, его использование описано ниже.

Упражнение 4.12

Даны два целых числа:

unsigned int ui1 = 3, ui2 = 7;

Каков результат следующих выражений?

(a) ui1 ui2 (c) uil | ui2

(b) ui1 ui2 (d) uil || ui2

Упражнение 4.13

Используя пример функции bit_on(), создайте функции bit_turn_on() (выставляет бит в 1), bit_turn_off() (сбрасывает бит в 0), flip_bit() (меняет значение на противоположное) и bit_off() (возвращает true, если бит равен 0). Напишите программу, использующую ваши функции.

Упражнение 4.14

В чем недостаток функций из предыдущего упражнения, использующих тип unsigned int? Их реализацию можно улучшить, используя определение типа с помощью typedef или механизм функций-шаблонов. Перепишите функцию bit_on(),применив сначала typedef, а затем механизм шаблонов.

<p>4.12. Класс bitset</p>

Операция

Значение

Использование

test(pos)

Бит pos равен 1?

a.test(4)

any()

Хотя бы один бит равен 1?

a.any()

none()

Ни один бит не равен 1?

a.none()

count()

Количество битов, равных 1

a.count()

size()

Общее количество битов

a.size()

[pos]

Доступ к биту pos

a[4]

flip()

Изменить значения всех

a.flip()

flip(pos)

Изменить значение бита pos a.fli

p(4)

set()

Выставить все биты в 1

a.set()

set(pos)

Выставить бит pos в 1 a.se

t(4)

reset()

Выставить все биты в 0

a.reset()

reset(pos)

Выставить бит pos в 0 a.rese

t(4)

Как мы уже говорили, необходимость создавать сложные выражения для манипуляции битовыми векторами затрудняет использование встроенных типов данных. Класс bitset упрощает работу с битовым вектором. Вот какое выражение нам приходилось писать в предыдущем разделе для того, чтобы “взвести” 27-й бит:

quiz1 |= 127;

При использовании bitset то же самое мы можем сделать двумя способами:

quiz1[27] = 1;

или

quiz1.set(27);

(В нашем примере мы не используем нулевой бит, чтобы сохранить “естественную” нумерацию. На самом деле, нумерация битов начинается с 0.)

Для использования класса bitset необходимо включить заголовочный файл:

#include bitset

Объект типа bitset может быть объявлен тремя способами. В определении по умолчанию мы просто указываем размер битового вектора:

bitset32 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; index32; ++index )

if ( index % 2 == 0 )

bitvec[ index ] = 1;

Аналогично существует два способа проверки значений каждого бита – с помощью функции test() и с помощью индекса. Функция () возвращает true, если соответствующий бит равен 1, и false в противном случае. Например:

if ( bitvec.test( 0 ))

Перейти на страницу:

Похожие книги