Accepting lines of input that are arbitrarily long is not something the C standard library was designed for. However, it can be an immensely useful feature to have. I recently came across this problem while rewriting the file input parts of libbitconvert. Here’s my solution, modeled after the C standard library’s fgets:
int dynamic_fgets(char** buf, int* size, FILE* file)
{
char* offset;
int old_size;
if (!fgets(*buf, *size, file)) {
return BCINT_EOF_FOUND;
}
if ((*buf)[strlen(*buf) - 1] == 'n') {
return 0;
}
do {
/* we haven't read the whole line so grow the buffer */
old_size = *size;
*size *= 2;
*buf = realloc(*buf, *size);
if (NULL == *buf) {
return BCERR_OUT_OF_MEMORY;
}
offset = &((*buf)[old_size - 1]);
} while ( fgets(offset, old_size + 1, file)
&& offset[strlen(offset) - 1] != 'n' );
return 0;
}
And here is an example of how to use it:
char* input;
int input_size = 2;
int rc;
input = malloc(input_size);
if (NULL == input) { return BCERR_OUT_OF_MEMORY; }
rc = dynamic_fgets(&input, &input_size, stdin);
if (BCERR_OUT_OF_MEMORY == rc) { return rc; }
/* use input */
free(input);
To show you how dynamic_fgets works, I’ll break into down line by line and then describe some of its features:
Continue reading ‘dynamic_fgets: Reading long input lines in C’