Why you mustn't write scanf(“%.2lf”, &a) in C?

2019-03-02 04:26发布

问题:

My friend have just started learning programming. He showed me his code and asked why it return some weird number. After taking a look at it, I saw that he was using scanf("%.2lf", &a) to take input, and by habit, I try to change it to normal. Then he asked me why it has some strange output. After googling around I still haven't find the answer.

Can anybody tell me why it doesn't work?

Thank you in advance and sorry for the long irrelevant story as well as my bad English.

Edit: added code below

    int main()
    {
        double a,b,c,delta;
        printf("Nhap vao 3 so thuc a,b,c: \n");
        scanf("%.2lf %.2lf %.2lf",&a,&b,&c);
        if(a == 0 && b == 0 && c == 0) printf("Phuong trinh co vo so nghiem");
        else if(a == 0 && b == 0 && c != 0) printf("Phuong trinh vo nghiem");
        else if(a == 0 && b != 0) printf("Phuong trinh co 1 nghiem la: %.2lf",-c/b);
        else if(a != 0)
        {
            delta=b*b-4*a*c;
            if(delta<0) printf("Phuong trinh vo nghiem");
            else if(delta == 0) printf("Phuong trinh co nghiem kep: %.2lf",-b/(2*a));
            else if(delta > 0) printf("Phuong trinh co 2 nghiem la:%.2lf, %.2lf",-(b-sqrt(delta))/(4*a),-(b+sqrt(delta))/(4*a));
        }
        return 0;
    }

回答1:

The C standard specifies that scanf conversion specifiers begin with %, and the POSIX standard specifies they begin with either % or %n$.

Neither the C standard nor the POSIX standard allows for a . in the conversion specifier, so this character is invalid.

You may have a decimal integer in your conversion specifier before the type specifier, but it specifies the maximum field width of the type. This means that scanf will read at most 2 characters before stopping when passed %2lf.

Additionally, lf specifies that the value should be a double, so a should be of type double.



回答2:

The posted code does not work because it causes undefined behavior. The . character is not a valid directive or modifier for scanf() format strings. According to §7.21.6.2 13 of the C Standard, "If a conversion specification is invalid, the behavior is undefined".

Frighteningly, one consequence of undefined behavior may be that code appears to work, at least sometimes. But then code may fail spectacularly under different circumstances, or on different platforms. This highlights the importance of always reading the documentation for any functions being used, with special attention paid to what the Standard has to say.



标签: c scanf