Как определить, является ли вход C 8-битным двоичным числом

75
6

Я пишу программу, которая возится с преобразованием двоичных значений в шестнадцатеричные и наоборот.

Пользователь должен ввести значение, которое будет храниться в переменной int. Мне нужно определить, является ли этот пользовательский ввод восьмибитным двоичным числом, таким как 10010010, 11110000, 10101010 и т.д.

Я уже написал функцию, чтобы определить, сколько символов вводит пользователь, но я не нахожу много о том, как убедиться, что пользовательский ввод равен 1 или 0.

Это просто простое решение, которое я не вижу?

спросил(а) 2021-01-19T20:05:43+03:00 2 месяца, 3 недели назад
1
Решение
75

Если ваша программа хранит пользовательский ввод в массиве символов (строке), вы можете использовать функцию strspn которая ищет первое вхождение несоответствующего символа из заданной строки.

#include <stdio.h>
#include <string.h>

int main () {
const char user_input[] = "101th";
const char bdigits[] = "01";

int i = strspn (user_input, bdigits);
printf("Not a binary digit at position %d.\n",i);
return 0;
}

ответил(а) 2021-01-19T20:05:43+03:00 2 месяца, 3 недели назад
44

Вместо того, чтобы вводить символы и затем пытаться преобразовать полученную строку в числовое значение, которым вы можете манипулировать, просто потребуйте, чтобы пользователь ввел 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. Увидеть человека 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

Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

ответил(а) 2021-01-19T20:05:43+03:00 2 месяца, 3 недели назад
45

используйте как это:

char st[1024];
fgets(st, sizeof(st), stdin);
int i = 0;
for (;;) {
if (i == 8) {
if (st[i] == '\n') {
//right
} else {
//error
}
break;
}
if (st[i] != '0' && st[i] != '1') {
// error
break;
}
++i;
}

ответил(а) 2021-01-19T20:05:43+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема