tags:

views:

103

answers:

3

I am getting a weird problem while using scanf() to store data into a union.

Here's my code

#include <stdio.h>

union Student
{
    float score;
    char grade;
};

int main(void)
{
    union Student jack;

    printf("Enter student score : ");
    scanf("%f", &jack.score);
    printf("Score : %f", jack.score);

    jack.score=0;

    printf("Enter student grade : ");
    scanf("%c", &jack.grade);
    printf("Grade : %c", jack.grade);

}

I get the following output

searock@searock-desktop:~/Desktop$ ./union
Enter student score : 12
Score : 12.000000Enter student grade : Grade :

but if I change my code to:

#include <stdio.h>

union Student
{
    float score;
    char grade;
};

int main(void)
{
    union Student jack;

    printf("Enter student grade : ");
    scanf("%c", &jack.grade);
    printf("Grade : %c\n", jack.grade);

    printf("Enter student score : ");
    scanf("%f", &jack.score);
    printf("Score : %f\n", jack.score);

}

It gives me the exact output [correct output]. I know this is not a good example, but can someone explain me what's going wrong?

Modified Code : Add \n before format string. [scanf("\n%c", &ch);]

#include <stdio.h>

    union Student
    {
        float score;
        char grade;
    };

    int main(void)
    {
        union Student jack;

        printf("Enter student score : ");
        scanf("%f", &jack.score);
        printf("Score : %f", jack.score);

        jack.score=0;

        printf("Enter student grade : ");
        scanf("\n%c", &jack.grade);
        printf("Grade : %c", jack.grade);

    }
+2  A: 

The difference is because of the \n in the string. These prevent the string from being cached in the output buffer and instead are immediately displayed on the screen.

JaredPar
I have removed /n from program but it still gives me the same error. I request you to copy the code the code and try running it. I am clueless about what's going wrong.
Searock
+1  A: 

In the first example you read a float and then the following character, which will be the newline that follows the float (you pressed the Enter key after inputting the float).

IN the second example the scanf() format specifiers include that newline, so the first scanf() reads a character followed by a newline and the second scanf() reads a float followed by a newline.

sth
I am sorry but I can't understand what you are trying to say.
Searock
+2  A: 

In the first example, the first scanf() reads a number up to but not including the newline (assuming you don't type just blanks and newlines; if you do, it will continue waiting for input until you provide a number or a non-number - where blanks etc do not count as either a number or a non-number). Then the second scanf() with the '%c' format specifier does not skip white space (unlike most other format specifiers) and reads the newline (assuming you typed a newline immediately after the end of the number; if you typed something else - white space or a letter, perhaps, it reads that character), completely ignoring anything you typed on the second line. (Indeed, when I run the code, it does not wait for me to enter anything for the second lot of input. Try typing "3.14+C" or "3.14C" and a newline.)

In the second example, the first scanf() reads the first character. The second scanf() skips over white space, including newlines, until it finds either a number or something that is definitively not a number (like a letter).

This is a beautiful demonstration of why most people avoid scanf(); it is very difficult to provide satisfactory control over it. You would be better off reading lines (perhaps using fgets(); definitely not using gets()) and then parsing them with sscanf(). You would then get sane behaviour for both examples.

Note that your problem is completely unrelated to the use of a union; your code is fine in the way that is working. Your problem is all tied up with the use of scanf().

Minor recommendation: when printing lines of output - other than prompts - include a newline at the end of the format string.

Jonathan Leffler
@Jonathan Leffler Thanks for the beautiful explanation. Thanks a lot : )
Searock