>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.