There are many ways you can approach this, but, if your goal is to read a string containing '1'
s and '0'
s and then convert the string in a base 2 conversion to a number, then strtoul()
provides the direct base 2 conversion you need (it provides base 2 - 36 conversions) with error checking.
On the other hand, atoi()
provides zero error detection or reporting and will happily accept atoi("my cow");
silently returning 0
with no indication that an error ever occurred.
In like manner, trying to read a string with scanf()
using "%s"
without a field-width modifier leaves your code wide open to exploit by buffer overrun because "%s"
will read an unlimited number of characters -- overwriting your array bounds (and off across your program stack). If your array is 15-charaters, then use "%15s"
to limit the number of characters read to 15
(saving 1
for the nul-terminating character). Or, better, take all user-input with fgets()
and avoid the pitfalls inherent in new C programmers using scanf()
.
With the basics out of the way, you simply want to:
- read your user input into a sufficiently sized array (don't skimp on buffer size),
- validate the string provided by the user consist only or
'0'
s and '1'
s,
- convert the string to an
unsigned long
value using strtoul()
with base = 2
, and then
- validate the
strtoul()
conversion by checking that endptr
does not equal the numptr
(your input
) confirming that digits were converted. (strtoul()
will set endptr
to point to the next character after the last character used in numeric conversion), and
- validate that overflow or other conversion error did not occur by checking that
errno
is zero after the conversion.
With that as an outline, you can approach your problem as follows:
#include <stdio.h>
#include <stdlib.h> /* for strtoul */
#include <string.h> /* for strspn, strcspn */
#include <errno.h> /* for errno */
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (void) {
char input[MAXC], *endptr = input; /* input and endptr for strtoul() */
unsigned long number = 0; /* number after conversion */
size_t len; /* length of input */
fputs ("enter a binary number: ", stdout); /* prompt for input */
if (!fgets (input, MAXC, stdin)) { /* read/validate input */
puts ("(user canceled input)");
return 0;
}
input[(len = strcspn (input, "\n"))] = 0; /* trim \n, save length */
if (strspn (input, "01") != len) { /* validate input is only 0's and 1's */
fputs ("error: string must contain only '0' and '1's\n", stderr);
return 1;
}
errno = 0; /* set errno zero */
number = strtoul (input, &endptr, 2); /* attempt base 2 converison */
if (endptr == input) { /* if no digits converted, handle error */
fputs ("error: no digits converted.\n", stderr);
return 1;
}
if (errno) { /* if error in conversion, handle error */
fputs ("error: in numeric conversion.\n", stderr);
return 1;
}
/* output results */
printf ("\nstring : %s\nnumber : %lu\n", input, number);
}
Example Use/Output
Does the code identify improper input?
$ ./bin/strtoul_bin
enter a binary number: 11101100011112
error: string must contain only '0' and '1's
What about the conversion? (removing the 2
above)
$ ./bin/strtoul_bin
enter a binary number: 1110110001111
string : 1110110001111
number : 7567
Does it handle the user canceling input by generating a manual EOF
with Ctrl + d (or Ctrl + z on windows)?
$ ./bin/strtoul_bin
enter a binary number: (user canceled input)
Those are three important cases all of your user-input routines should handle. (1) good input, (2) bad input -- handle error, and (3) user canceling input. I'll leave it to you to research fgets()
. See man 3 fgetc to determine how the manual EOF
is caught.
Look things over and let me know if you have questions.