User Name Password Register
DaniWeb IT Discussion Community
All
What is DaniWeb IT Discussion Community?
You're currently browsing the C section within the Software Development category of DaniWeb, a massive community of 456,547 software developers, web developers, Internet marketers, and tech gurus who are all enthusiastic about making contacts, networking, and learning from each other. In fact, there are 3,353 IT professionals currently interacting right now! Registration is free, only takes a minute and lets you enjoy all of the interactive features of the site.
Please support our C advertiser: Programming Forums
Views: 7017 | Replies: 6
Reply
Join Date: Jul 2007
Posts: 14
Reputation: #include_rose is an unknown quantity at this point 
Rep Power: 2
Solved Threads: 0
#include_rose #include_rose is offline Offline
Newbie Poster

Scanf vs fgets

  #1  
Oct 17th, 2007
I'm having some trouble understanding the advantages and disadvantages of using scanf over fgets.

When we have allocated memory using an array for eg, it is not wise to use scanf since buffer overflow can occur. But in what way does fgets prevent that from happening?

Also, if you are allocating memory dynamically then is it okay to be using scanf?

I have this code:
typedef struct node
{
  int data;
  struct node *next;
}NODE;
static NODE *find(NODE *element);

void main()
{
  NODE *element,*head,*a;
  element = (NODE *) malloc (sizeof(NODE));
  element->next=head;
  printf("Enter the data\n");
  scanf("%d",&element->data);
  head=element;
  a =find(element);
  if(a)
    {
      printf("Element %d was found \n",element->data);
    }
  else
    {
      printf("Element %d was not found\n",element->data);

    }
  free(head);
}

NODE * find(NODE *element)
{
  while(element)
    {
      if(element->data==50)
        {
          return element;
        }
      else
        {
          return 0;
        }
      element=element->next;
    }

}

If I were to use fgets instead of scanf here, how would I incorporate it?

Thanks.
AddThis Social Bookmark Button
Reply With Quote  
Join Date: Sep 2004
Posts: 6,515
Reputation: Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of 
Rep Power: 31
Solved Threads: 489
Super Moderator
Narue's Avatar
Narue Narue is offline Offline
Expert Meanie

Re: Scanf vs fgets

  #2  
Oct 17th, 2007
>I'm having some trouble understanding the advantages
>and disadvantages of using scanf over fgets.
I imagine because the comparison is difficult. scanf and fgets do different things. scanf is designed for formatted input and fgets is designed for unformatted input.

>But in what way does fgets prevent that from happening?
Assuming you use it correctly, the second argument of fgets provides a limit on the number of characters that are read:
char buffer[10];

if ( fgets ( buffer, 10, stdin ) != NULL )
  fputs ( buffer, stdin );
It doesn't matter how many characters you actually type, only up to 9 will be written to buffer, and the last spot will be '\0'. The same can't be said about a naive use of scanf:
char buffer[10];

if ( scanf ( "%s", buffer ) == 1 )
  puts ( buffer );
You can type 5000 characters, and as long as there's no whitespace scanf will read 5000 characters. The big question is, where does it write them all if buffer can only hold 10?

That's a naive use of scanf, and if you find yourself doing that, you shouldn't be using scanf at all, because you simply don't understand it well enough to use it safely. You can plug the buffer overflow hole with scanf like this:
char buffer[10];

if ( scanf ( "%9s", buffer ) == 1 )
  puts ( buffer );
By adding a maximum field width, you're telling scanf to read up to that many characters, and no more. So if you type 5000 character, scanf will only read the first 9, and tack a '\0' onto the last spot.

>Also, if you are allocating memory dynamically then is it okay to be using scanf?
How you get the buffer is irrelevant.

>If I were to use fgets instead of scanf here, how would I incorporate it?
The problem is that scanf reads formatted input and fgets only reads strings. scanf will take "12345\n" and with the %d specifier, convert it into the integer 12345. fgets will just give you "12345\n". To get the integer value with fgets, you need another conversion step. Ironically, sscanf is a good choice for that. So this:
scanf("%d",&element->data);
becomes this:
{
  char line[BUFSIZ];

  if ( fgets ( line, sizeof line, stdin ) == NULL
    || sscanf ( line, "%d", &element->data ) != 1 )
  {
    /* Handle bad input */
  }
}
Other methods include the horrible atoi function, the much better strtol, and your own conversion routine. Using scanf for reading anything but string data is actually not that bad. You may have some minor issues handling failure, but most of the conversion specifiers aren't glaringly unsafe like %s.
Last edited by Narue : Oct 17th, 2007 at 5:14 pm.
I'm here to prove you wrong.
Reply With Quote  
Join Date: Jul 2007
Posts: 14
Reputation: #include_rose is an unknown quantity at this point 
Rep Power: 2
Solved Threads: 0
#include_rose #include_rose is offline Offline
Newbie Poster

