Thread: fgets

  1. #1
    New_to_C
    Guest

    fgets

    Hi,

    I've been reading through the forums and noticed that both the use of scanf and gets are said to be bad.

    I'ev no arguments with this as you people know what you're talking about, but I can't get fgets() to work...

    Say, I have this code:

    int main()
    {
    char name[20]

    printf("Enter your name >> ");
    fgets(name,20,stdin)
    /* More rubbish..... */
    }

    It will just skip getting the user input, and carry on without it... What am I doing wrong??

  2. #2
    Registered User C_Coder's Avatar
    Join Date
    Oct 2001
    Posts
    522
    That code should work fine, apart from the missing ';' which I guess is just a typo.
    Post some more of your code if you still have trouble.

    [edit]
    when input is skipped over it is usually because there is a newline lurking around in the input buffer. This is why you have read that scanf is bad.
    Try adding this before you call fgets() :
    Code:
    while( getchar() != '\n' );
    This will remove unwanted characters from the input buffer up to the first newline.
    [/edit]

    Last edited by C_Coder; 08-18-2002 at 02:50 PM.
    All spelling mistakes, syntatical errors and stupid comments are intentional.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > What am I doing wrong??
    Almost certainly using scanf() before using fgets()

    This is one of the reasons why scanf() is bad, it leaves the input stream in a terrible mess.

    The short term fix is to put this between calls to scanf and calls to fgets

    Code:
    while ( getchar() != '\n' );  /* tidy up scanf() mess */
    Long term, always use fgets() for reading input, then use sscanf() if appropriate

  4. #4
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >>else while( getchar() != 0xa );
    Just to be picky, how do you know that 0xa is a newline character? And no, the answer isn't "because the ASCII chart says so".

    To be portable, you should use \n
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  5. #5
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >If it didn't, there's garbage left
    Be careful, that 'garbage' may be valid input that was one of those cases where the string was longer than the buffer. If you throw it away then the rest of the program could break.

    >To be portable, you should use \n
    But 0xA looks more computery. We can't have non-programmers being able to figure out our code now, can we? And you're not being picky, portability is very important, if the standard gives us something that can go from ASCII to EBCDIC to whatever without change then by all means we should use it.

    [edit]
    To be more portable, you should take files into consideration:
    Code:
    while ( ( ch = fgetc ( filep ) ) != EOF && ch != '\n' );
    [/edit]

    -Prelude
    Last edited by Prelude; 08-18-2002 at 03:57 PM.
    My best code is written with the delete key.

  6. #6
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >>while ( ( ch = fgetc ( filep ) ) != EOF && ch != '\n' );

    ...except that EOF is no longer reliable since file formats these days are littered with the signature EOF value -1. The most reliable way is to use the while(!feof(file_pointer)) construct with files since it relies on the information the operating system places in the FILE structure. fgets() works too since it returns NULL when the end of file condition is reached.
    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;
    }

  7. #7
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Originally posted by Sebastiani
    >>while ( ( ch = fgetc ( filep ) ) != EOF && ch != '\n' );

    ...except that EOF is no longer reliable since file formats these days are littered with the signature EOF value -1. The most reliable way is to use the while(!feof(file_pointer)) construct with files since it relies on the information the operating system places in the FILE structure. fgets() works too since it returns NULL when the end of file condition is reached.
    Seb, you're way off base here.

    EOF is an int, not a char. fgetc() will return EOF at the end of the file (or upon error) which will equate to a -1 int, not a -1 char. There's a big difference.

    Here's some code to prove it, with comments at the end to show the results.
    Code:
    #include <stdio.h>
    
    int main(void)
    {
        FILE *fp;
        int c;
        
        if ((fp = fopen("file.bin", "rb")) == NULL)
            return 1;
        
        while ((c = fgetc(fp)) != EOF)
            printf ("c is %x\n", c);
        printf ("\nEOF: %x", c);
        fclose(fp);
        return(0);
    }
    
    /*
    The input file is one byte long, and that byte has value 0xff.
    The output from this program is:
    c is ff   <- This is "real data"
    
    EOF: ffffffff   <-- This is the value of c now it has been assigned EOF
    >while(!feof(file_pointer))
    Definately not the way to go. This can lead to double reads at the end of the file.

    Some compilers don't set the EOF flag in the file stream until they have performed a read and the OS has replied with EOF instead of data.

    Other compilers will work differently, and will set EOF when doing the final read that gets data. In this case, the feof() loop would work correctly.

    >>fgets() works too since it returns NULL when the end of file condition is reached.
    Agreed.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > except that EOF is no longer reliable since file formats these days are littered with the signature EOF value
    EOF is not a value in a file, its a status returned by a file reading function, which is distinct from all the possible char values which can be read from a file.

    > while(!feof(file_pointer)) construct
    Which has been shown to be wrong on so many occasions, like here

    > Some compilers don't set the EOF flag in the file stream until they have performed a read and the OS has replied with EOF instead of data.

    If it were to do otherwise, I think it would not be an ANSI-C compiler.

  9. #9
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    i thought EOF could be defined by the standard library as any int value which cannot fit into a single char, not nessecarily -1?
    hello, internet!

  10. #10
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    i thought EOF could be defined by the standard library as any int value which cannot fit into a single char, not nessecarily -1?
    Yes, you are correct, but it is typically -1, hence I used it in my example. The same principles still apply.

    [EDIT] From one of the standards docs:
    EOF is traditionally -1, but may be any negative integer, and hence distinguishable from any valid character code.
    Last edited by Hammer; 08-18-2002 at 06:08 PM.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  11. #11
    Registered User
    Join Date
    Jan 2002
    Location
    Vancouver
    Posts
    2,212
    I always use something like this (may not work):
    Code:
    #include <stdio.h>
    
    ...
    
    int getstuffed(char *cpntr, int maxlen)
    {
     fgets(cpntr, maxlen, stdin);   // whoops,  corrected.
     for(int i = 0;cpntr[i];i++)
      if(cpntr[i] == '\n') cpntr[i] == '\0';
     return 0;
    }
    
    int main(void)
    {
     char coolstring[256];
     getstuffed(coolstring,256);
     printf("%s",coolstring);
     return 0;
    }
    Last edited by Brian; 08-18-2002 at 07:19 PM.

  12. #12
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >>>I always use something like this (may not work):
    You can't use that, the function name is way too funny

    Besides, there's a library function that'll do it for you:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char c[] = "This is a line\n";
        printf (">%s<\n", c);
        c[strcspn(c, "\n")] = '\0';
        printf (">%s<\n", c);
        return(0);
    }
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  13. #13
    Registered User
    Join Date
    Jan 2002
    Location
    Vancouver
    Posts
    2,212


    I haven't been here for a while. But isn't this addressed in the FAQ?

  14. #14
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Originally posted by Brian


    I haven't been here for a while. But isn't this addressed in the FAQ?
    Probably, but they're top secret, and no-one is allowed to read them.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  15. #15
    Cody
    Guest

    Re: fgets

    Originally posted by New_to_C
    Hi,

    I've been reading through the forums and noticed that both the use of scanf and gets are said to be bad.

    I'ev no arguments with this as you people know what you're talking about, but I can't get fgets() to work...

    Say, I have this code:

    int main()
    {
    char name[20]

    printf("Enter your name >> ");
    fgets(name,20,stdin)
    /* More rubbish..... */
    }

    It will just skip getting the user input, and carry on without it... What am I doing wrong??

    Hello, I didn't read all the posts above, but your code should look like this:

    Code:
    #include <stdio.h>
    
    int main()
    {
    char name[20]
    
    printf("Enter your name >> ");
    fgets(name, 20, stdin);
    sscanf(name, "%c", &name);
    /* More rubbish..... */
    }
    Correct me if I'm wrong, but you forgot the ; after the fgets line, you forgot #include <stdio.h>, and you forgot the sscanf for input.

    Hope that helps.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fgets not working after fgetc
    By 1978Corvette in forum C Programming
    Replies: 3
    Last Post: 01-22-2006, 06:33 PM
  2. problem with fgets
    By learninC in forum C Programming
    Replies: 3
    Last Post: 05-19-2005, 08:10 AM
  3. problem with fgets
    By Smoot in forum C Programming
    Replies: 4
    Last Post: 12-07-2003, 03:35 AM
  4. fgets crashing my program
    By EvBladeRunnervE in forum C++ Programming
    Replies: 7
    Last Post: 08-11-2003, 12:08 PM
  5. help with fgets
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 10-17-2001, 08:18 PM