Thread: Need a bit of help on scanf

  1. #1
    Registered User
    Join Date
    Aug 2012
    Posts
    11

    Unhappy Need a bit of help on scanf

    Hi there, I'm fairly new to C and after doing some research I know that a lot of people said to avoid scanf and should just use gets or something.. but.. I'm going to use it for now :)

    The problem is..

    Here is the code
    Code:
    #include <stdio.h>
    #include <ctype.h>
    #include <stdlib.h>
    #define FLUSH_STDIN while ( getchar() != '\n' )
    
    
    int main(void){
    
    
        /* Clear stdout buffer */
        setvbuf(stdout, NULL, _IONBF, 0);
        setvbuf(stderr, NULL, _IONBF, 0);
    
    
        char s[80]; // Input String
        char width_c, height_c; // For storing the input
        int width, height; // For storing the input AFTER converted into int
        int area; // Area
    
    
        /* Prompt for width */
        printf("Please enter width: ");
        gets(s);
        sscanf(s, "%s", &width_c);
    
    
        /* Check if input is digit, if not... */
        while(!(isdigit(width_c))){
            printf("Input Error: Invalid format\n");
            printf("Please enter width: ");
            gets(s);
            sscanf(s, "%s", &width_c);
        }
    
    
        /* Prompt for height */
        printf("Please enter height: ");
        gets(s);
        sscanf(s, "%s", &height_c);
    
    
        /* Check if input is digit, if not... */
        while(!(isdigit(height_c))){
            printf("Input Error: Invalid format\n");
            printf("Please enter height: ");
            gets(s);
            sscanf(s, "%s", &height_c);
        }
    
    
        /* Convert string value into int */
        width = atoi(&width_c);
        height = atoi(&height_c);
    
    
        /* Display width and height */
        puts("------------------------");
        printf("Width is: %d\n", width);
        printf("Height is: %d\n", height);
    
    
        /* Calculate + print the area */
        area = width * height;
        puts("------------------------");
        printf("Area is: %d\n", area);
    
        return 0;
    }
    What I'm getting is :
    Code:
    Please enter width: 3
    Please enter height: 4
    ------------------------
    Width is: 0
    Height is: 4
    ------------------------
    Area is: 0
    There was something else that I tried.. and the result was:
    Code:
    Please enter width: 3
    Please enter height: 4
    ------------------------
    Width is: 3
    Height is: 43
    ------------------------
    Area is: 129
    as if the stdin buffer wasn't properly cleared.

    Any tips on how I should do this? Thanks :)
    P.S I'm using Eclipse CDT as IDE

  2. #2
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Code:
    sscanf(s, "%s", &width_c);
    Yur'e trying to read a string into a single character.

    Using gets() to read the input was a bad advice. Use fgets().

    Kurt

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    In the following snippet:
    Code:
    /* Clear stdout buffer */
        setvbuf(stdout, NULL, _IONBF, 0);
        setvbuf(stderr, NULL, _IONBF, 0);
    Your comment is misleading, this is not really clearing your buffer it is removing buffering from these streams.

    Jim

  4. #4
    Registered User
    Join Date
    Aug 2012
    Posts
    11
    Quote Originally Posted by ZuK View Post
    Code:
    sscanf(s, "%s", &width_c);
    Yur'e trying to read a string into a single character.

    Using gets() to read the input was a bad advice. Use fgets().

    Kurt
    Ah okay, any better way for replace this? the sscanf that is.
    Code:
    sscanf(s, "%s", &width_c);
    I did try to debug the code, and found out after I enter the "height_c" value, "width_c" was immediately change to null (0 '\0')

    Your comment is misleading, this is not really clearing your buffer it is removing buffering from these streams.

    thanks for the explanation I was using it to substitute all the fflush(stdout), because there's something wrong with eclipse console..
    Last edited by dendeer82; 08-03-2012 at 03:48 PM.

  5. #5
    Registered User
    Join Date
    Aug 2012
    Posts
    11
    nvm, solved.
    using fgets is the right choice, thanks Kurt

    changed the while loop into
    Code:
     while( sscanf(width_c, "%d", &width) != 1 )
    solved the problem..

  6. #6
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    thanks for the explanation I was using it to substitute all the fflush(stdout), because there's something wrong with eclipse console..
    What do you perceive to be the problem with the Eclipse console? You are really better off flushing the output buffer rather than turning off buffering altogether.

    Also note you are turning off buffering on the stderr stream, this stream doesn't use buffering by default so you don't need to turn it off.

    Jim

  7. #7
    Registered User
    Join Date
    Aug 2012
    Posts
    11
    Quote Originally Posted by jimblumberg View Post
    What do you perceive to be the problem with the Eclipse console? You are really better off flushing the output buffer rather than turning off buffering altogether.
    This is the reason I turned off the buffer, and It'll probably make the code more cleaner for this type of tiny program.
    CDT/User/FAQ - Eclipsepedia

    and yeah, I guess in professional programming it would be better to flush the output buffer in case of random bugs..

  8. #8
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Is width_c still declared as a single char? That is a problem that ZuK pointed out, and it's still a problem if you use fgets instead of gets.

  9. #9
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    I guess in professional programming it would be better to flush the output buffer in case of random bugs..
    Actually, since this is a bug in the Eclipse console, I would suggest not running this program through the Eclipse console, run it through a Window's command prompt. If you use the "hack" of turning off buffering while developing the program, before you "release" your program remove the "hack" and test the program in the Window's command prompt to insure everything is working correctly.

    Jim

  10. #10
    Registered User
    Join Date
    Aug 2012
    Posts
    11
    Is width_c still declared as a single char? That is a problem that ZuK pointed out, and it's still a problem if you use fgets instead of gets.
    ah right no, I actually changed the width_c into width_c[80].. sorry for not making things clear

    Actually, since this is a bug in the Eclipse console, I would suggest not running this program through the Eclipse console, run it through a Window's command prompt. If you use the "hack" of turning off buffering while developing the program, before you "release" your program remove the "hack" and test the program in the Window's command prompt to insure everything is working correctly.

    Yup, that would work. It is just so hard to change from Java into C -__- (Using eclipse for java) everything is so unfamiliar and in addition to that the eclipse CDT console is glitched make things so much harder. Windows command prompt still the way to go..

  11. #11
    Registered User
    Join Date
    Aug 2012
    Posts
    11
    Final Code btw..

    Code:
    #include <stdio.h>
    #include <ctype.h>
    #include <stdlib.h>
    #define FLUSH_STDIN while ( getchar() != '\n' )
    
    
    int main(void){
    
    
        /* Set stdout unbuffered */
        setvbuf(stdout, NULL, _IONBF, 0);
        setvbuf(stderr, NULL, _IONBF, 0);
    
    
        char width_c[80]; // For storing the width user input
        char height_c[80]; // For storing the height user input
        double width, height; // For storing the input AFTER converted into int
        double area; // Area
    
    
        /* Prompt for width */
        printf("Please enter width: ");
        fgets(width_c, 256, stdin);
    
    
        /* Check if input is digit, if not... */
        while( sscanf(width_c, "%lf", &width) != 1 ){
            printf("Bad input..\n");
            printf("Please enter width: ");
            fgets(width_c, 256, stdin);
        }
    
    
        /* Prompt for height */
        printf("Please enter height: ");
        fgets(height_c, 256, stdin);
    
    
        /* Check if input is digit, if not... */
        while( sscanf(height_c, "%lf", &height) != 1 ){
            printf("Bad input..\n");
            printf("Please enter height: ");
            fgets(height_c, 256, stdin);
        }
    
    
        /* Convert string value into int */
        width = atof(width_c);
        height = atof(height_c);
    
    
        /* Display width and height */
        puts("------------------------");
        printf("Width is: %lf\n", width);
        printf("Height is: %lf\n", height);
    
    
        /* Calculate + print the area */
        area = width * height;
        puts("------------------------");
        printf("Area is: %lf\n", area);
    
    
        return 0;
    }

  12. #12
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by dendeer82 View Post
    Code:
        char width_c[80]; // For storing the width user input
        fgets(width_c, 256, stdin);
    This is as bad as using gets. 256 is larger than the actual buffer size so you can still have a buffer overflow. I would use "sizeof(width_c)" here and in the rest of the fgets calls.

  13. #13
    Registered User
    Join Date
    Aug 2012
    Posts
    11
    ooohhh ok, I wasn't aware of that... new to C.. still need some more advices later
    thank you for pointing that out!

  14. #14
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Code:
    /* Convert string value into int */
    width = atof(width_c);
    height = atof(height_c);
    First, your comment is wrong (you convert the string to a double)

    Second, you have already converted the string to a double a few lines above (using sscanf).

    Bye, Andreas

  15. #15
    Registered User
    Join Date
    Aug 2012
    Posts
    11
    kk, forgot to change the comment... use to be atoi.. thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. scanf in c++
    By herWter in forum C++ Programming
    Replies: 5
    Last Post: 04-06-2009, 10:48 AM
  2. First scanf() skips next scanf() !
    By grahampatten in forum C Programming
    Replies: 5
    Last Post: 08-17-2004, 02:47 AM
  3. scanf
    By kurz7 in forum C Programming
    Replies: 2
    Last Post: 04-08-2003, 06:14 AM
  4. scanf() <-> esc key
    By ipe in forum C Programming
    Replies: 5
    Last Post: 03-12-2003, 10:27 AM
  5. scanf - data is "put back" - screws up next scanf
    By voltson in forum C Programming
    Replies: 10
    Last Post: 10-14-2002, 04:34 AM