Операции с разрядами (битами) в языке С
Задание 4
- В качестве исходных десятичных чисел примите год и число рождения пользователя.
- Произведите операцию исключающего ИЛИ над двумя десятичными числами в соответствии с предыдущим пунктом задания. Операцию выполните в главной функции main().
- Подсчитайте число итераций оператора цикла for.
Пример 5. Напишите программу выполнения поразрядных операций с шестнадцатеричными числами, которые получаются после преобразования десятичных чисел, введенных с клавиатуры.
Программный код решения примера:
#include <stdio.h> #include <conio.h> const char basestr[16] = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F'}; const char *two16[16] = {"0000","0001","0010","0011","0100","0101","0110","0111", "1000","1001", // 0,1,2,3,4,5,6,7,8,9 "1010","1011","1100","1101","1110","1111"}; //A,B,C,D,E,F // Прототипы функций char *dec2hex(unsigned int var); void printHex2Bin(unsigned int number); // Главная функция int main (void) { int d12; unsigned int number1, number2; char ch, *NUM1; printf("\n The program on demonstration digit-by-digit operations\n with hexadecimal numbers\n"); printf("\n\t Enter the unsigned number of N1: "); scanf_s("%u", &number1); printf("\t Enter the unsigned number of N2: "); scanf_s("%u", &number2); _flushall(); //Для контроля перевода десятичного числа в шестнадцатеричное printf("\n\t Hexadecimal numbers: %X, %X\n", number1, number2); printf("\n\t Enter bit operation ( &, |, ^, ~ ): "); scanf_s("%c", &ch); switch (ch) { case '&': NUM1 = dec2hex(number1 & number2); printHex2Bin(number1 & number2); break; case '|': NUM1 = dec2hex(number1 | number2); printHex2Bin(number1 | number2); break; case '^': NUM1 = dec2hex(number1 ^ number2); printHex2Bin(number1 ^ number2); break; case '~': printf("\t Type 1 - for the first number; type 2 - for the second number: "); scanf_s("%d", &d12); _flushall(); if (d12 == 1) { NUM1 = dec2hex(~number1); printHex2Bin(~number1); } else { NUM1 = dec2hex(~number2); printHex2Bin(~number2); } break; default : fprintf(stdout, "\n\t Unknown symbol."); break; } printf("\n\n Press any key: "); _getch(); return 0; } char *dec2hex(unsigned int var) { int number[64]; int i, j, k = 0; unsigned int base = 16; char Hex[128], *PTR; PTR = Hex; do { number[k] = var % base; ++ k; var /= base; } while (var != 0); for (i = k-1, j = 0; i >= 0; --i, ++j) { Hex[j] = (char )basestr[number[i]]; PTR[j] = Hex[j]; } PTR[j] = '\0'; return (PTR); } void printHex2Bin(unsigned int number) { unsigned int num = 1 << 31; unsigned int i; printf("\n Hexadecimal number: %s\n", dec2hex(number)); printf(" Binary equivalent:\n "); for (i = 1; i <= 32; ++i) { printf("%2c", (number & num )? '1' : '0'); number <<= 1; if (i % 8 == 0) printf(" "); } }
В программе используется следующий указатель на функцию:
char *dec2hex(unsigned int var);
Это дает возможность возвращать указатель с адресом необходимого символьного массива. Обратите внимание на выполнение операции завершения строки в функции *dec2hex() для указателя *PTR.
Возможный результат выполнения программы показан на рис. 16.5.
Задание 5
- В программе предусмотрите вывод двоичных эквивалентов для введенных чисел.
- Измените программу так, чтобы операции с переключателем switch выполнялись в функции printHex2Bin().
- В функции сформируйте одномерный массив символов двоичного эквивалента заданного шестнадцатеричного числа. Предусмотрите вывод результата.
- Выполните программу со всеми поразрядными операциями при вводе чисел: года и дня рождения пользователя.
- Напишите программу перевода десятичных чисел в восьмеричные (вместо *dec2hex() ). Предусмотрите также поразрядные операции с выводом двоичных эквивалентов.
- В программе предусмотрите копирование консольного содержания в текстовый файл с именем compX.txt, где Х – номер компьютера, за которым выполняется лабораторная работа.
Пример 6. Напишите программу ротации битов для заданных чисел, представленных в шестнадцатеричном виде, когда биты с самых крайних разрядов не теряются, а переносятся на противоположную сторону [16.2].
Программный код решения примера:
#include <stdio.h> #include <conio.h> #include <string.h> const char basestr[16] = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F'}; int main (void) { int n; unsigned int number, uns; char *NUM1, str[128] = "0x", un[] = "u"; FILE *fid; // Прототипы функций char *dec2hex (unsigned int var); unsigned int rotate (unsigned int value, int n); printf("\n The program for demonstration of bit-by-bit rotation \n of the numbers set in a hexadecimal kind\n"); printf("\n\t Enter the unsigned decimal: "); scanf_s("%u", &number); printf("\t Enter the number of bits of rotation: "); scanf_s("%d", &n); //Для контроля перевода десятичного числа в шестнадцатеричное printf("\n\t Hexadecimal numbers: %X\n", number); NUM1 = dec2hex(number); strcat_s(str, 127, NUM1); strcat_s(str, 127, un); fopen_s(&fid,"temp.txt", "w"); fprintf(fid,"%s", str); fclose(fid); fopen_s(&fid,"temp.txt", "r"); fscanf_s(fid,"%x", &uns); fclose(fid); printf("\n\t After rotating %d-bits: %X\n", n, rotate(uns, n)); printf("\n\n Press any key: "); _getch(); return 0; } //Функция перевода десятичного числа в шестнадцатеричное char *dec2hex(unsigned int var) { int number[64]; int i, j, k = 0; unsigned int base = 16; char Hex[128], *PTR; PTR = Hex; do { number[k] = var % base; ++ k; var /= base; } while (var != 0); for (i = k-1, j = 0; i >= 0; --i, ++j) { Hex[j] = basestr[number[i]]; PTR[j] = Hex[j]; } PTR[j] = '\0'; return (PTR); } //Функция ротации числа влево или вправо unsigned int rotate (unsigned int var, int n) { unsigned int result, bits; // Ограничение диапазона ротации if (n > 0) n = n % 32; else n = -(-n % 32); if (n == 0) result = var; else if (n > 0) // Ротация влево { bits = var >> (32 - n); result = var << n | bits; } else // Ротация вправо { n = -n; bits = var << (32 - n); result = var >> n | bits; } return (result); }
В программе сначала формируется символьное выражение шестнадцатеричного числа с помощью функции dec2hex(). Затем оно приводится к стандартному виду с помощью функции strcat_s(), которая к имеющемуся значению 0х добавляет содержимое строки от функции dec2hex(). После еще добавляется суффикс u типа unsigned int. Для получения собственно шестнадцатеричного числа выполнена операция записи строки в файл и чтения из файла в шестнадцатеричном формате. Далее используется функция rotate() из [16.2]. Ротация переменной на n битов влево производится в соответствии с алгоритмом, состоящим из трех шагов [5]. Сначала извлекаются левые n бит исходного значения в отдельную переменную ( bits ), которая сдвигается вправо (с помощью поразрядного сдвига >> ) на количество позиций ( 32–n ). Затем исходное значение ( var ) сдвигается влево на n битов и наконец над получившимся значением и из влеченными битами производится операция поразрядной дизъюнкции "ИЛИ" ( | ). Аналогичные действия выполняются при сдвиге вправо.
Возможный результат выполнения программы показан на рис. 16.6.