The most effective way that I've ever found:

char str[256]; /* Actually, this is sometimes too small. But caveat emptor. */

fgets(str, 256, f);

This NUL terminates the string as a free gift, and stops before the array ends, guaranteed, which makes it much harder to blow the buffer. It's especially handy for reading user input, and it makes it far more difficult for the user to overflow your buffer and cause a segfault (or local variant). It does store the newline as well, so you might want to do something like:

str[strlen(str)-1] = 0;

As long as you got the string from fgets(), and the file hasn't hit EOF (you do check that, right?), there's at least one character in the array, so this is safe. Note that fgets() promises to 0-terminate the string for you, come hell or high water, so the strlen() will be okay.

If the user pounded on the keys like a wild monkey before hitting enter, most of their input will not make it into the fgets(), and will be waiting around for the next time you try to read. But what you got will be safe, so the constant buffer is okay. (Well, as I said, it may be smaller than you want for your code, but you can always change the size if you recompile.)


As an aside to cbond's, er, Furious George's comment, recursion is quite expensive, especially if you're getting a truly monstrous stack as a free gift. If getline() isn't on your target system, or if your target has a pathetically small stack (which could then cause you to blow your stack) you might run into problems... But "to each their own," said the woman as she kissed the cow.

Update: To each their own. Since I've never been on a system with getline() and I have been on systems with tiny stacks, I suppose there is some paranoia going on here. Use my solution, use Furious George's solution, but please, use something besides gets().

Oh, and when I say tiny stacks, they were big enough for one buffer of 256 bytes - but not a series of stack frames and 16 byte buffers and so on. Yes, I do sometimes wake up twitching, why do you ask?

The only problem when dealing with fgets() is that you have to use a buffer with a static length. Fuck me in the goat ass! This is extremely problematic when dealing with user input, and should be avoided.

More convenient is the non-standard getline() interface, which allows you to read strings of unlimited length and usually guarantees only one malloc() call. Apparently, it does this by allocating small chunks of stack each time getline() is called and using them to store pieces of the string, calling itself recursively if it needs more space. When the end of the line/file is reached, it allocates a buffer and unwinds. When each instance of getline() is returned to, it prepends its buffer to the malloc()'d space until it has fully unwound and you're left with your string. Clever, no?

Anyway, the moral of the story is to be clever about your fgets() use, or use getline().


Coffee: Your implementation uses the stack to store the string as well. It's silly to worry about the few bytes that the getline recursion would cost (for return address, etc.). That stack space is recovered as soon as the stack frame is dismantled and the string is put into malloced memory. Besides, I'd rather risk running out of stack space than arbitrarily truncating input with fgets.

Log in or register to write something here or to contact authors.