4

When I compile this code, it leads to scanf asking for a value twice when I pick choice A. What am I missing here?

This isn't the first time this is encountered, so I'm suspecting I'm failing to grasp something rather fundamental with scanf.

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

int main()
{

char choice;
printf("1. 'enter 'A' for this choice\n");
printf("2. 'enter 'B' for this choice\n");
printf("3. 'enter 'C' for this choice\n");

scanf("%c", &choice);

switch (choice)
{
case 'A':
    {
        int a =0;
        printf("you've chosen menu A\n");
        printf("enter a number\n");
        scanf("%d\n", &a);
        printf("%d\n", a);
    }
break;
case 'B':
printf("you've chosen B\n");
break;
case 'C':
printf("you've chosen C\n");
break;
default:
printf("your choice is invalid\n!");
break;
}

return 0;

}
andresimo
  • 41
  • 2
  • 1
    Unrelated,but shouldn't the `\n` in the `printf` in the `default` case be placed **after** the exclamation mark? – Spikatrix Nov 27 '14 at 11:00

4 Answers4

6

scanf("%d\n", &a); should be scanf("%d", &a);

Also read Related question.

In former case after reading an integer and storing into a, scanf's argument string is not exhausted. Looking at \n, scanf would consume all the whitespaces (newline, tab, spaced etc) it sees (And will remain blocked) until it encounters a non-whitespace character. On encountering a non-whitespace character scanf would return.

Learning: Don't use space, newline etc as trailing character in scanf. If the space character is in the beginning of argument string, scanf may still skip any number of white space characters including zero characters. But when whitespace is a trailing characters, it would eat your new line character also unless you type a non-whitespace character and hit return key.

Community
  • 1
  • 1
Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
  • The space before `%c` is unecessary here. – Spikatrix Nov 27 '14 at 10:57
  • @CoolGuy You are loosing nothing with that space. Read Related question 2. Moreover having the space would skip unwanted newline or space in the beginning. – Mohit Jain Nov 27 '14 at 11:00
  • Makes sense. But how does the unwanted newlines and/or spaces appear in the `stdin` in the beginning of the program? – Spikatrix Nov 27 '14 at 13:50
  • @CoolGuy If you are redirecting a file or even using stdin, there may be unwanted space sometimes mistyped by mistake. Because there is almost no harm in using a whitespace in beginning while scanning a char, I suggested to use it but later remove it not to confuse the main point of the answer. – Mohit Jain Nov 27 '14 at 13:57
4

Simply remove the newline character from scanf("%d\n", &a); and it will not ask to enter a value twice

Raghvendra Kumar
  • 1,328
  • 1
  • 10
  • 26
0
scanf("%d", &a);

Remove a newline character while scanning

Gopi
  • 19,784
  • 4
  • 24
  • 36
0
// the trailing '\n' in the scanf format string 
// is what is causing the dual inputs

// the returned value from I/O statements (I.E. scanf)
// needs to be checked to assure operation was successful

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

int main()
{

    char choice;
    printf("1. 'enter 'A' for this choice\n");
    printf("2. 'enter 'B' for this choice\n");
    printf("3. 'enter 'C' for this choice\n");

    // note 
    //    leading ' ' in format string to consume leading white space 
    //    and no trailing '\n'
    if( 1 != scanf(" %c", &choice) ) 
    { // then, scanf failed
        // handle error condition
        perror("scanf failed for choice");
        exit(EXIT_FAILURE);
    }

    // implied else, scanf successful

    switch (choice)
    {
        case 'A':
        { // braces needed due to variable declaration
            int a = 0; // corrected ':' to ';'
            printf("you've chosen menu A\n");
            printf("enter a number\n");

            // note 
            //    leading ' ' in format string to consume leading white space 
            //    and no trailing '\n'
            if( 1 != scanf(" %d", &a) ) 
            { // then scanf failed
                // handle error condition
                perror("scanf failed for number");
                exit(EXIT_FAILURE);
            }
            // implied else, scanf successful
            printf("%d\n", a);
        }
        break;

        case 'B':
            printf("you've chosen B\n");
        break;

        case 'C':
            printf("you've chosen C\n");
        break;

        default:
            printf("your choice is invalid\n!");
        break;
    } // end switch

    return 0;

} // end function: main
user3629249
  • 16,402
  • 1
  • 16
  • 17