2

A friend of mine is trying to learn c (on her own, with a book) and sometimes she asks for help.

She just showed me something I can't answer; I'm ashamed but I studied C in college and then moved to php. I'm really stuck so I would like to know why we can't get three inputs. Here's partial code:

#include <stdio.h>

int main()
{
    int num1;
    int num2;
    char x;

    printf("Enter a number:\n");
    scanf("%d\n",&num1);
    printf("Enter another number:\n");
    scanf("%d\n",&num2);
    printf("Choose an operation sign:\n");
    scanf("%c\n",&x);

...

Like this it asks for the first input two times, like this:

Enter a number:
1
2
Enter another number:
3
Choose an operation sign:
-

If I remove the \n it skips the last scanf.

Can you help me understand why?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0plus1
  • 4,475
  • 12
  • 47
  • 89
  • Note that with the example input above, you get `num1 == 1`, `num2 == 2`, `x == '3'`. – undur_gongor Oct 19 '11 at 09:15
  • 1
    if you remove the \n, the program doesn't skip the last scanf. instead, the \n which is still left behind in the buffer by scanf gets stored in variable x. – Farhan Oct 19 '11 at 09:17

3 Answers3

4

Read here: scanf() leaves the new line char in buffer?

Solution:

int main()
{
    int num1;
    int num2;
    char x;

    printf("Enter a number:\n");
    scanf("%d",&num1);
    printf("Enter another number:\n");
    scanf("%d",&num2);
    printf("Choose an operation sign:\n");
    scanf("\n%c",&x); /* See the \n <---------------- */
}

An alternative:

char buf[2]; /* We need 2 characters for the null */
scanf("%1s", buf); /* We ask max 1 character (plus null given by scanf) */
char x = buf[0]; /* We take the first character */

As a small note, thanks to how scanf works, with both the solutions you can insert directly in the first "input" all the data and the various scanf will take their part. So you could insert 123 234 + and it would be split in the three variables correctly.

Community
  • 1
  • 1
xanatos
  • 109,618
  • 12
  • 197
  • 280
  • 2
    See this question for another way to ensure all junk is flushed from stdin between reads: [I am not able to flush stdin](http://stackoverflow.com/questions/2187474/i-am-not-able-to-flush-stdin) – Daniel Buckmaster Oct 19 '11 at 09:18
  • @Daniel In the end there isn't a "portable" solution. Even the C FAQ tells it and suggests an alternative http://c-faq.com/stdio/stdinflush2.html – xanatos Oct 19 '11 at 09:21
  • @xanatos the C FAQ page you listed has a portable code snippet for clearing out the buffer :P – Farhan Oct 19 '11 at 09:27
  • @Farhan Yes you are right but I was looking at it from another POV. In the end it's breaking the "standard" scanf working, where you can pre-set the next values (so if you had inputted `5 3` you would have "filled" the first two scanf and with `5 3 +` you have the whole reverse polish operation) – xanatos Oct 19 '11 at 09:30
1

Yes, scanf does not remove the newline, and you can't flush stdin, so how about this:

int num1;
char nleater;
printf("Enter a number:\n");
scanf("%d%c", &num1, &nleater);

or indeed this:

printf("Enter number sign number: ");
scanf("%d %c %d",&num1,&x,&num2);
printf("%d %c %d", num1, x, num2);
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
M. Wangel
  • 101
  • 1
  • 1
0

You can also try to use fflush, but it depends on the library implementation (stdio). The C reference for it can be found here.

I'll test this a bit later on and update my post and say whether it worked.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
lucian.pantelimon
  • 3,673
  • 4
  • 29
  • 46
  • invoking fflush on inputstream leads to undefined behaviour. – Farhan Oct 19 '11 at 09:23
  • Depends on compiler, VC empties the input stream. Of course, this is highly non-portable. – SvenS Oct 19 '11 at 10:20
  • Not on the compiler, but the actual library implementation (as it's stated in the reference). This means that the behavior can change when the library is updated. But for learning purposes you could use that as it's not a production environment where you may have a need for long term support or portability. – lucian.pantelimon Oct 19 '11 at 12:04