Thread: checking scanf return value

  1. #1
    Registered User
    Join Date
    Apr 2019
    Posts
    662

    checking scanf return value

    While tidying up the code on my latest project i decided its about time i learnt to check that the user is inputting the correct data. my understanding of the return value of scanf is an int to the value of he number of items read in. ie
    scanf("%d", &a); will return 1. if the user just hit enter scanf would sit there waiting for a number to be entered.
    Code:
    int main()
    {
        int a, b, x;
    
        printf("please enter 2 numbers between 1 and 10 ");
        x = scanf(" %d %d", &a, &b);
        while (x != 2)
        {
            printf("incorrect input please enter 2 numbers between 1 and 10 ");
            x = scanf(" %d %d", &a, &b);
        }
    
    
        return 0;
    }
    if the above is correct why is this an infinite loop
    coop

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,158
    You need to get rid of the invalid input, otherwise the next scanf call will try to read it, and fail again.

    Because this kind of interactive I/O tends to be line-based in that you enter your input on a line, then output is printed, then you enter your input on another line, one approach is to combine fgets with sscanf instead of just using scanf. So, the fgets call reads the line from the input buffer into an array, then sscanf parses the content of the array into your output variables. If sscanf fails, you don't have to worry about discarding invalid input because the line of input has already been successfully read.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Apr 2019
    Posts
    662
    thanks i have it working
    Code:
    int main()
    {
        int a, b, x;
        char array[4];
    
        printf("please enter 2 numbers between 1 and 10 ");
        fgets(array, sizeof(array), stdin);
        x = sscanf(array, " %1d%1d", &a, &b);
        while (x != 2)
        {
            printf("inccorect entery please enter 2 numbers beteen 1 and 10 ");
            fgets(array, sizeof(array), stdin);
            x = sscanf(array, " %1d%1d", &a, &b);
        }
        printf("x = %d a = %d b = %d\n", x, a ,b);
    
        return 0;
    }
    why does the array have to be four to allow entry of "3 4" though
    coop

  4. #4
    Registered User
    Join Date
    Apr 2019
    Posts
    662
    never mind looking at my deceleration its a char array so even though i am dealing with numbers its still a string and there for to hold the string "Coop" in an array i would declare it with a size of 5 for the \0 character
    coop

  5. #5
    Registered User
    Join Date
    Feb 2019
    Posts
    533
    Quote Originally Posted by cooper1200 View Post
    never mind looking at my deceleration its a char array so even though i am dealing with numbers its still a string and there for to hold the string "Coop" in an array i would declare it with a size of 5 for the \0 character
    coop
    If you need to enter 2 values between 1 and 10 you'll need, at least 7 chars: "XX XX\n\0" (fgets() will get the \n from stdin). BUT, what if you enter "10__________20" (10 spaces -- change each '_' for a space)?

    Instead of using fgets() I recommend using POSIX getline() to allocate the buffer dinamically...
    Code:
    char *buffer = NULL;
    size_t size = 0;
    if ( getline( &buffer, &size, stdin ) == -1 )
    { ... error ... }
    ... do something ...
    free( buffer ); // free the allocated buffer.
    Last edited by flp1969; 05-12-2019 at 06:50 AM.

  6. #6
    Registered User
    Join Date
    Apr 2019
    Posts
    662
    ok now what am i doing wrong
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct
    {
        char name[10];
        int age;
        char age_array[3];
    }DETAILS;
    
    int main()
    {
        int a, x = 0;
        DETAILS record;
    
        printf("Please enter your name upto 10 characters: ");
        while (x != 1)
        {
            fgets(DETAILS.name, sizeof(DETAILS.name), stdin);
            x = sscanf(DETAILS.age_array, " %s", DETAILS.name);
            if (x != 1)
            {
                printf("incorrect entry Please enter your name upto 10 characters: ");
            }
        }
    
        return 0;
    }
    coop

  7. #7
    Registered User
    Join Date
    Apr 2019
    Posts
    662
    Quote Originally Posted by laserlight View Post
    You need to get rid of the invalid input, otherwise the next scanf call will try to read it, and fail again.

    Because this kind of interactive I/O tends to be line-based in that you enter your input on a line, then output is printed, then you enter your input on another line, one approach is to combine fgets with sscanf instead of just using scanf. So, the fgets call reads the line from the input buffer into an array, then sscanf parses the content of the array into your output variables. If sscanf fails, you don't have to worry about discarding invalid input because the line of input has already been successfully read.
    Quote Originally Posted by flp1969 View Post
    If you need to enter 2 values between 1 and 10 you'll need, at least 7 chars: "XX XX\n\0" (fgets() will get the \n from stdin). BUT, what if you enter "10__________20" (10 spaces -- change each '_' for a space)?

    Instead of using fgets() I recommend using POSIX getline() to allocate the buffer dinamically...
    Code:
    char *buffer = NULL;
    size_t size = 0;
    if ( getline( &buffer, &size, stdin ) == -1 )
    { ... error ... }
    ... do something ...
    free( buffer ); // free the allocated buffer.
    so which is the right one? which do i research to answer my question.
    coop

  8. #8
    Registered User
    Join Date
    Feb 2019
    Posts
    533
    That sensation of cursing is back...

    cooper1200, laserlight said "one approach is..." meaning there are others.
    I said: "I recommend..." means this is ONE of those other approaches...

    BOTH are right! research BOTH!

  9. #9
    Registered User
    Join Date
    Apr 2019
    Posts
    662
    Quote Originally Posted by flp1969 View Post
    That sensation of cursing is back...
    glad were on the same wave length chuck

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. checking if int when using scanf. Help!
    By xtrmi in forum C Programming
    Replies: 4
    Last Post: 09-18-2008, 11:26 PM
  2. Replies: 12
    Last Post: 04-07-2007, 11:11 AM
  3. error checking problem with scanf
    By Axel in forum C Programming
    Replies: 1
    Last Post: 10-19-2005, 05:46 AM
  4. scanf() error checking
    By Dangerous Dave in forum C Programming
    Replies: 7
    Last Post: 11-26-2003, 06:02 PM
  5. Error Checking for scanf
    By Dangerous_Dave in forum C Programming
    Replies: 2
    Last Post: 11-12-2003, 11:30 AM

Tags for this Thread