Thread: fgets - user input including spaces

  1. #1
    Microsoft. Who? MethodMan's Avatar
    Join Date
    Mar 2002
    Posts
    1,198

    fgets - user input including spaces

    I am trying to read user input, including spaces.

    ex:
    //this one will include spaces
    printf("Enter your name: ");
    fgets(name,sizeof(name),stdin);

    printf("Enter your age: ")
    scanf("%d", &age);

    The problem is, it doesnt take any input from fgets and proceeds directly to the next input line.

    Why is this happening?

    Thanks.
    -MethodMan-

    Your Move:Life is a game, Play it; Life is a challenge, Meet it; Life is an opportunity, capture it.

    Homepage: http://www.freewebs.com/andy_moog/home.html

  2. #2
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >it doesnt take any input from fgets and proceeds directly to the next input line
    Are you sure fgets doesn't read anything? fgets will return if one of four things happens: end-of-file is reached, the buffer is filled, a newline is found or an error occurs. I would bet my next paycheck that previous input left a newline in the stream and fgets terminates immediately after reading it. Execution then moves to the scanf call. Maybe if you tested the return value of fgets you would have better luck in diagnosing the problem.
    My best code is written with the delete key.

  3. #3
    Microsoft. Who? MethodMan's Avatar
    Join Date
    Mar 2002
    Posts
    1,198
    Actually there is a previous input from the user from a menu.

    If I flush stdin before I get to this section of input (code in the first post) would that solve the problem?

    Thanks

    //just tried fflsuh(stdin); before the input, same result as before
    Last edited by MethodMan; 03-12-2004 at 11:38 AM.
    -MethodMan-

    Your Move:Life is a game, Play it; Life is a challenge, Meet it; Life is an opportunity, capture it.

    Homepage: http://www.freewebs.com/andy_moog/home.html

  4. #4
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    fflush(stdin) is undefined behaviour - fflush should be used on output streams, not input.

    You might try a look at this particularly 12.18, and then 12.17, 12.19, 12.20 and then 12.26.

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Also, remember that scanf() and fgets() don't mix well.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Yeah; why not use fgets() again, then sscanf() or some other (better) function to get the decimal value?

    Dave

  7. #7
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    If you wanted to get numbers you could try something like this. I will add a disclaimer that I have not run this code past anybody, to see if it is ok, so I would appreciate any criticism of the code, so I can improve it if necessary. thanks

    Code:
     
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>		
    
    void getline(char line[], int len);
    
    int main(void)
    {
        char text[40];
        double x = 0.0;
        double y = 0.0;
        printf("\n\nEnter some text: ");
        getline(text, 40);
        x = atof(text);
        printf("Enter some more text: ");
        getline(text, 40);
        y = atof(text);
        printf("\n%.2f minus %.2f equals: %.2f\n\n", x, y, x - y);
        return 0;
    }
    
    void getline(char line[], int len)
    {
        char buf[len];
        char *p;
    
        fflush(stdout);
        fgets(buf, sizeof buf, stdin);
        if ((p = strchr(buf, '\n')) != NULL) { 
    	 *p = '\0';  
              strcpy(line, buf);
        }
    }

  8. #8
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Couple of problems in getlini()

    Is the following legal?

    Code:
        char buf[len];
    Borland bcc gives an error message:
    Constant expression required in function getline
    Just to get things going forward, I substituted
    Code:
        char buf[40];
    And it compiles and runs.

    The problem that I now have is: what if someone enters something more than 40 characters? ("Not likely that anyone would do such a thing," you say; "Absolutely guaranteed that some day, some time, someone will do it," I say.)

    Since fgets() has stopped before the input buffer has been fully "used up". a subsequent call to fgets() picks up where the previous one left off.

    Try it. (I got the same results with Borland bcc and gnu gcc on my Windows XP box.)

    What to do? (Note that, according to information in previous threads, fflush() doesn't help -- I never tried it, so I don't know, but I wouldn't count on fflush() to help input scanning problems.)

    Well try this:

    (--- remainder of post deleted by the Big Giant Head in the sky --- "Left as an exercise for the student.")

    Regards, and keep 'em coming! I like this kind of stuff --- it really makes me think!

    Dave

  9. #9
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    I actually was not counting on fflush to deal with improper input, but I was thinking there could be problems with too much user input.

    I just looked at the program in light of your suggestions, and indeed it messes up if more than 40 characters are entered. I will work on this some more.

    ~/

    [edit]

    Ok, I am lost here - I was thinking I could somehow implement strlen and use it to read in one less than the size of the buffer, and go from there, but I was just reading that fgets already reads in at most one less than the size characters from the stream. ergh. Any help on how I can fix my function, or?

    [/edit]
    Last edited by kermit; 03-12-2004 at 01:05 PM.

  10. #10
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    "Off of the top of my head"

    In getline(), use

    Code:
        char buf[BUFSIZ];
    and use fgets() like you do.

    (Note that BUFSIZ is defined in <stdio.h>, and varies from compiler to compiler. If you're curious, use printf() to find out what it is for your case.)

    Then, use strncpy(line, buf, ???); to copy appropriately. (Where ??? means, "You figure it out.")

    Cheers!

    Dave

  11. #11
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    Maybe I am missing something here, but does not using BUFSIZ in this case just 'postpone' the problem occuring. For example, if I set size in the fgets call to 40, there are problems after 40 characters are entered. Now if I set the buffer to BUFSIZ, and make size the same, it makes the size a minimium of 256, and in my case 8192. So does this mean that when 8200 characters are entered, there will be problems? Granted, someone is not likely to enter that many characters, but then again....

  12. #12
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Would any of this be helpful?
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  13. #13
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    It is helpful. The first thing I did was modify my code a little to look like this (which was not your suggestion but someone else who posted in your thread):

    Code:
    #include <stdio.h>
    #include <string.h>
    
    void getline(char line[], int len);
    
    int main(void)
    {
        char text[10];
        printf("\n\nEnter some text: ");
        getline(text, 10);
        printf("\n\nYou entered this text: %s\n\n", text);
    
        printf("\n\nEnter some more text: ");
        getline(text, 10);
        printf("\n\nYou entered this text: %s\n\n", text);
        return 0;
    }
    
    void getline(char line[], int len)
    {
        char *p;
    
        fflush(stdout);
        fgets(line, len, stdin);
        if ((p = strchr(line, '\n')) != NULL) {   /* check if last element is a newline */
    	 *p = '\0';                          /* make last element a null character */
        }
    }
    Of course this gets me a problem...lol - I liked the way the code looked though, compared to what I had. I realised that that the input would carry over to the next fgets call, but its fun to mess with other people's code sometimes.

    Anyway, I had a look at your code, and I am sure to be able to understand it with your copious comments. It is too bad the discussion on it could not have gone further, to see if any of the issues people had could be adressed somehow. Anyway, I am developing a splitting headache so no more computer for me for a while. Thanks for the link Dave.

    ~/

  14. #14
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Originally posted by kermit
    Maybe I am missing something here, but does not using BUFSIZ in this case just 'postpone' the problem occuring. For example, if I set size in the fgets call to 40, there are problems after 40 characters are entered. Now if I set the buffer to BUFSIZ, and make size the same, it makes the size a minimium of 256, and in my case 8192. So does this mean that when 8200 characters are entered, there will be problems? Granted, someone is not likely to enter that many characters, but then again....
    Why would there be a problem?
    Code:
    char buf[BUFSIZ] = {0};
    fgets( buf, BUFSIZ, stdin );
    if( strchr( buf, '\n' ) == NULL )
    {
        ...more than BUFSIZ entered, deal with it...
    }
    [edit]Beat me to the submit button.[/edit]

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

  15. #15
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    It's an interesting question (what happens if the user attempts to enter more than BUFSIZ characters), and the answer is "it depends". (Isn't that the answer to all questions?)

    In Borland C , version 5.1.1, BUFSIZ = 512, and if I try to enter more than 512 characters, it simply stops accepting inputs(!) until I hit the Enter key. How civilized!

    In gnu gcc 3.3.1 (Cygwin), BUFSIZ = 1024, and fgets() continues accepting characters after 1024. (I got tired of holding down the key, so don't know if it ever gives up.) The next call to fgets() picks up where the previous call left off. The important thing is that it doesn't crash. (Functions like fgets and strncpy, and strnxxx, are designed to allow us to prevent buffer-overflow crashes, so there may not be anything magic about BUFSIZ.)

    Of course, any input obtained by holding numeric keys down for this many characters may not be reliable.

    What if I really wanted to enter 1 followed by 500 zeros? Do you think I could actually do it? Suppose I really could (actually the input may come from a file, and someone could have written 1 followed by 500 zeros). How should the program handle it? Is this a valid number? Should all programs check validity of input data before attempting to use the information in calculations?

    Lots of questions here; what are the answers?

    It depends.

    Dave

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Why doesn't fgets() read my input?
    By laczfinador in forum C Programming
    Replies: 10
    Last Post: 05-13-2009, 04:20 AM
  2. What Would You Use To Read User Input?
    By djwicks in forum C Programming
    Replies: 11
    Last Post: 04-05-2005, 03:32 PM
  3. SSH Hacker Activity!! AAHHH!!
    By Kleid-0 in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 03-06-2005, 03:53 PM
  4. vectors and user input
    By Chaplin27 in forum C++ Programming
    Replies: 6
    Last Post: 01-17-2005, 10:23 AM
  5. Nested Structures - User Input
    By shazg2000 in forum C Programming
    Replies: 2
    Last Post: 01-09-2005, 10:53 AM