Reputation:
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
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
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
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