1

I need to check if the string contain a binary number., I tried this way with a for it worked for a while but then, I've got problem, it will be a my stupid error, but i need help!!

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

int main(){
    char input[16];
    int ndec=0,rem,nbin,base=1;
    printf("Insert a binary number \n-----> ");
    scanf("%s", input);
    nbin=atoi(input);
    while(nbin>1111111111111111){
        printf("THE NUMBER YOU ENTERED IS NOT TOO BIG \n Enter a smaller number n----> ");
    }
    int lun = strlen(input);
    for(int i=lun;i!=-1;i--){
        if (input[i] !=49 && input[i] !=48) {
            printf("The entered number is not a binary number!!  n Enter a binary number n----> ");
            scanf("%s", input);
            int lun = strlen(input);
            i =lun;
            }
    }
    nbin=atoi(input);
    int temp = nbin;
    while(temp > 0)
    {
        rem = temp % 10;
        ndec = ndec + rem * base;
        temp = temp / 10;
        base = base * 2;
    }
    printf("Decimal value is %d\n",ndec); 
}
steeper
  • 11
  • 3
  • 2
    `atoi` is the wrong function for this task. You'll want to use something like [strtol](https://en.cppreference.com/w/c/string/byte/strtol) where you can specify the base. – Retired Ninja Oct 11 '22 at 00:51
  • `scanf("%s", input);` without a field-width modifier is no safer than `gets()` See [Why gets() is so dangerous it should never be used!](https://stackoverflow.com/q/1694036/3422102). Failing to ***check the return*** someone could enter `"my cow"` and you would blindly process it as a number (and `atoi()` would silently fail returning `0` without any indication of an error) if `nbin > 1111111111111111` then you will enjoy unlimited output from `while(nbin>1111111111111111){...}` – David C. Rankin Oct 11 '22 at 00:53

2 Answers2

3

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.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

i resolved this way

void da_binario_a_decimale() {

    int ndec=0,rem,nbin,base=1;
    printf("Inserire un numero binario che verra' covertito in decimale \n-----> ");
    scanf("%s", input);
    nbin=atoi(input);
    while(nbin>1111111111111111){
        printf("IL NUMERO CHE HAI INSERITO NON E' TROPPO GRANDE\n Inserisci un numero minore\n-----> ");
    }
    int lun = strlen(input);
    
    for(int i=lun-1;i>-1;i--){
        if (input[i] !=49 && input[i] !=48) {
            printf("Il numero inserito non e' un numero binario!!\n Inserire un numero binario\n-----> ");
            scanf("%s", input);
            int lun = strlen(input);
            i =lun;
            }
    }
    nbin=atoi(input);
    int temp = nbin;
    while(temp > 0){
        rem = temp % 10;
        ndec = ndec + rem * base;
        temp = temp / 10;
        base = base * 2;
    }
    printf("Il numero decimale e' %d\n",ndec); 
}
steeper
  • 11
  • 3
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 17 '22 at 09:31