Опубликован: 14.12.2010 | Уровень: для всех | Доступ: свободно
Лекция 17:

Операции с разрядами (битами) в языке С

< Лекция 16 || Лекция 17: 1234 || Лекция 18 >

Задание 4

  1. В качестве исходных десятичных чисел примите год и число рождения пользователя.
  2. Произведите операцию исключающего ИЛИ над двумя десятичными числами в соответствии с предыдущим пунктом задания. Операцию выполните в главной функции main().
  3. Подсчитайте число итераций оператора цикла 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.

Пример побитовых операций с шестнадцатеричными числами

Рис. 16.5. Пример побитовых операций с шестнадцатеричными числами

Задание 5

  1. В программе предусмотрите вывод двоичных эквивалентов для введенных чисел.
  2. Измените программу так, чтобы операции с переключателем switch выполнялись в функции printHex2Bin().
  3. В функции сформируйте одномерный массив символов двоичного эквивалента заданного шестнадцатеричного числа. Предусмотрите вывод результата.
  4. Выполните программу со всеми поразрядными операциями при вводе чисел: года и дня рождения пользователя.
  5. Напишите программу перевода десятичных чисел в восьмеричные (вместо *dec2hex() ). Предусмотрите также поразрядные операции с выводом двоичных эквивалентов.
  6. В программе предусмотрите копирование консольного содержания в текстовый файл с именем 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(), которая к имеющемуся значению добавляет содержимое строки от функции dec2hex(). После еще добавляется суффикс u типа unsigned int. Для получения собственно шестнадцатеричного числа выполнена операция записи строки в файл и чтения из файла в шестнадцатеричном формате. Далее используется функция rotate() из [16.2]. Ротация переменной на n битов влево производится в соответствии с алгоритмом, состоящим из трех шагов [5]. Сначала извлекаются левые n бит исходного значения в отдельную переменную ( bits ), которая сдвигается вправо (с помощью поразрядного сдвига >> ) на количество позиций ( 32–n ). Затем исходное значение ( var ) сдвигается влево на n битов и наконец над получившимся значением и из влеченными битами производится операция поразрядной дизъюнкции "ИЛИ" ( | ). Аналогичные действия выполняются при сдвиге вправо.

Возможный результат выполнения программы показан на рис. 16.6.

Результат ротации  заданного числа

Рис. 16.6. Результат ротации заданного числа
< Лекция 16 || Лекция 17: 1234 || Лекция 18 >
Мухаммадюсуф Курбонов
Мухаммадюсуф Курбонов
Андрей Поляков
Андрей Поляков
Россия, Челябинск, Южно-Уральский Государственный Университет (НИУ)