14

I'm trying to execute this block of code.

#include <stdio.h> 
int main(void)
{       

     printf("Start from here\n");
     int e, f, g, h;

     scanf("%d,%d", &e, &f);
     scanf("%d, %d", &g, &h);

     printf("%d %d %d %d", e, f, g, h);
}

When I input 2,0 or something that matches the format string in the first scanf(), the second scanf() also executes.

However, if I input something like 2-0 in the first scanf(), the program skips the second scanf() and goes straight to the printf()

For example, here's the input and output of a sample run of the program. The second line is the input.

Start from here
1-2  
1 0 -2 -856016624u

Notice how the program completely skipped the second scanf(), and went straight to the printf(). Why is the second scanf() being skipped over here?

melpomene
  • 84,125
  • 8
  • 85
  • 148
Nathu
  • 449
  • 1
  • 4
  • 11
  • 1
    `1-2` should be `1,-2`? That is, a comma between the numbers. Because that is what you told `scanf` to expect. – kaylum Feb 23 '17 at 05:57
  • 3
    your second `scanf` is being executed. `e` gets `1` and `g` gets `-2` – Nishant Bhakta Feb 23 '17 at 06:01
  • 1
    Why are you not checking the return values from `scanf`? Might be handy to read the manual page – Ed Heal Feb 23 '17 at 06:46
  • FALSE. The program does not 'skip' the second `scanf` — the program executes it, but the results are different from what you expect. Just read a manual about `scanf()` to understand what happens when you provide an input incompatible with the format, and how to detect and handle the error. – CiaPan Feb 23 '17 at 11:44
  • this is one of the many times when checking the returned value (not the parameter value) from `scanf()` would have informed the code of the failure to read both parameters in the first call to `scanf()` and the failure of the second call to `scanf()` to read both parameters – user3629249 Feb 23 '17 at 22:56

3 Answers3

21

scanf's format string cares about the non-format specifiers in it too. When you write "1-2" the first scanf will read "1", then look for a comma. It won't find one, so it'll give up. Now, the second scanf will see "-2" and then look for a comma. It won't find one, so it'll give up.

The end result is that the other two variables won't get set so they end up being whatever garbage is in their memory location at execution time.

You can avoid this by checking the return value of scanf. It'll tell you how many values it found. Try this:

#include <stdio.h> 
int main(void)
{       

     printf("Start from here\n");
     int e, f, g, h;

     if (scanf("%d,%d", &e, &f) != 2) { /* error handling */ }
     if (scanf("%d, %d", &g, &h) != 2) { /* error handling */ }

     printf("%d %d %d %d", e, f, g, h);
}
Peter G
  • 2,773
  • 3
  • 25
  • 35
  • 5
    Note: As part of *error handling*, you might need to discard some user input! That can be done using a `getchar` loop, or `scanf("%*[^\n]"); getchar();` for example... – autistic Feb 23 '17 at 06:04
  • 5
    Also note: the space, in this case, is semantically meaningless; both format strings are functionally equivalent as `%d` will implicitly discard leading whitespace *anyway*. – autistic Feb 23 '17 at 06:04
  • Good to know, removed the bit about the format strings. – Peter G Feb 23 '17 at 06:06
  • 1
    Why use `while` instead of `if`? – Ruslan Feb 23 '17 at 08:33
  • If you flush stdin where I wrote `/* error handling */` as Seb suggested, you can prompt the user again for input (if you don't, you'll probably just get an infinite loop). Using `if` will skip to the next scanf (or to the print, which will print garbage). – Peter G Feb 23 '17 at 09:07
  • This is why you should avoid scanf for input that may be wrong unless you really understand it, and it's usually easier to just write your own parser. – pjc50 Feb 23 '17 at 13:29
  • Downvoted for the use of `while` instead of `if`. Change that to an if statement. Otherwise, this is a good answer. – David Hammen Feb 23 '17 at 14:00
  • Changed it to use `if` instead. – Peter G Feb 23 '17 at 20:02
2

Remove a comma between the two format specifier.

scanf("%d %d", &e, &f); // Remove comma in first argument of scanf
scanf("%d %d", &g, &h);  // Remove comma in first argument of scanf
        ^^^
      Remove comma between two numbers

Because scanf will only skip white space and the comma is not white space.

What actually happens when you ask scanf to read numeric data is that it first skips any white space it finds and then it reads characters until the character it reads cannot form part of a number.

In this case, when it encounters the comma, it stops reading. Since it has not read any digits, there is no number for it to store, so it simply leaves the original value.

msc
  • 33,420
  • 29
  • 119
  • 214
1

In your code, scanf("%d, %d",&e,&f) is in this way, so you should give your input like: 1,2 or 2,3 etc

If you want your input to be given like 0-2 or 2-4, then your scanf must be like this : scanf("%d-%d",&e,&f).

In this way, it will not be skipped.

Suraj Jain
  • 4,463
  • 28
  • 39
Bidisha Pyne
  • 543
  • 2
  • 13