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

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

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

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

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

Ответы [ 3 ]

0 голосов
/ 13 января 2019

Если ваша программа для хранения ввода пользователя в массиве символов (строке), вы можете использовать функцию 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;
}
0 голосов
/ 13 января 2019

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

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

0 голосов
/ 13 января 2019

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

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...