1

Here's a simple example: I have an array of 3 characters, I write an input on terminal and I want to check immediately what i scanned, like this:

scanf("%3s\n",array);
printf("%s",array);

What i want to know is: why, after running the program, if I write on terminal "abc", to make it print out the array I have to put another input, like writing another letter or a number?

If I write "abcd" and then press ENTER then it immediately prints, but if I just write "abc" and press ENTER many times it still doesn't go to the next instruction (which is printf).

I know that it has to do with how \n makes scanf read the string, but I cant quite get it.

wattbatt
  • 447
  • 2
  • 13
  • 2
    how did you declared `array`? if it has only 3 elements then it can't store a 3-character string and you're getting UB – phuclv Jul 31 '18 at 16:04
  • Have you tried changing the `%3` to `%2` in your scanf() function? – Uclydde Jul 31 '18 at 16:18
  • @JBraha no I didn't, doesn't `%2s` make it scan only 2 chars? Oh right no room for the terminator if I do `%3s`, correct? – wattbatt Jul 31 '18 at 17:16
  • @wattbatt Well if your code had `%3` and 'abcd' (a 4-char string) worked properly, I thought that `%2` and 'abc' (a 3-char string) might work properly. – Uclydde Jul 31 '18 at 17:18

1 Answers1

4

It is not the printf (as the first version of your now edited title implied) which needs the additional input, it is the scanf.
Your format string contains a "\n".
That happens to be a white space.
Any whitespace in that position will tell scanf to consume any number of whitespace following the three characters (e.g. "abc").
As long as you continue adding whitespace (including returns), the scanf is not done consuming "all following whitespace".
As soon as you enter any non-whitespace (e.g. "d") it knows "aha, all whitespace done". Then, and not before, it can complete. Leaves the non-whitespace in the input stream and returns.
Note (credits to chux) that with a (commonly, to the point of almost always if you did not intentionally change that) line buffered input, you need to enter such a non-whitespace with a return/newline following it somewhere.

Note, as mentioned in comments, you need 4 characters of space in your target array, to also accomodate the always written "\0" at the end of the string. If you only have three characters space, then the last 0 will be written beyond causing undefined behaviour.

I am not sure how to solve your problem, because I cannot tell what the purpose of your "\n" is. But I think you should try the behaviour if you move the "\n" out of scanf() and maybe into the printf(). A following scanf() call starting with a conversion specifier (except "[", "c", and "n") consumes any leading whitespace anyway, including any remaining newlines/returns from this one.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • "As soon as you enter any non-whitespace (e.g. "d") it knows "aha, all whitespace done". Then, and not before, it can complete." --> Perhaps "not a soon" since `stdin` is commonly line buffered and so a following _line_ of input is required before `scanf()` sees any more data. – chux - Reinstate Monica Jul 31 '18 at 16:40
  • @chux Good point. I improved the phrasing. Thanks for the input. – Yunnosch Jul 31 '18 at 16:41
  • Until now i worked on strings as char arrays so I didn't know about the string terminator character..about this I have an additional question: my array is `char array[3];` so that means it has room for 3 chars, right? Why if I write "abc", it gets printed regularly and it doesn't give any error, since there is no more room for the '\0' char? – wattbatt Jul 31 '18 at 16:57
  • See https://en.cppreference.com/w/c/io/fscanf quote "Always stores a null character in addition to the characters matched (so the argument array must have room for at least width+1 characters)" Note that scanf does not know about the size of what you refer to as destination. – Yunnosch Jul 31 '18 at 16:59
  • 1
    @federicomasseroni C is not specified to give an error when your code writes outside `array[3]`. Code broke the rules - so rest of code moot. "since there is no more room for the '\0' " is not known to be true. We know there is not _certainly_ enough room - there might be - there might not be enough room - it is all _undefined behavior_. – chux - Reinstate Monica Jul 31 '18 at 17:05
  • I know I should not address voters. But however did that fourth upvote granted me the silver "C". Thank you so very much. :-) – Yunnosch Jul 31 '18 at 17:08