Thread: Difference between scanf and fgets

  1. #1
    Registered User
    Join Date
    Sep 2013
    Posts
    82

    Difference between scanf and fgets

    Hey guys,
    Whats the difference between scanf and fgets? Because I am having problem with the code below:

    Code:
    #include<stdio.h>
    
    main()
    {
          char string[200],name[200];
          FILE *fptr = fopen("test string","rb");
          
          printf("Enter your name: ");
          
          /*When I use fgets below the code works correctly, but  it doesn't works correctly when I use scanf*/
          scanf ("%*[^\n]",name);
          
          while(fgets(string,sizeof(string),fptr) != NULL)
          {   /*I also tried subtracting the new line character*/
                if (strcmp(name,string) == 0)
                    printf("correct\n");
                else
                    printf("Wrong\n");
          }
          
          system("pause");
    }

  2. #2
    11DE784A SirPrattlepod's Avatar
    Join Date
    Aug 2013
    Posts
    485
    Code:
    scanf ("%*[^\n]",name);
    Are you sure that '*' does what you think it does? What value does scanf() return?

  3. #3
    Registered User
    Join Date
    Sep 2013
    Posts
    82
    Quote Originally Posted by SirPrattlepod View Post
    Code:
    scanf ("%*[^\n]",name);
    Are you sure that '*' does what you think it does? What value does scanf() return?
    I think '*' empties whatever was there before in 'name', but without the '*' code works.

  4. #4
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    * - makes scanf skip all that matches current format and the result is not written to any variable
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  5. #5
    Registered User
    Join Date
    Sep 2013
    Posts
    82
    Quote Originally Posted by vart View Post
    * - makes scanf skip all that matches current format and the result is not written to any variable
    Hmm, then I think its better to use fgets whenever dealing with files. One more question; if I use two fgets with one variable, will I get any problems?

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    The difference between fscanf() and fgets() is that fscanf() performs formatted input (tries to read whatever the format string specifies, and reports if it can't). fgets() simply reads lines of text.

    fgets() also leaves the trailing '\n' on the string it reads (unless it stops because the buffer is full). Your fscanf() call reads data until it encounters '\n', but leaves the '\n' in the stream - where it will be picked up immediately by the next fgets() call.

    Also, since you have used an asterix in the format, fscanf() is discarding data, rather than reading characters into the array name.

    The general rule of thumb, however, is: don't mix the two on one stream. The reason is that each stop reading for different reasons so, if followed by the other, the results cn be surprising.

    There is no problem with calling fgets() twice with the same arguments. Just bear in mind, however, that the characters read by the first call will be overwritten by those read by the second call. So, if you want to use the characters read by the first call, you need to make use of them (or copy them elsewhere) before the second call.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  7. #7
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    Code:
    scanf ("%*[^\n]",name);
    Are you sure this works? At the end of the statment, name should hold nothing? Is that intended. What you need is this perhaps?

    Code:
    scanf( "%[^\n]", name);
    This is approch is commanly used to make sure the input buffer is left clean after reading the data of the user.

    ssharish
    Life is like riding a bicycle. To keep your balance you must keep moving - Einstein

  8. #8
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    You might want to consider the approach where you use fgets to read in a line at a time into a buffer and then use sscanf(buf, ...) to read in the formatted input into variables. This approach seems to make things simpler to organize in many cases.

  9. #9
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Also, fscanf makes it harder to avoid buffer overflows. With fgets, it's easy:
    Code:
    #define NAME_LEN 25
    char name[NAME_LEN];
    fgets(name, sizeof(name), stdin);  // whatever I change NAME_LEN to, the sizeof parameter ensures it wont overflow
    With scanf, you can specify a maximum size of the char array you're reading into, but it needs to be hard-coded in the string:
    Code:
    #define NAME_LEN 25
    char name[NAME_LEN];
    scanf("%25[^\n]", name);  // now, if I change NAME_LEN, I have to remember to change the scanf separately, or risk overflow
    There is no easy way around it. You can get around that with some macro string quoting tricks or by sprintf'ing your format string into another string first.

    That, along with some of the other reasons mentioned, are why I prefer to use fgets to read a line of input, and strtol/strtod family of functions, or sscanf (the extra 's' is for scanning a string), to parse out any non-string data. strtol/strtod are much more powerful and provide better error handling than sscanf for reading in numbers.
    Quote Originally Posted by grumpy View Post
    ...used an asterix...
    Been reading many French comics lately, grumpy? (emphasis mine)

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by anduril462 View Post
    With scanf, you can specify a maximum size of the char array you're reading into, but it needs to be hard-coded in the string:
    Code:
    #define NAME_LEN 25
    char name[NAME_LEN];
    scanf("%25[^\n]", name);  // now, if I change NAME_LEN, I have to remember to change the scanf separately, or risk overflow
    There is no easy way around it. You can get around that with some macro string quoting tricks or by sprintf'ing your format string into another string first.
    It is also possible to use a loop with the %c format as well.

    I wouldn't describe it as difficult, but I agree it's not as easy as it could be.

    I do agree with you on preferring fgets() to read and other functions to scan though.

    Quote Originally Posted by anduril462 View Post
    Been reading many French comics lately, grumpy? (emphasis mine)
    Haven't read comics about the indomitable Gauls in years .....
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  11. #11
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    But doesn't the following have possibilities of accessing your array out of bounds?
    Code:
    #define NAME_LEN 25
    char name[NAME_LEN];
    scanf("%25[^\n]", name);
    Doesn't scanf() read up to 25 characters, then append the end of string character afterwords? Unlike fgets() I believe you need to reserve space for the end of string character. So in this case the scanf should be "%24...", not 25.

    Jim

  12. #12
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by jimblumberg View Post
    But doesn't the following have possibilities of accessing your array out of bounds?
    Code:
    #define NAME_LEN 25
    char name[NAME_LEN];
    scanf("%25[^\n]", name);
    Doesn't scanf() read up to 25 characters, then append the end of string character afterwords? Unlike fgets() I believe you need to reserve space for the end of string character. So in this case the scanf should be "%24...", not 25.

    Jim
    Ahh, yes...you're right. That's what I get for not double checking the documentation. And that's one more reason to use fgets!

  13. #13
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    With scanf we also can work out something so that limit will adjust automatically as soon as buffer length is adjusted

    Code:
    #include <stdio.h>
    #include <string.h>
    
    #define xSTR_VALUE(arg) STR_VALUE(arg)
    #define STR_VALUE(arg)  #arg
    #define MAX_LEN 5
    #define STR_LEN xSTR_VALUE(MAX_LEN)
    
    int main( void )
    {
        char buf[MAX_LEN+1];
        int res;
        printf ( "Enter string:\n") ;
        res = scanf("%" STR_LEN "s" ,buf); 
        if(res == 1)
            printf ( "Scanned %d bytes\n", (int)strlen(buf) ) ;
        else
            printf ( "Scanf failed\n") ;
    
        return 0;
    }
    Of course it is not as nice looking as straight number or passing sizeof(buf) into fgets...
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  14. #14
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    No not nice at all.

    What happens when you have different length strings?

    A different macro for each of these different sizes?

    Jim

  15. #15
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    >What happens when you have different length strings?
    That indeed looks a bit messy. But to answer the question, isn't it the case with the fgets too, that you need to set the buffer size limit. In his case you set the MAX_LEN which was would be limit of the buffer everywhere. If you have a different length string, you declare string with bigger BUFFER size. Which I believe is same with the scanf anf fgets.

    ssharish
    Life is like riding a bicycle. To keep your balance you must keep moving - Einstein

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fgets and scanf
    By kkk in forum C Programming
    Replies: 10
    Last Post: 07-29-2011, 10:11 AM
  2. difference between gets and fgets here???
    By n3cr0_l0rd in forum C Programming
    Replies: 4
    Last Post: 03-18-2009, 02:37 PM
  3. scanf vs fgets?
    By Matus in forum C Programming
    Replies: 65
    Last Post: 11-17-2008, 04:02 PM
  4. what happens after 'fgets' and 'scanf'
    By the bassinvader in forum C Programming
    Replies: 4
    Last Post: 07-30-2006, 03:04 PM
  5. Scanf->Fgets
    By 00Sven in forum C Programming
    Replies: 2
    Last Post: 04-21-2006, 02:39 PM

Tags for this Thread