Home > Mobile >  Why is fgets waiting for input before it's even called?
Why is fgets waiting for input before it's even called?

Time:06-14

I'm trying to write a simple program to read an integer and then a string, then print both to standard output. Ideally, the execution should look something like this:

Input the number.
> 10

Input the string.
> a string

number: 10
string: a string

However, when I run the program, it freezes after the call to scanf() until more input is provided.

Input the number.
> 10
a string

Input the string.
> 
number: 10
string: a string

Why is it waiting for input before fgets() is ever called?

 #include <stdio.h>
 
 int main()
 {
     int number;
     char string[32];
 
     printf("Input the number.\n> ");
     scanf("%d\n", &number);
 
     printf("\nInput the string.\n> ");
     fgets(string, 32, stdin);
 
     printf("\nnumber: %d\nstring: %s\n", number, string);
 }

CodePudding user response:

From a previous post...

https://stackoverflow.com/a/5918223/2203541

#include <stdio.h>

int main()
{
  int number;
  int c;
  char string[32];

  printf("Input the number.\n> ");
  scanf("%d", &number);
  do
  {
    c = getchar();
  } while (c != '\n');
  printf("\nInput the string.\n> ");
  fgets(string, 32, stdin);

  printf("\nnumber: %d\nstring: %s\n", number, string);
}

CodePudding user response:

"Why is fgets waiting for input before it's even called"

fgets() does not act until it is called, but if when called, and if pointing to stdin and there is content remaining in the stdin stream, it will consume it immediately. If that contents contained EOF, n-1, OR a newline (read link) execution flow will continue.

The problem here is that scanf() (called prior to fgets()) is notorious for doing exactly what it is asked to do. For example, upon user entering 12<return> two recognizable items are entered into stdin, digits and a newline but by using "%d" as the format specifier, only the first of those items is consumed, leaving the \n hanging, until the very next call to fgets(), which accepts it as input, allowing execution flow to resume immediately (as described above), causing the apparent skip you are seeing.

[This is one (of several) examples that will provide a work around for the scanf() issue:

Change this:

 printf("Input the number.\n> ");
 scanf("%d", &number);//leaves the newline

To this:

 char c;
 ...
 printf("Input the number.\n> ");
 scanf("%d%c", &number, &c);//consumes the newline

From comments:

"is there a way to use fgets to read an integer"

Yes, I prefer fgets() coupled with your favorite string to number converter. (There are several) The simplest is this:

char cNum[10];
int num;

printf("Input the number.\n> ");
if(fgets(cNum, sizeof cNum, stdin))
{
     num = atoi(cNum);
}
else //handle error

See also strtol() for a more robust solution.

CodePudding user response:

Alright, so I played around with it some more and did a little more studying on scanf() format syntax, and figured out a solution. Apparently, putting the whitespace character at the end of my scanf call there tells it to keep reading until it finds something AFTER the whitespace, so of course it would hang up there until you give more input.

Remove the whitespace character in the scanf formatter, and add a leading space to the following scanf call.

The reason I had used fgets originally was so I could specify a buffer length to avoid overflow. Apparently, the same effect can be achieved using 2s in the scanf call. The fixed code looks like this:

 #include <stdio.h>
 
 int main()
 {
     int number;
     char string[32];
 
     printf("Input the number.\n> ");
     scanf("%d", &number);
 
     printf("\nInput the string.\n> ");
     scanf(" 2s", &string);
 
     printf("\nnumber: %d\nstring: %s\n", number, string);
 }
  • Related