user10792793
user10792793

Reputation:

How to Determine Whether C Input is an 8 bit Binary Number

I'm writing a program that will mess around with converting binary values to hex and vice versa.

The user should enter a value which will be stored in an int variable. I need to determine whether or not this user input is an eight-bit binary number like 10010010, 11110000, 10101010, etc.

I've already written a function to determine how many characters the user enters, but I'm not finding much on how to make sure the user's input is either a 1 or a 0.

Is this just a simple solution that I'm not seeing?

Upvotes: 0

Views: 1892

Answers (3)

David C. Rankin
David C. Rankin

Reputation: 84561

Rather than taking character input and then attempting to convert the resulting string into a numeric value that you can manipulate, simply require the user to enter a 8-bit numeric value. Whether entered in decimal, hexadecimal or octal, the resulting value is always stored in memory as a binary value.

Since you are wanting to limit input to a 8-bit value, C99 introduced exact width variable types that eliminate any ambiguity in type-size between architectures. Understand that char and unsigned char are defined as 1-byte/8-bits on virtually every system, where types such as long can be 4-bytes on some systems (e.g. x86) and 8-bytes on others (e.g. x86_64). Use of the exact-width types removes all ambiguity.

The exact-width types are defined in stdint.h and the macros for use with printf or scanf are defined in inttypes.h (note: inttypes.h is required to include stdint.h, so if using the macros, inttypes.h is all that is needed) See: man inttypes.h

In requiring an 8-bit value, it is useful to take entry into a temporary variable of larger type (e.g. as a 64-bit value) and then test whether the value entered is within the range of an 8-bit value. A simple conditional checking that the unsigned value is 0-255 or a signed value is -128 to 127 is sufficient. If the value entered is not with those ranges for unsigned/signed types, it isn't an 8-bit value.

After reading user input and validating the conversion and that the value is within the range of 8-bit, you can output the value in any base you like using the macros provided in inttypes.h for unsigned and hexadecimal types, and a simple function to output a padded binary representation.

Putting it altogether, you could do something like the following:

#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);
}

Example Use/Output

$ ./bin/8bitentry
enter a value: 127

unsigned : 127
hex      : 7f
binary   : 01111111

If the user attempts to enter something outside the range of an 8-bit value:

$ ./bin/8bitentry
enter a value: 256
error: entry exceeds 8-bit value.

Taking Input as a String Representation of a Binary Value

The only scenario that wouldn't be covered by requiring input as above, is if you actually want the user to enter the binary representation as a string which you then want to convert to a numeric value. The simplest way to handle a string containing a binary representation of a value is to use the base-2 conversion provided by strtoul. This allows complete error checking of input by making use of the endptr parameter to validate only '0's and '1's were entered. See man strtoul

A simple implementation taking string entry of '0's and '1's could be:

#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);
}

Example Use/Output

$ ./bin/8bitentry_string
enter an 8-bit binary no.: 1111111
unsigned: 127
hex     : 7f

Or user enters more than an 8-bit binary value:

$ ./bin/8bitentry_string
enter an 8-bit binary no.: 111111111
error: input exceeds 8-bit value.

Or user enters a value beginning with an invalid character:

$ ./bin/8bitentry_string
enter an 8-bit binary no.: 310
error: invalid binary entry.

Or user enters a value containing an invalid character:

$ ./bin/8bitentry_string
enter an 8-bit binary no.: 10131
warning: conversion ended at invalid char '3'
unsigned: 5
hex     : 5

Look things over and let me know if you have further questions.

Upvotes: 0

3CxEZiVlQ
3CxEZiVlQ

Reputation: 38528

If your program to store user input in a char array (string) you can use strspn function that searches for the first occurrence of a not matching char from a given string.

#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;
}

Upvotes: 2

Yunbin Liu
Yunbin Liu

Reputation: 1498

use like this:

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;
}

Upvotes: 0

Related Questions