Thread: scanf and whitespaces

  1. #1
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154

    scanf and whitespaces

    Hi,

    I know this is a common topic on this forum, but I haven't found a nice, clean solution anywhere. Main thing is that I'm never sure whether the solution described really applies to my code. And when I try to integrate pieces of code from those solutions in my own code it never does what I want it to .

    I request some inputs from the user:

    Code:
    puts("\n--------------------------------");
        puts("Please enter the vehicle make: ");
        scanf("%s", &vehicle_make);
        puts("Please enter the vehicle model: ");
        scanf("%s", &vehicle_model);
        puts("Please enter the model year:");
        scanf("%s", &vehicle_year);
        puts("Please enter your name:");
        scanf("%s", &tester);
        puts("--------------------------------");
    Now when I have for example a 205 GTI and enter that after Please enter the vehicle model it skips Please enter the model year. I found out that it is because of the space between 205 and GTI, because GTI is stored as vehicle_year if I enter the string above.

    Has anyone got a solution for this problem? I know it's probably quite simple, but not for me (yet) .

    Thanks very much in advance!

    René

  2. #2
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Yeah, don't use scanf() use fgets().

    Code:
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    
    int main()
    {
        char vehicle_make[30], vehicle_model[30], vehicle_year[30], tester[30];
        
        puts("\n--------------------------------");
        puts("Please enter the vehicle make: ");
        fgets(vehicle_make, 30, stdin);
        puts("Please enter the vehicle model: ");
        fgets(vehicle_model, 30, stdin);
        puts("Please enter the model year:");
        fgets(vehicle_year, 30, stdin);
        puts("Please enter your name:");
        fgets(tester, 30, stdin);
        puts("--------------------------------");
    }
    Last edited by SlyMaelstrom; 03-02-2006 at 10:45 AM.
    Sent from my iPad®

  3. #3
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154





    Hehe, just kidding...

    I hope it's as easy as you say but I'm off work now. I'll try this tomorrow morning first thing. Thanks!

  4. #4
    Registered User
    Join Date
    Feb 2006
    Posts
    17
    Just make sure you don't forget that, in this case, if you type less than 29 characters, fgets() will also read a \n into the buffer and this might cause you trouble if you're going to compare the string read with a constant like "quit".

  5. #5
    Registered User
    Join Date
    Jan 2006
    Posts
    100
    Can't you also use getchar() after a scanf() to flush the buffer and avoid that error?

  6. #6
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Quote Originally Posted by richdb
    Can't you also use getchar() after a scanf() to flush the buffer and avoid that error?
    No, how would that help the fact that scanf only reads up to whitespace?
    Sent from my iPad®

  7. #7
    Registered User
    Join Date
    Jan 2006
    Posts
    100
    Sorry I was thinking about using a getchar() by itself before a getchar assignment if characters are to be entered after the scanf():
    Code:
                                                    scanf("%d" , &num);
                                                    getchar();
                                                    x = getchar();

  8. #8
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    Quote Originally Posted by SlyMaelstrom
    Yeah, don't use scanf() use fgets().
    Yeah, fgets() works perfectly. Thanks very much for your help!

    Quote Originally Posted by tcpl
    Just make sure you don't forget that, in this case, if you type less than 29 characters, fgets() will also read a \n into the buffer and this might cause you trouble if you're going to compare the string read with a constant like "quit".
    Yeah, I noticed! Is there an easy way to fill up the fgets() string up to 29 characters? Or just simply to delete the '\n' at the end? I write this data to an exernal text file where formatting is important as well, so it would be nicer if I don't have that \n at the end.

    Thanks

    Edit: is it flushing I need to do?
    Last edited by rkooij; 03-03-2006 at 03:16 AM.

  9. #9
    Registered User
    Join Date
    Feb 2006
    Posts
    155
    Code:
    vehicle_make[strlen(vehicle_make)-1]='\0' ;
    just use this after the assignment , this clears the '\n' at the end of vehicle_make array.
    Last edited by qqqqxxxx; 03-03-2006 at 03:31 AM.

  10. #10
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    Quote Originally Posted by qqqqxxxx
    Code:
    vehicle_make[strlen(vehicle_make)-1]='\0' ;
    just use this after the assignment , this clears the '\n' at the end of vehicle_make array.
    Simple and effective, what more do you want?

    Thanks a lot, appreciate your help guys!

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    It's not effective, it's bugged. fgets does not guarantee a newline. Thus, if there isn't one, you've just nuked the last character in your word/line.



    Quzah.
    Hope is the first step on the road to disappointment.

  12. #12
    Registered User
    Join Date
    Feb 2006
    Posts
    17
    Is there an easy way to fill up the fgets() string up to 29 characters? Or just simply to delete the '\n' at the end? I write this data to an exernal text file where formatting is important as well, so it would be nicer if I don't have that \n at the end.
    I usually do this:
    Code:
    #include <string.h>
    void cleanup(char *s)
    {
        char *p;
        int c;
    
        if ((p = strchr(s, '\n')) != NULL)
            *p = '\0';
        else
            while ((c = getchar()) != EOF && c != '\n')
                ;
    }
    If fgets read everything that was to read from the input buffer, a \n will be found on s, otherwise the input buffer will still have the \n and problably more characters so the else takes care of that.

  13. #13
    Registered User
    Join Date
    Feb 2006
    Posts
    155
    Code:
    if(vehicle_make[strlen(vehicle_make)-1]=='\n')
     vehicle_make[strlen(vehicle_make)-1]='\0';
    this should do the trick?

  14. #14
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    About as much as it did the trick the last time you said it.

    Quote Originally Posted by Quzah
    It's not effective, it's bugged. fgets does not guarantee a newline. Thus, if there isn't one, you've just nuked the last character in your word/line.
    Sent from my iPad®

  15. #15
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Quote Originally Posted by tcpl
    I usually do this:
    Code:
    #include <string.h>
    void cleanup(char *s)
    {
        char *p;
        int c;
    
        if ((p = strchr(s, '\n')) != NULL)
            *p = '\0';
        else
            while ((c = getchar()) != EOF && c != '\n')
                ;
    }
    If fgets read everything that was to read from the input buffer, a \n will be found on s, otherwise the input buffer will still have the \n and problably more characters so the else takes care of that.
    Alternatively:
    Code:
    char buf[20];
    char clear[20]
    int  len;
    
    fgets(buf, 20, stdin);    // get a line
    len = strlen(buf) - 1;    // last character's position
    if (buf[len] == '\n')     // test for RETURN
    {
        buf[len] == '\0';     // clear RETURN
    }
    else
    {        // Too many characters were entered
        do   // read off the rest of the input buffer
        {
            fgets(clear, 20, stdin);  // get excess
            len = strlen(buf) - 1;
        }  while (clear[len] != '\n');
    }
    Just another option.
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

Popular pages Recent additions subscribe to a feed