0
int main ()
{
    char c;
    int choice,dummy;
    do{
    printf("1. Print Hello\n2. Print World\n3. Exit\n");
    scanf("%d",&choice);
    switch(choice)
    {
        case 1 :
        printf("Hello\n");
        break;
        case 2:
        printf("World\n");
        break;
        case 3:
        exit(0);
        break;
        default:
        printf("please enter valid choice\n5");
    }
    printf("do you want to enter more?");
    scanf("%d",&dummy);
    scanf("%c",&c);
    }while(c=='y');
}

tried removing int dummy variable and dummy input, program exits without taking any character input. how is this helping the code to not to exit ?

2 Answers2

2

The scanf("%d",&dummy) removes a newline so the subsequent scanf("%c",&c); works. Otherwise, it will take \n as its character.

The "extra" newline comes from the fact that it is left in the input stream by the original: scanf("%d",&choice);


To fix, remove the dummy related code and do:

scanf(" %c",&c);

Note the preceding space in the format. This tells scanf to skip over whitespace (which includes newlines).


The fully corrected code is:

#include <stdio.h>
#include <stdlib.h>

int
main(void)
{
    char c;
    int choice;

    do {
        printf("1. Print Hello\n2. Print World\n3. Exit\n");

        scanf("%d", &choice);
        switch (choice) {
        case 1:
            printf("Hello\n");
            break;
        case 2:
            printf("World\n");
            break;
        case 3:
            exit(0);
            break;
        default:
            printf("please enter valid choice\n5");
        }

        printf("do you want to enter more?");
        scanf(" %c", &c);
    } while (c == 'y');

    return 0;
}
Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • It's interesting that scanf("%d") leaves the newline in the buffer if there is an integer present, and removes it if there isn't. I knew the former, not the latter. Is it documented somewhere? – pmacfarlane Dec 29 '22 at 21:30
  • @pmacfarlane I don't use `scanf` in my own code. IMO, it's something horrible to inflict on newbies. So, I haven't memorized all its documentation. But, I do believe that it has to work for input like: `123x` and code: `scanf("%d",&num); scanf("%c",&i_want_x);` So, it couldn't absorb the _next_ char after `123` [even if it was `\n`] I tested various versions of the code (e.g. with `dummy`, without, and the corrected version). The explanation was the only one that made sense. – Craig Estey Dec 29 '22 at 21:37
  • 1
    @pmacfarlane Actually, I think the semantics are that `%d` _will_ [implicitly] skip over leading whitespace [which includes newline]. So, the left over newline from `scanf("%d,&choice);` is the leading whitespace skipped by the subsequent `scanf("%d",&dummy);`. I didn't test it, but I believe the latter would return 0 for the count. – Craig Estey Dec 29 '22 at 21:47
  • 1
    The `%d` will skip whitespace, and then fail when the first non-whitespace character is not a digit. So it's just a horrible hack to skip whitespace. – user3386109 Dec 29 '22 at 21:50
2

Whoever wrote this doesn't understand how scanf format specifiers work.

The first call to scanf uses the %d format specifier. This reads and discards any leading whitespace, then reads a decimal integer. Assuming you pressed ENTER after typing in this integer, a newline character will be left in the input buffer.

The %c format specifier reads the first character in the input buffer but does not strip off trailing whitespace. So without the prior call reading dummy, this will read the newline that was stuck in the input buffer previously into c. That causes the comparison c=='y' to be false so the loop exits..

The extra call to scanf for dummy reads and discards the newline left in the input buffer and wait for an integer to be read. Presumably, the user will enter y or n given the prompt, so that call to scanf will not read anything more and will return 0, indicating that nothing matched. The following scanf then reads the y or n.

The proper way to handle this is to add a space before the %c format specifier to absorb leading whitespace instead of adding a "dummy" call:

printf("do you want to enter more?");
scanf(" %c",&c);
dbush
  • 205,898
  • 23
  • 218
  • 273