I guess most people know but I suppose it bears repeating that scanf() should be avoided in almost all cases. The scanf() function is
"notoriously ill behaved", and there are far better ways to deal with user input. Especially the way you are using it currently, you might as well be using gets(). Now, while using these methods in
educational programs, or throw-away code that you intend to use as an experiment is generally okay, you should take in interactive user input by different means, and preferably just altogether avoid taking in user input VIA interactive input. You will notice that many of the released and frequently used by users command line programs take in input using command line arguments and/or files, which happens to be far safer (and the way I recommend you deal with input whenever possible).
Consider the following three echoing programs, the first takes in interactive input through scanf(), the second takes in input using a function that is much safer for user input, and the third uses command line input:
#include <stdio.h>
int main(void)
{
char buffer[40];
scanf("%[^\n]", buffer);
printf("%s", buffer);
return 0;
}Simple, yes, but entirely unsafe. In the case of getting more than 40 characters your program will overrun the buffer, and will lead to undefined behavior (the worst kind of behavior).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Requires C99 and to include stdio.h, stdlib.h, and string.h
size_t get_input(char **retval)
{
// RETVAL IS ASSUMED NULL!!!
size_t curlen = 0;
char buffer[40];
while (fgets(buffer, sizeof buffer, stdin))
{
size_t slen = strlen(buffer) + 1;
if (!buffer) break;
curlen += slen;
char *temp = realloc(retval, curlen);
if (temp)
{
*retval = temp;
}
else
{
free(*retval);
*retval = NULL
return 0; // Indicate failure.
}
strncat(*retval, buffer, slen);
if (buffer[slen - 2] == '\n') break;
}
return curlen;
}
int main(void)
{
char *str = NULL;
if (get_input(&str)) // You should check the return value of get_input
// in case it is zero.
{
printf("%s", str);
}
free(str);
}A lot better. It doesn't make many assumptions (except that it
is, in fact, interactive input, and not piped in input), but like I just said, there's the issue of piped in file input, which
may or may not cut off the piped in file at an arbitrary point. Notice that it only checks if the last character at the end of the buffer
happens to be an end-line character, which if that happens to occur while reading in piped input then it'll just leave the rest in the input buffer and carry on. This isn't to say that it's no better than scanf(), just that it's got it's own problems as well. If you want interactive input, use something like that.
#include <stdio.h>
int main(int argc, char **argv)
{
if (argc > 1)
{
printf("%s\n", argv[1]);
}
return 0;
}This is also very simple, and most importantly,
entirely safe. Using input in this manner, in my opinion, is how new C programmers
should be taught to take in input, since it's extremely simple to figure out, simple to utilize once you understand it, and most importantly, won't cause problems for them in the future if they use it.
Yeah, just had to say that.