To read entire lines with a recent C library on POSIX systems, you should use getline(3). It allocates (and reallocates) the buffer holding the line as needed. See the example on the man page.
If you have a non-POSIX system without getline
you might use fgets(3) but then you have to take the pain to allocate the line itself, test that you did not read a full newline terminated line, and repeat. Then you need to pre-allocate some line buffer (using e.g. malloc
) before calling fgets
(and you might realloc
it if a line does not fit and call fgets
again). Something like:
//// UNTESTED CODE
size_t linsiz=64;
char* linbuf= malloc(linsiz);
if (!linbuf) { perror("malloc"); exit(EXIT_FAILURE); };
memset(linbuf, 0, sizeof(linbuf));
bool gotentireline= false;
char* linptr= linbuf;
do {
if (!fgets(linptr, linbuf+linsiz-linptr-1, stdin))
break;
if (strchr(linptr, '\n'))
gotentireline= true;
else {
size_t newlinsiz= 3*linsiz/2+16;
char* newlinbuf= malloc(newlinsiz);
int oldlen= strlen(linbuf);
if (!newlinbuf) { perror("malloc"); exit(EXIT_FAILURE); };
memset (newlinbuf, 0, newlinsiz); // might be not needed
strncpy(newlinbuf, linbuf, linsiz);
free (linbuf);
linbuf= newlinbuf;
linsiz= newlinsiz;
linptr= newlinbuf+oldlen;
);
} while(!gotentireline);
/// here, use the linbuf, and free it later
A general rule would be to always initialize pointers (e.g. declare char *line=NULL;
in your case), and always test for failure of malloc
, calloc
, realloc
). Also, compile with all warnings and debug info (gcc -Wall -Wextra -g
). It could have give a useful warning to you.
BTW, I love to clear every dynamically allocated memory, even when it is not very useful (because the behavior is then more deterministic, making programs easier to debug).
Some systems also have valgrind to help detecting memory leaks, buffer overflows, etc..