Search code examples
cscanf

Some trouble with scanf() function


It may seem simple to you, but I really don't understand what's wrong. Why is the value I enter for b assigned to h? That is, I can no longer enter steps. And the program immediately outputs a line. What is the problem?

int main(int argc, char** argv) {
    double a, b, h, x, x1, E;
    printf(" Input eps:");
    scanf("%lf", &E);
    printf(" Input [a,b]:");
    scanf("%lf,%lf", &a, &b);
    printf(" Step :");
    scanf("%lf", &h);
    printf ("%lf,%lf,%lf,%lf", E, a, b, h);
    return 0;
}

enter image description here


Solution

  • scanf("%lf,%lf",&a,&b);
    

    That comma there in the format string means you need to enter a comma. Otherwise the scan fails after one item, leaving the 5 in the input stream.

    If you checked the return value of the scanf, you would see it was one rather than two. That's why b is zero (though it could be any arbitrary value as you do not initialise it) and the 5 remaining in the input stream is being used in the following scanf which populates h.

    The simplest fix is probably just use "%lf %lf" instead, with a space rather than a comma. White space is not considered a literal requirement for the exact characters, it will simply skip to the first non-whitespace character. From the ISO C11 standard on the scanf directives:

    The format is composed of zero or more directives: one or more white-space characters, an ordinary multibyte character (neither % nor a white-space character), or a conversion specification.

    A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read.

    A directive that is an ordinary multibyte character is executed by reading the next characters of the stream. If any of those characters differ from the ones composing the directive, the directive fails and the differing and subsequent characters remain unread.

    A directive that is a conversion specification defines a set of matching input sequences, as described below for each specifier.

    The comma, being neither whitespace nor a conversion specification (these start with %), falls under the purview of the "ordinary multibyte character" paragraph above.


    As an aside, this is illustrated with the following program:

    #include <stdio.h>
    
    int main()  {
        double d1 = 999, d2 = 998;
        printf("Enter two doubles: ");
        int count = scanf("%lf,%lf", &d1, &d2);
        printf("count = %d, d1 = %f, d2 = %f\n", count, d1, d2);
    
        printf("Rest of input line is: [");
        int ch;
        while ((ch = getchar()) != '\n') {
            putchar(ch);
        }
        puts("]");
    
        return 0;
    }
    

    This produces the following on my system:

    pax:/home/pax> ./testprog # with space separator
    Enter two doubles: 4.6 9.2
    count = 1, d1 = 4.600000, d2 = 998.000000
    Rest of input line is: [ 9.2]
    
    pax:/home/pax> ./testprog # with comma separator
    Enter two doubles: 4.6,9.2
    count = 2, d1 = 4.600000, d2 = 9.200000
    Rest of input line is: []