0

I am aware of scanf() usage and is not encouraged. But I've the problem, where scanf sends the stdin value to the next function stdin. I'm wondering why it's doing like this.

code:

#include <stdio.h>

void ffgets() {
    char name[40];
    printf("What's your name? ");
    if (fgets(name, 40, stdin)) {
        printf("Hello %s", name);
    }
}

int main(int argc, char **argv) {
    int a;
    printf("enter a number: ");

    int res = scanf("%d", &a);
    if (res > 0) {
        printf("Valid Integer %d.\n", a);
    } else {
        printf("It's not a number\n");
    }

    ffgets();
    return 0;
}

Output:

Test case 1:

Why the function doesn't ask for stdin, it just print empty string

 ./a.out 
enter a number: 23
Valid Integer 23.
What's your name? Hello 

Test case 2: I entered the string with the special character that is passed name.

./a.out 
enter a number: random##¤
It's not a number
What's your name? Hello random##¤

I dont want stdin value from main passed to the function, how to do that?

  • 2
    Don't mix the two, Use only `fgets()` to read whole lines, it's much less confusing. – unwind Jun 15 '17 at 09:37
  • Your problem is exactly why the use of `scanf()` is not encouraged. See also [A beginners' guide away from `scanf()`](http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html). – Jonathan Leffler Jun 15 '17 at 14:40

3 Answers3

2

If you input something that scanf can not match to the format specification then it will stop immediately and leave the input in the input buffer for the next input function.

Also, when using scanf it will not consume the trailing newline in the input buffer, also leaving it for the next input function.

To solve both problems consider using fgets to get the whole line from the input, and then use sscanf to parse the string.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • That's true. The input buffer is used in the next input function. How to stop that, I dont want next instruction to use the scanf buf? flushing stdin is ub. –  Jun 15 '17 at 09:38
  • 1
    @DanglingPointer Either use the method I described already (using `fgets` and `sscanf`) or "flush" the input by reading character by character until you have a newline. – Some programmer dude Jun 15 '17 at 09:40
1

I am aware of scanf() usage and is not encouraged.

This is exactly the issue that comes from scanf() (namely, that input not used by scanf is left in the input buffer, contrary to what the user expected). So, as you seem to already know, the solution is to not use the function.

It's not that hard to make a function to read a complete line of input, and parse an int from there with sscanf() or strtol or friends:

#include <stdio.h>
#include <limits.h>

int getint(void)
{
    char buffer[120] = {0}; /* arbitrary limit */
    fgets(buffer, 120, stdin);
    int a;
    if (sscanf(buffer, "%d", &a) == 1) {
        return a;
    }
    return INT_MIN;
}

(Of course INT_MIN is a valid number to enter, so you might want to have some better way of returning errors. And perhaps consider what to do with garbage following the number.)

ilkkachu
  • 6,221
  • 16
  • 30
  • This make sense. Thanks for the answer. I just got the answer from someprogrammingdude. Because scanf just parse the data and leaves next instruction to use it. –  Jun 15 '17 at 09:46
  • Thanks, for the answer. It enlightens me, difficult in StackOverflow I can just accept one as the answer. if have another option two accept two answers, I would have done your's. –  Jun 15 '17 at 09:48
0

The reason is that in the first case, the matching input is consumed by scanf() but the newline \n is present in the input buffer. That makes a valid input and terminator for fgets() in the first case.

Related , quoting C11, chapter §7.21.6.2

Trailing white space (including new-line characters) is left unread unless matched by a directive. [....]

In the second case, the matching failure happens, which makes the entire input to be available in the input buffer at the time of fgets() call, so fgets() reads the whole thing.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • It's mistake I just removed the newline, i knew fgets It reads a line of input. I test without \n while printing. But the real problem is different. –  Jun 15 '17 at 09:35