1

I'm trying to create a code in C that asks how many words the user wants to insert and then ask repeatidly for each of the words, but on the first iteraction of the loop the code skips the printf() statement and goes directly to the fgets() line, showing the printf() after. The real problem to me is why fgets() on line #10 is being executed before printf() on line #09 on the first iteraction of the loop (on subsequents iteractions they follow the proper order).

Here's my code:

#include <stdio.h>

int main(void) {
    int T = 0, i = 1;
    char S[10000];
    printf("How many words? ");
    scanf("%d ", &T);
    while (i <= T){
        printf("\nType %d words ", T-i+1);
        fgets(S, sizeof(S), stdin);
        printf("\n Your word: %s", S);
        i++;
    }
return 0;
}

The expected output is something like this:

How many words? 2
Type 2 words banana
Your word: banana
Type 1 words orange 
Your word: orange

But what I get is something like this:

How many words? 2
banana

Type 2 words 
 Your word: banana

Type 1 words orange

 Your word: orange
  • 2
    Does this answer your question? [What is the effect of trailing white space in a scanf() format string?](https://stackoverflow.com/questions/19499060/what-is-the-effect-of-trailing-white-space-in-a-scanf-format-string) – Andreas Wenzel Jul 31 '22 at 17:45
  • 1
    This question may also be relevant: [fgets doesn't work after scanf](https://stackoverflow.com/q/5918079/12149471) This is probably the reason why you are using the trailing whitespace in the `scanf` format string, but that is not a proper solution. – Andreas Wenzel Jul 31 '22 at 17:48
  • These two questions you pointed out are good points to observe, however what I trying to figure out is why the fgets() function is being executed before the printf() since this is before the fgets(), and the execution should be line by line. I'll edit my question to clarify this. – dexter.amico Jul 31 '22 at 18:05
  • The `fgets` function on line #10 is not being executed before the `printf` function on line #9. Rather, the `scanf` function will execute until the user has finished entering the second line. This happens because of the trailing space character in the `scanf` format string. See the duplicate question for further information. – Andreas Wenzel Jul 31 '22 at 18:17
  • You appear to be under the impression that `scanf` will always read exactly one line of input. However, that impression is not correct. The function `scanf` will do exactly what you tell it to. If you want to always read one line of input, then I recommend that you always use `fgets` instead of `scanf`. You may want to read this: [What can I use for input conversion instead of scanf?](https://stackoverflow.com/q/58403537/12149471) You may also want to read this guide: [A beginners' guide away from scanf()](http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html) – Andreas Wenzel Jul 31 '22 at 18:18
  • I starting to understand, the problem seems to be the input buffer, right? Since there are still some 'junk' on it because of the use of `scanf()` when it's time for the `fgets()` to read the input it's already occupied by the leftover from the last input. and it goes directly to the next instruction. This is right or I'm still on the wrong direction? – dexter.amico Jul 31 '22 at 18:26
  • What you describe in your previous comment would be the problem if you weren't using the trailing space character in the format string. However, because you are, you have the following problem instead: The function `scanf` will be executing until the user enters two lines of input. This is caused by the trailing space character in the format string, because that character in the format string will cause `scanf` to continue consuming newline characters until it finds a non-newline character. [continued in next comment] – Andreas Wenzel Jul 31 '22 at 18:36
  • [continued from previous comment] It will only find such a non-newline character after the user has entered two lines of input. But `scanf` will only consume the newline character of the first line, so `fgets` will still correctly consume the second line of input. The only problem is that the `printf` in line #8 will only print after `scanf` in line #6 has finished, which will only happen after the user has entered two lines of input. – Andreas Wenzel Jul 31 '22 at 18:37
  • I therefore do not recommend that you ever use a trailing space character in a `scanf` format string. In fact, I do not recommend that you use `scanf` at all for user input. See the previous two links that I posted above for alternatives. I recommend that you use `fgets` for reading one line of input as a string and `strtol` for converting that string to a number. If you also want full input validation, then you may want to take a look at my function `get_int_from_user` in [this answer of mine to another question](https://stackoverflow.com/a/69636446), which uses `fgets` and `strtol`. – Andreas Wenzel Jul 31 '22 at 18:43
  • I really appreciate your effort to explain it to me and I'm very grateful for this. Now I can understood this topic a little better and have some directions to what I should read to keep learning about it. Thank you very much! – dexter.amico Jul 31 '22 at 18:44
  • The following question may also be useful to you: [Why does scanf ask twice for input when there's a newline at the end of the format string?](https://stackoverflow.com/q/15740024/12149471). The only difference to your problem is that this question uses a newline character as the trailing character in the `scanf` format string, whereas you are using a space character for that. However, both of these characters have exactly the same effect in a `scanf` format string. – Andreas Wenzel Jul 31 '22 at 19:20

1 Answers1

0

A simple method is to use fgets after scanf to clear stdin.

#include <stdio.h>

int main(void) {
    int T = 0, i = 0;
    char S[10000];
    printf("How many words? ");
    scanf("%d", &T);

    // Clear stdin with fgets so the "Type _ words" output displays before the first input prompt
    fgets(S, sizeof(S), stdin);

    while (i < T) {
        // Decrement T instead of incrementing i as a performance optimization
        printf("Type %d words ", T--);
        fgets(S, sizeof(S), stdin);
        printf("Your word: %s", S);
    }

    return 0;
}

Here's the result:

How many words? 2
Type 2 words a
Your word: a
Type 1 words b
Your word: b

I updated the answer below with output wording that makes more sense if others are reading this.

#include <stdio.h>

int main(void) {
    int T = 0, i = 1;
    char S[10000];
    printf("How many words? ");
    scanf("%d", &T);

    // fgets() clears stdin so the "Type _ words" output displays before the first input prompt.
    fgets(S, sizeof(S), stdin);

    while (i < T) {
        // T is decremented instead of incrementing i as a performance optimization
        printf("Type a word [%d words remaining]: ", T--);
        fgets(S, sizeof(S), stdin);
        printf("Your word: %s", S);
    }

    printf("Type a word [1 word remaining]: ");
    fgets(S, sizeof(S), stdin);
    printf("Your word: %s", S);
    return 0;
}

Here's the result.

How many words? 2
Type a word [2 words remaining]: a
Your word: a
Type a word [1 word remaining]: b
Your word: b
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • Thank you, your answer solved the problem! Also thanks to @andreas-wenzel for explaining and pointing out what I had misunderstood while using `scanf()`. – dexter.amico Jul 31 '22 at 18:35
  • Instead of only providing a solution, you may also want to provide an explanation why OP's code is not working and why you removed the trailing space character from the `scanf` format string. – Andreas Wenzel Jul 31 '22 at 19:34