5

for some simple HW code I wrote I needed to get 7 arguments via the scanf function:

scanf("%d %d %d %d\n", &vodka, &country, &life, &glut);
scanf("%d\n", &ageof);
scanf("%d\n", &dprice);
scanf("%d\n", &mprice);

as you can see, I'm asking for 7 arguments in this order:

argument [space] argument [space] argument [space] argument (down line)

argument (down line)

argument (down line)

argument (down line)

BUT, when running the code, I'm suddenly required to input 8 of them, and I have no idea why....

any help anyone?

  • 4
    Remove `\n` from `scanf`. – haccks Nov 24 '15 at 22:29
  • 1
    If you want to force the "(down line)", then you should read lines with `fgets` and parse the lines with `sscanf`. With `scanf` the user can type all the numbers on a single line, or each number on a separate line, and you'll never know the difference. – user3386109 Nov 24 '15 at 22:36
  • 2
    Ok, then haccks was right. Here's what the man page says about the `\n`: *"White space (such as blanks, tabs, or newlines) in the format string match any amount of white space, including none, in the input."* So the `\n` simply doesn't work the way you expected it to work. – user3386109 Nov 24 '15 at 22:40
  • aha. got it. thank you very much! – Alon Leibovitsh Nov 24 '15 at 22:42

3 Answers3

3

As explained by @chqrlie and @Blue Moon a white space in the format, be it ' ', '\n', '\n' or any white-space does the same thing. It directs scanf() to consume white-space, such as '\n' from an Enter, until non-white-space is detected. That non-white-space character is then put back into stdin for the next input operation.

scanf("%d\n", ...) does not return until some non-white space is entered after the int. Hence the need for the 8th input. That 8th input is not consumed, but available for subsequent input.


The best way to read the 4 lines of input is to .... drum roll ... read 4 lines. Then process the inputs.

char buf[4][80];
for (int i=0; i<4; i++) {
  if (fgets(buf[i], sizeof buf[i], stdin) == NULL) return Fail;
}
if (sscanf(buf[0], "%d%d%d%d", &vodka, &country, &life, &glut) != 4) {
  return Fail;
}
if (sscanf(buf[1], "%d", &ageof) != 1) {
  return Fail;
}
if (sscanf(buf[2], "%d", &dprice) != 1) {
  return Fail;
}
if (sscanf(buf[3], "%d", &mprice) != 1) {
  return Fail;
}
// Use vodka, country, life, glut, ageof, dprice, mprice
return Success
Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
2

When you have a whitespace in the format string, you tell scanf() to ignore any number of whitespace characters. So the spaces you have between the %d requires to input a non-whitespace char(s) which are consumed for each of the subsequent %d.

The effect of spaces and \n in the following scanf() calls you have isn't quite obvious. But the newline character at the end of each last scanf() forces you to input a non-whitespace char. Hence, it looks like scanf() requires an extra input.

However, you don't really any whitespace characters here as %d would always ignore whitespace characters. So simply remove all spaces and \n characters from the format strings.

P.P
  • 117,907
  • 20
  • 175
  • 238
1

White space characters in the scanf format string are directives that mean read white space characters until you get a non white space character. A trailing \n in your format string causes scanf to consume the linefeed that was typed by the user and to keep asking for input until a non white space character is seen, but is left in the input buffer.

To consume the \n exactly, you can use this ugly scanf format:

scanf("%d%*1[\n]", &mprice);

Or you can just remove the trailing \n and consume the character with getchar() but be aware that neither of these approaches provide for exact matching of the input:

scanf("%d", &mprice);
getchar();
chqrlie
  • 131,814
  • 10
  • 121
  • 189