Question

I am trying to convert numerical strings inputs to integer. When I type 2 my output is 0

    scanf( "%d", betNumber );
    printf("What number do you want to bet? \n");
    printf("Here is your number: %d\n" ,atoi(betNumber));

User input = 2 or 3 or 5 Output = always 0

Was it helpful?

Solution

You should never use the *scanf family, nor atoi and friends. The correct way to write this code is

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(void)
{
  char inbuf[80], *endp;
  unsigned long bet;  /* negative bets don't make sense */

  puts("What number do you want to bet?");
  if (!fgets(inbuf, sizeof inbuf, stdin))
    return 1;  /* EOF - just quit */

  errno = 0;
  bet = strtoul(inbuf, &endp, 10);
  if (endp == inbuf || *endp != '\n' || errno) {
    fputs("invalid number entered, or junk after number\n", stderr);
    return 1;
  }

  printf("Here is your number: %lu\n", bet);
  return 0;
}

Some exposition, perhaps:

The only sane way to read input from the user in C is an entire line at a time. If you don't, you are very likely to get in trouble when, not if, the user types more input than you expected. The ideal way to do this is with getline, but many C libraries do not have it, and it does make you remember to free the line-buffer. Failing that, fgets is good enough for many purposes, as shown here.

The only correct way to convert text to machine numbers in C is with the strto* family of functions. I use the word correct very deliberately. All the alternatives either silently ignore numeric overflow (ato*) or, worse, trigger undefined behavior on numeric overflow (*scanf). The usage pattern for strto* is a little tricky, but once you get used to it, it is just boilerplate to be memorized and typed. I'll take it apart for you:

errno = 0;

It is necessary to clear errno manually before calling strto*, because a syntactically valid number that overflows the range of the return value is reported only by setting errno, but success does not clear errno. (The manpage says that a particular numeric value is returned, but that value could have resulted from correct input, so that's no help.)

bet = strtoul(inbuf, &endp, 10);

When this function call returns, bet will be the number you wanted, and endp will be set to the first character in inbuf that is not a digit.

if (endp == inbuf || *endp != '\n' || errno) { /* error */ }

If endp equals inbuf, that means there were no digits, which is usually not considered a valid number.

If *endp is not equal to '\n', that means either there was something else on the line after the number, or fgets did not read the whole line; in either case, again, the input is not as expected. (All 64-bit unsigned numbers fit in fewer than 80 characters.)

And if errno is nonzero, numeric overflow occurred.

OTHER TIPS

I suggest you not use scanf, nor any of it's disreputable coterie of insidious companions. Use strtol. Easier to get your head around and less error prone. atoi is a less-safe equivalent of strtol.

But... atoi takes a pointer to char. So if this compiles...

printf("Here is your number: %d\n" ,atoi(betNumber));

...then betNumber must be:

char betNumber[100];

...or something like that. Which explains what's wrong with the call to scanf.

scanf("%d", p) expects that you'll be passing it a pointer to int, not a pointer to char. It reads text from standard input, converts it to an integer, and assigns it to the int variable -- or what it assumes must be an int variable -- that the pointer is pointing to. There is no type checking there, there can't be. The compiler can't tell that you passed the wrong thing (a C compiler could be written to validate scanf's arguments against the format string, but the general tendency with C compilers has always been to politely let you shoot yourself in the foot (modulo gcc -Wall, thanks @Zack), and rightly so).

If you use scanf() properly, such as

int betNumber;
scanf("%d", &betNumber);

then after scanf() returns successfully, the value of betNumber already is an integer, you do not need to convert it anymore.

scanf and atoi both take a pointer to some previously allocated storage. Here's a working example:

int betNumber;
printf("What number do you want to bet?\n");
scanf("%d", &betNumber);
printf("Here is your number: %d\n", betNumber);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top