Re: Scanf vs fgets

  #3  
Oct 17th, 2007
Thanks a lot. That cleared my doubts. :-)
Reply With Quote  
Join Date: Jul 2007
Posts: 14
Reputation: #include_rose is an unknown quantity at this point 
Rep Power: 2
Solved Threads: 0
#include_rose #include_rose is offline Offline
Newbie Poster

Re: Scanf vs fgets

  #4  
Oct 17th, 2007
Ironically, sscanf is a good choice for that. So this:
scanf("%d",&element->data);
becomes this:
{
  char line[BUFSIZ];

  if ( fgets ( line, sizeof line, stdin ) == NULL
    || sscanf ( line, "%d", &element->data ) != 1 )
  {
    /* Handle bad input */
  }
}

I didn't understand this though. How would I use fgets when I want to allocate memory dynamically? Here you are allocating static memory using line[BUFSIZ]; Am i right?
Last edited by #include_rose : Oct 17th, 2007 at 10:52 pm.
Reply With Quote  
Join Date: Dec 2006
Posts: 1,569
Reputation: Aia is a splendid one to behold Aia is a splendid one to behold Aia is a splendid one to behold Aia is a splendid one to behold Aia is a splendid one to behold Aia is a splendid one to behold Aia is a splendid one to behold 
Rep Power: 12
Solved Threads: 114
Aia's Avatar
Aia Aia is offline Offline
Posting Virtuoso

Re: Scanf vs fgets

  #5  
Oct 17th, 2007
Originally Posted by #include_rose View Post
I didn't understand this though. How would I use fgets when I want to allocate memory dynamically? Here you are allocating static memory using line[BUFSIZ]; Am i right?


When you used
 scanf("%d",&element->data);

element->data is the pointer of what is in dynamic memory.

When you use fgets is the same element->data that is in the heap.
line[BUFSIZ] is a local array to temporarily hold the string needed
by sscanf to convert it into an integer.
That line[BUFSIZ] doesn't need to be in dynamic memory.
Last edited by Aia : Oct 17th, 2007 at 11:27 pm.
At the very moment that I find myself in the side of the mayority, I will know that I need to re-think my ideas. ~ In my book.
Reply With Quote  
Join Date: Sep 2004
Posts: 6,515
Reputation: Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of 
Rep Power: 31
Solved Threads: 489
Super Moderator
Narue's Avatar
Narue Narue is offline Offline
Expert Meanie

Re: Scanf vs fgets

  #6  
Oct 18th, 2007
>How would I use fgets when I want to allocate memory dynamically?
Exactly the same way. Did you miss the part where I said that how you get the buffer is irrelevant? If it really bothers you, is this better? It uses memory dynamically.
{
  char *line = malloc ( BUFSIZ );

  if ( line != NULL ) {
    if ( fgets ( line, BUFSIZ, stdin ) == NULL
      || sscanf ( line, "%d", &element->data ) != 1 )
    {
      /* Handle bad input */
    }
  }

  free ( line );
}
I'm here to prove you wrong.
Reply With Quote  
Join Date: Jul 2007
Posts: 14
Reputation: #include_rose is an unknown quantity at this point 
Rep Power: 2
Solved Threads: 0
#include_rose #include_rose is offline Offline
Newbie Poster

Re: Scanf vs fgets

  #7  
Oct 18th, 2007
For some reason now it feels better
Reply With Quote  
Reply

Only community members can participate in forum threads. You must register or log in to contribute.

DaniWeb C Marketplace
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)

 

Thread Tools Display Modes

Similar Threads
Other Threads in the C Forum

All times are GMT -4. The time now is 5:10 am.
Forum system based on vBulletin Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
©2003 - 2008 DaniWeb® LLC