
- •Нижегородский государственный университет им. Н.И. Лобачевского
- •Оглавление
- •Предисловие
- •Глава 1. Вычисление значений функций
- •1.1. Операторы циклов
- •1.2. Операторы ветвления
- •Когда в программе нужно выбрать один из многочисленных вариантов, бывает целесообразным применять оператор-переключатель switch. Этот оператор называется ещё оператором множественного выбора [1].
- •Switch (выражение)
- •1.3. Алгоритмы, необходимые для написания программ
- •Глава 2. Суммирование рядов
- •Глава 3. Позиционная запись числа
- •Глава 4. Делители целого числа
- •5.1. Сортировка вставкой
- •5.2. Метод пузырька
- •5.3. Сортировка выбором
- •5.4. Быстрая сортировка
- •Глава 6. Работа с файлами. Построение массивов без повторений
- •6.1. Работа с файлами
- •6.2. Построение массивов без повторений
- •Глава 7. Обработка последовательности символов
- •7.1. Алгоритм выделения слова из строки
- •7.2. Выбор слов, подходящих под шаблон
- •7.3. Перевод прописных символов в строчные
- •Глава 8. Побитовые операции
- •Глава 9. Преобразование и построение матриц
- •Содержимое файла “input.Txt”
- •Глава 10. Структуры
- •Выделение памяти под объект coat
- •Содержимое файла "input.Txt".
- •Содержимое файла "outout.Txt"
- •Содержимое файла "input.Txt"
- •11. Динамические структуры данных
- •11.1. Односвязные списки
- •11.2. Очереди
- •11.3. Стеки
- •Содержимое файла “input.Txt”
- •Содержимое файла “input.Txt”
- •Список литературы
Глава 8. Побитовые операции
Побитовые операции можно применять только к целочисленным операндам типа char, short, int, long. Они действуют на отдельные разряды двоичного представления чисел. В С++ определены следующие побитовые операции [32]:
| – побитовое логическое ИЛИ;
& – побитовое логическое И;
^ – побитовое исключающее ИЛИ;
~ – побитовое логическое отрицание;
<< – сдвиг влево;
>> – сдвиг вправо.
Результаты действия побитовых операций на операнды a и b представлены в табл. 8.1.
Таблица 8.1
Побитовые операции
a |
b |
a|b |
a&b |
a^b |
~a |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
Операция побитового логического отрицания (~) является унарной. В результате этой операции каждый бит, имеющий значение 1, становится равным 0 и наоборот. Данная операция называется также дополнением до единицы или инверсией.
Результатом операции сдвига влево (<<) является левый операнд, сдвинутый влево на число позиций, которое указано в правом операнде. Освобождающиеся младшие разряды заполняются нулями [24, 25]. Данная операция может применяться для умножения на число, равное степени числа 2, в соответствии с правилом:
x << n эквивалентно умножению х на 2 в степени n.
Результатом операции сдвига вправо (>>) является левый операнд, сдвинутый вправо на число позиций, которое указано в правом операнде. Освобождающиеся старшие разряды заполняются нулями для переменных типа unsigned либо значением старшего (знакового) бита для данных другого типа [24, 25]. Данная операция может применяться для деления на число, равное степени числа 2, в соответствии с правилом:
x >> n эквивалентно делению х на 2 в степени n.
Следует отметить, что перед выполнением побитовых операций нужно преобразовывать знаковые целые числа в беззнаковые целые.
Листинг 8.1. Для печати содержимого памяти, отведенной под переменную типа unsigned int, может быть использована функция, в которой создается массив, и элементы массива заполняются следующим образом:
Создается шаблон, содержащий единицу в старшем разряде.
Проверяется побитовое умножение исходного числа на шаблон и в массив заносится символ ‘1’, если это произведение отлично от нуля, и ‘0’ – в противном случае.
Затем шаблон сдвигается вправо на один бит.
Для более легкого чтения информации после каждых 8 битов в массив заносится пробел.
Операция повторяется до тех пор, пока шаблон отличен от нуля.
//L8_1.cpp
void print_bit(unsigned int x)
{
unsigned int sh=~0, i=0, k=0;
sh=~(sh>>1); //Шаблон с 1 в старшем разряде
char s[40];
while(sh>0)
{
s[i++]=sh&x?'1':'0';
k++;
if(k==8)
{
s[i++]=' ';
k=0;
}
sh>>=1; //Сдвиг шаблона в следующий разряд
}
s[i]='\0';
cout<<s<<'\n';
}
Для успешной проверки данной функции следует вводить числа в шестнадцатеричном виде, так как каждая шестнадцатеричная цифра представляется четырьмя двоичными разрядами.
Листинг 8.2. Программа печатает двоичное представление числа с использованием функции, приведенной в листинге 8.1.
//L8_2.cpp
#include <fstream>
#include <iostream>
using namespace std;
int main( )
{
setlocale(LC_CTYPE,"russian");
unsigned int n;
do
{
cout<<"Введите неотрицательное n ";
cin>>hex>>n; //Ввол числа в шестнадцатеричной
//системе счисления.
}while(n<0);
print_bit(n); //Печать числа в двоичной системе числения
cin.get();
cin.get();
return 0;
}
Результат работы программы листинга 8.2 приведен на рис. 8.1.
Рис. 8.1. Результат работы программы листинга 8.2
Листинг 8.3. В заданном числе инвертировать n битов с позиции k вправо. При вводе данных следует контролировать, чтобы позиция инвертируемого бита и количество инвертируемых битов не выходили за пределы числа. Для построения необходимо создать шаблон, содержащий 1 в инвертируемых позициях и 0 в остальных.
//L8_3.cpp
#include <stdio.h>
#include <tchar.h>
#include <iostream>
using namespace std;
void print_bit(unsigned int x);
int main( )
{
setlocale(LC_CTYPE,"russian");
unsigned int x, n, k, m, sh, y;
m=sizeof(unsigned int)*8;
do
{
cout<<"Введите неотрицательное x ";
cin>>hex>>x;
}while(x<0);
do
{
cout<<"Введите позицию k и число инвертируемых битов n ";
cin>>dec>>k>>n;
}while(!(k<=m&&n<=k));
print_bit(x);
sh=~0;
sh=((sh<<m-k)>>m-n)<<k-n;
y=~(x&sh)&sh;
x=x&(~sh)|y;
print_bit(x);
return 0;
}
void print_bit(unsigned int x)
{
unsigned int sh=~0,k=0,i=0;
char s[40];
sh=~(sh>>1);
cout<<'\n';
while(sh!=0)
{
s[i++]=(sh&x)?'1':'0';
k++;
if(k%8==0)
s[i++]=' ';
sh=sh>>1;
}
s[i]='\0';
cout<<s<<'\n';
}
На рис. 8.2 приведен результат выполнения программы листинга 8.3.
Рис. 8.2. Результат работы программы листинга 8.3
Побитовые операции можно использовать для укрупненного начертания слов. Укрупненное начертание какого-либо символа связано с заданием этого символа в виде таблицы [15]. Заполненные клетки таблицы образуют нужный контур символа. Содержимое такой таблицы можно закодировать с помощью 1 (клетка заполнена) и 0 (клетка не заполнена). Пусть такая таблица состоит из 7 × 5 элементов. Тогда для идентификации символа достаточно пяти семиразрядных двоичных чисел. Каждое из них будет кодировать один из пяти вертикальных слоев. Например, начертание символа “Н” кодируется следующими двоичными числами: 1111111 (первый и пятый вертикальные слои таблицы), 10 (второй, третий и четвертый слои таблицы). При этом переход от младших разрядов к старшим соответствует просмотру исходной таблицы сверху вниз (рис. 8.3).
|
0 |
0 |
0 |
|
Младший разряд |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
Старший разряд |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
Рис. 8.3. Кодирование начертания символа “Н”
Для распечатки символа необходимо установить, какие двоичные цифры находятся в соответствующих разрядах всех пяти чисел: 0 – печатать пробел, 1 – печатать выбранный символ.
Листинг 8.4. Вывести на экран дисплея укрупненное начертание слов: “ННГУ” и “МЕХМАТ”.
//L8_4.cpp
#include "stdafx.h"
#include <stdio.h>
#include <locale>
void _tmain()
{setlocale (LC_ALL, "Russian");
int i, j, k, n;
int B[6][5], D[6][5];
static char s[]="ННГУ", s2[]="МЕХМАТ";
char c, e;
for (n=0; (c=s[n])!='\0'; n++)
switch (c)
{
case 'Н': B[n][0]=B[n][4]=0177;
B[n][1]=B[n][2]=B[n][3]=010;
break;
case 'Г': B[n][0]=0177;
B[n][1]=B[n][2]=B[n][3]=01;
B[n][4]=03;
break;
case 'У': B[n][0]=047;
B[n][1]=B[n][2]=B[n][3]=0110;
B[n][4]=077;
break;
}
for (k=0; k<7; k++) // k – разряд
{ for (i=0; i<n; i++) // i – буква
{ j=0; // j - слой
do
{if (B[i][j] & 01) //Выделение k-го разряда каждого
//из чисел, кодирующих букву.
printf("%c", s[i]);
else
printf("%c", ' ');
B[i][j]=B[i][j]>>1; //Сдвиг вправо на одну позицию
//всех разрядов числа.
j++;
}
while (j<5);
printf("%s", " ");
}
printf ("\n");
}
printf ("\n");
for (n=0; (e=s2[n])!='\0'; n++)
switch (e)
{
case 'М': D[n][0]=D[n][4]=0177;
D[n][1]=D[n][3]=02;
D[n][2]=04;
break;
case 'Е': D[n][0]=0177;
D[n][1]=D[n][2]=D[n][3]=0111;
D[n][4]=0101;
break;
case 'Х': D[n][0]=D[n][4]=0143;
D[n][1]=D[n][3]=024;
D[n][2]=010;
break;
case 'А': D[n][0]=D[n][4]=0176;
D[n][1]=D[n][2]=D[n][3]=011;
break;
case 'Т': D[n][0]=D[n][1]=D[n][3]=D[n][4]=01;
D[n][2]=0177;
break;
}
for (k=0; k<7; k++)
{ for (i=0; i<n; i++)
{ j=0;
do {
if (D[i][j] & 01) //Выделение k-го разряда каждого
//из чисел, кодирующих букву.
printf("%c", s2[i]);
else
printf("%c", ' ');
D[i][j] = D[i][j] >> 1; //Сдвиг вправо на одну позицию
//всех разрядов числа.
j++;
}
while (j<5);
printf("%s", " ");
}
printf ("\n");
}
printf ("\n");
}
Результат выполнения программы листинга 8.4 приведен на рис. 8.4.
Рис. 8.4. Результат работы программы листинга 8.4
Упражнения
Написать функцию, заменяющую n правых битов числа x на n правых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, заменяющую n левых битов числа x на n правых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, заменяющую n правых битов числа x на n правых инвертированных битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, которая циклически перемещает n правых битов числа х в старшие биты, не меняя их порядка. Провести вычисление для заданного числа x и заданного количества правых битов n. Результат записать в файл.
Написать функцию, заменяющую n левых битов числа x на n правых битов этого же числа. Провести вычисление для заданного числа x и заданного количества левых битов n. Результат записать в файл.
Написать функцию, заменяющую n левых битов числа x на инвертированные n левых битов этого числа. Провести вычисление для заданного числа x и заданного количества левых битов n. Результат записать в файл.
Написать функцию, заменяющую n левых битов числа x на n левых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, заменяющую n битов с позиции p числа x на n правых инвертированных битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, заменяющую n левых битов числа x на n правых инвертированных битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, которая циклически перемещает n левых битов числа х в младшие биты, не меняя их порядка. Провести вычисление для заданного числа x и заданного количества правых битов n. Результат записать в файл.
Написать функцию, заменяющую n левых битов числа x на инвертированные n правых битов этого числа. Провести вычисление для заданного числа x и заданного количества левых битов n. Результат записать в файл.
Написать функцию, заменяющую n правых битов числа x на инвертированные n правых битов этого числа. Провести вычисление для заданного числа x и заданного количества правых битов n. Результат записать в файл.
Написать функцию, определяющую количество единиц в двоичном представлении целого числа. Провести вычисление для заданного числа х. Результат записать в файл.
Написать функцию, определяющую разность между количеством нулей и единиц в двоичном представлении целого числа. Провести вычисление для заданного числа х. Результат записать в файл.
Написать функцию, заменяющую n битов с позиции p числа x на n правых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, заменяющую n битов с позиции p числа x на n левых инвертированных битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, заменяющую n битов с позиции p числа x на инвертированные. Провести вычисление для заданного числа x и заданного количества битов n. Результат записать в файл.
Написать функцию, определяющую количество нулей в двоичном представлении целого числа. Провести вычисление для заданного числа х. Результат записать в файл.
Написать функцию, заменяющую n битов с позиции p числа x на n левых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, заменяющую n битов с позиции p числа x на n правых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, определяющую количество битов, значение которых в двоичном представлении чисел x и y совпадают. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, определяющую количество битов, значение которых в двоичном представлении чисел x и y не совпадают. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, определяющую разность между количеством единиц в двоичном представлении чисел x и y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, определяющую разность между количеством нулей в двоичном представлении чисел x и y. Провести вычисление для заданных чисел x и y. Результат записать в файл.
Написать функцию, заменяющую n левых битов числа x на n битов с позиции p числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.