/ws12/get-bit/src/get-bit.c
C | 214 lines | 46 code | 13 blank | 155 comment | 8 complexity | 38794205787733ec0727371b58c3e459 MD5 | raw file
- /**
- * @section Описание
- *
- * Программа выводит значения бита заданного числа.
- * Со стандартного потока ввода (stdin) считывается входное число
- * и номер бита, который нужно вывести. Отсчет ведется от нуля.
- * На стандартный поток вывода (stdout) выводится значение искомого бита.
- * На стандартный поток ошибок выводится отладочная информация:
- * * входное число в двоичном представлении;
- * * входное число после двоичного сдвига на номер бита
- * (тоже в двоичном представлении).
- * Размер входного числа должен быть не более размера типа `unsigned long`,
- * вашего компилятора. Программа проверялась на gcc x86_64.
- * Размер `unsigned long int` составлял восемь байт (64 бита).
- *
- * @subsection Пример
- *
- * $> gcc get-bit.c -Wall -pedantic -std=c89
- * $> ./a.out
- * 100 2
- * 0000000000000000000000000000000000000000000000000000000001100100
- * 0000000000000000000000000000000000000000000000000000000000011001
- * 1
- * $> ./a.out 2> /dev/null
- * 100 2
- * 1
- * $> ./a.out
- * 4294967295 31
- * 0000000000000000000000000000000011111111111111111111111111111111
- * 0000000000000000000000000000000000000000000000000000000000000001
- * 1
- * $> ./a.out 2> /dev/null
- * 9223372036854775807 63
- * 0
- * $> ./a.out 1> /dev/null
- * 9223372036854775807 63
- * 0111111111111111111111111111111111111111111111111111111111111111
- * 0000000000000000000000000000000000000000000000000000000000000000
- * $> ./a.out
- * -10 1
- * 1111111111111111111111111111111111111111111111111111111111110110
- * 0111111111111111111111111111111111111111111111111111111111111011
- * 1
- *
- *
- * @authors Никитин Илья Константинович (преп. каф. 806 МАИ) <w@w-495.ru>
- * @version 1.0
- **/
- /*
- * Подключаем заголовочный файл стандартного ввода-вывода
- * (STanDart Input-Output) для использования getchar, putchar, scanf, printf.
- */
- #include <stdio.h>
- /**
- * @fn Возвращает бит числа `input` под номером `numbit`.
- * Отсчет ведется от нуля.
- *
- * @param input входное число;
- * @param numbit номер бита;
- **/
- int get_bit(unsigned long input_number, unsigned short numbit);
- /**
- * @fn Выводит на поток ошибок число `input` в двоичном представлении.
- * В этой программе нужна исключительно для отладки.
- *
- * @param input входное число;
- **/
- void debug_print_binary(unsigned long input);
- int main(){
- /**
- * @var Входное число, для которого надо вывести бит.
- */
- unsigned long input_number = 0;
-
- /**
- * @var Номер бита, который нужно вывести. Отсчет от нуля.
- */
- unsigned short numbit = 0;
-
- /**
- * @var Бит, который мы будем выводить.
- * Изначально присваиваем невозможное значение,
- * Чтобы быстро выловить ошибку, если у нас такая случится.
- */
- unsigned short bit = 2;
- if(scanf("%lu", &input_number) != 1){
- /*
- * Защита от дурака.
- * Если на вход подается что-то неприличное,
- * то на стандартный поток (файл) ошибок выводим сообщения об ошибке.
- */
- fprintf(stderr, "error: %lu is not integer number.", input_number);
- return 1;
- }
- if(scanf("%hu", &numbit) != 1){
- /*
- * Защита от дурака.
- * Если на вход подается что-то неприличное,
- * то на стандартный поток (файл) ошибок выводим сообщения об ошибке.
- */
- fprintf(stderr, "error: %hu is not number of bit.", numbit);
- return 1;
- }
- /*
- * Определяем бит. Обратите внимение,
- * что отсчет битов идет не от единицы, а от нуля.
- */
- bit = get_bit(input_number, numbit);
- printf("%hu\n", bit);
- return 0;
- }
- /**
- * @fn Возвращает бит числа `input` под номером `numbit`.
- * Отсчет ведется от нуля.
- *
- * @param input входное число;
- * @param numbit номер бита;
- **/
- int get_bit(unsigned long input_number, unsigned short numbit){
- unsigned long tmp = 0;
- /*
- * Посмотрим, как выглядит наше число в двоичном представлении.
- * Это нужно только для отладки
- */
- debug_print_binary(input_number);
- /*
- * Двоичный сдвиг числа `input_number` на `numbit` бит влево
- * (по сути, `numbit` раз разделили на `2`).
- */
- tmp = (input_number >> numbit);
- /*
- * Посмотрим в двоичном представлении это же число после сдвига.
- * Это нужно только для отладки.
- */
- debug_print_binary(tmp);
- /**
- * Применяем побитовое умножение `битовое И` для исходного числа
- * и единицы. Таким образом выделяем нужные бит.
- * Суффикс `L` у числа говорит компилятору,
- * что мы работаем с типом `unsigned long`.
- */
- if(1L == (tmp & 1L)){
- return 1;
- }
- return 0;
- }
- /**
- * @fn Выводит на поток ошибок число `input` в двоичном представлении.
- * В этой программе нужна исключительно для отладки.
- *
- * @param input входное число;
- * @param width ширина выводимого числа;
- * Этот аргумент нужен, чтобы дополнять выходное число
- * ведущими нулями, до нужного размера.
- * Например `debug_print_binaryw(2, 4)` напечатает `0010`.
- **/
- void debug_print_binaryw(unsigned long input, unsigned short width){
- /*
- * Получаем разряд числа `input` в системе счисления `2`.
- */
- unsigned short digit = input % 2;
- /*
- * Условие остановки рекурсии.
- */
- if(!input){
- unsigned short i;
- /*
- * Печатаем ведущие нули.
- * Каждый предыдущий шаг рекурсии уменьшал `width` на единицу,
- * т.к. к выходному числу добавлялось по разряду.
- * Теперь мы выводим столько нулей, сколько необходимо,
- * до дополнения до ширины `width`.
- */
- for(i = 0; i < width; ++i)
- fprintf(stderr, "0");
- }
- else{
- /*
- * Рекурсивно вызываем эту же функцию,
- * Параметр `input` становится в `2` раза меньше,
- * а параметр `width` уменьшаем на 1,
- * если он был положительным (тут используется тренарный оператор).
- * Как результат возвращает предыдущие разряды числа.
- */
- debug_print_binaryw(input / 2, (width) ? (width - 1) : 0);
- fprintf(stderr, "%hu", digit);
- }
- }
- /**
- * @fn Выводит на поток ошибок число `input` в двоичном представлении.
- * В этой программе нужна исключительно для отладки.
- *
- * @param input входное число;
- **/
- void debug_print_binary(unsigned long input){
- /**
- * @var Ширина выводимого числа.
- * Нужна для дополнения его ведущими нулями.
- */
- unsigned short width = sizeof(input) * 8;
- debug_print_binaryw(input, width);
- fprintf(stderr, "\n");
- }