Вместо того, чтобы вводить символы и затем пытаться преобразовать полученную строку в числовое значение, которым вы можете манипулировать, просто потребуйте, чтобы пользователь ввел 8-битное числовое значение. Введено ли оно в десятичном, шестнадцатеричном или восьмеричном виде, результирующее значение всегда сохраняется в памяти в виде двоичного значения.
Поскольку вы хотите ограничить ввод 8-битным значением, C99 ввел точные типы переменных ширины, которые устраняют любую неоднозначность в отношении размера шрифта между архитектурами. Следует понимать, что char
и unsigned char
определены как 1-байтовые / 8-битные практически в каждой системе, где типы, такие как long
, могут быть 4-байтовыми в некоторых системах (например, x86) и 8-байтовыми в других ( например, x86_64). Использование типов точной ширины устраняет всю двусмысленность.
Типы точной ширины определены в stdint.h
, а макросы для использования с printf
или scanf
определены в inttypes.h
(примечание: inttypes.h
необходимо включить stdint.h
, поэтому при использовании макросы, inttypes.h
- это все, что нужно) См .: man inttypes.h
Когда требуется 8-битное значение, полезно взять запись во временную переменную более крупного типа (например, как 64-битное значение) и затем проверить, находится ли введенное значение в диапазоне 8-битного значения. , Достаточно простой условной проверки, что значение unsigned
равно 0-255
или значение signed
равно -128 to 127
. Если введенное значение не соответствует этим диапазонам для неподписанных / подписанных типов, это не 8-разрядное значение.
После прочтения введенных пользователем данных и проверки правильности преобразования и того, что значение находится в диапазоне 8 бит, вы можете вывести значение в любой понравившейся вам базе, используя макросы, предоставленные в inttypes.h
для беззнаковых и шестнадцатеричных типов, и простая функция для вывода дополненного двоичного представления.
В целом, вы можете сделать что-то вроде следующего:
#include <stdio.h>
#include <limits.h> /* for CHAR_BIT */
#include <inttypes.h> /* for exact width macros, includes <stdint.h> */
/** binary representation of 'v' padded to 'sz' bits.
* the padding amount is limited to the number of
* bits in 'v'. valid range: 0 - sizeof v * CHAR_BIT.
*/
void binprnpad (const uint64_t v, size_t sz)
{
if (!sz) { /* validate sz not zero */
fputs ("error: invalid sz.\n", stderr);
return;
}
if (!v) { /* handle v = 0 case */
while (sz--)
putchar ('0');
return;
}
if (sz > sizeof v * CHAR_BIT) /* validate size not greater than bits */
sz = sizeof v * CHAR_BIT;
while (sz--) /* output char representation of binary value */
putchar ((v >> sz & 1) ? '1' : '0');
}
int main (void) {
uint64_t tmp = 0; /* temporary value to store user input value */
fputs ("enter a value: ", stdout); /* prompt */
if (scanf ("%" SCNu64, &tmp) == 1) { /* read/validate input */
if (tmp <= UINT8_MAX) { /* check 8-bit value */
uint8_t val = (uint8_t)tmp; /* assign 8-bit value */
printf ("\nunsigned : %" PRIu8 /* output dec, hex */
"\nhex : %" PRIx8
"\nbinary : ", val, val);
binprnpad (val, sizeof val * CHAR_BIT); /* output binary */
putchar ('\n'); /* tidy up with newline */
}
else /* handle error: not an 8-bit value */
fputs ("error: entry exceeds 8-bit value.\n", stderr);
}
else /* handle error: invalid input */
fputs ("error: invalid entry.\n", stderr);
}
Пример использования / Вывод
$ ./bin/8bitentry
enter a value: 127
unsigned : 127
hex : 7f
binary : 01111111
Если пользователь пытается ввести что-то вне диапазона 8-битного значения:
$ ./bin/8bitentry
enter a value: 256
error: entry exceeds 8-bit value.
Прием входных данных в виде строкового представления двоичного значения
Единственный сценарий, который не охватывается требованием ввода, как указано выше, - это если вы действительно хотите, чтобы пользователь вводил двоичное представление в виде строки, которую затем хотите преобразовать в числовое значение. Простейшим способом обработки строки, содержащей двоичное представление значения, является использование преобразования base-2, предоставляемого strtoul
. Это позволяет выполнить полную проверку ошибок ввода, используя параметр endptr
, чтобы проверить только введенные значения '0's
и '1's
. См. man strtoul
Простая реализация, принимающая строковые записи '0's
и '1's
, может быть:
#include <stdio.h>
#include <stdlib.h> /* for strtoul */
#include <errno.h> /* for errno */
#define MAXC 1024
int main (void) {
char buf[MAXC],
*endptr; /* end pointer for use with strtoul */
unsigned long tmp;
unsigned char val;
fputs ("enter an 8-bit binary no.: ", stdout); /* prompt */
if (fgets (buf, MAXC, stdin) == NULL) {
fputs ("(user canceled input)\n", stderr);
return 1;
}
errno = 0; /* reset errno 0 */
tmp = strtoul (buf, &endptr, 2); /* convert base2 string to value */
if (buf == endptr) {
fputs ("error: invalid binary entry.\n", stderr);
return 1;
}
else if (errno) {
fputs ("error: over/underflow occured.\n", stderr);
return 1;
}
else if (tmp > 255) {
fputs ("error: input exceeds 8-bit value.\n", stderr);
return 1;
}
else if (*endptr != '\n' && *endptr != 0)
fprintf (stderr, "warning: conversion ended at invalid char '%c'\n",
*endptr);
val = (unsigned char)tmp;
printf ("unsigned: %hhu\nhex : %hhx\n", val, val);
}
Пример использования / Вывод
$ ./bin/8bitentry_string
enter an 8-bit binary no.: 1111111
unsigned: 127
hex : 7f
Или пользователь вводит более 8-битное двоичное значение:
$ ./bin/8bitentry_string
enter an 8-bit binary no.: 111111111
error: input exceeds 8-bit value.
Или пользователь вводит значение, начинающееся с недопустимого символа:
$ ./bin/8bitentry_string
enter an 8-bit binary no.: 310
error: invalid binary entry.
Или пользователь вводит значение, содержащее недопустимый символ:
$ ./bin/8bitentry_string
enter an 8-bit binary no.: 10131
warning: conversion ended at invalid char '3'
unsigned: 5
hex : 5
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.