You read a fragment of a line at a time into a buffer of a fixed size, and then copied the contents of that fixed size to a buffer with dynamically allocated and resizable:
#include <string.h> #include <stdio.h> #include <stdlib.h> #define SIZE ... // some reasonable size to handle most cases int getNextLine(FILE *stream, char **line, size_t *lineLength) { char inbuf[SIZE]; int done = 0; int rval = 1; // success *lineLength = 0; /** * If *line is not NULL, it is assumed that it was allocated on a * previous call to getNextLine. Free it and set to NULL. */ if (*line != NULL) { free(*line); *line = NULL; } while(!done) { char *tmp; if (fgets(inbuf, sizeof inbuf, stream)) { /** * Check for newline character. If present, clear it and set the * done flag to true. */ char *newline = strchr(inbuf, '\n'); if (newline != NULL) { *newline = 0; done = 1; } /** * Extend the dynamic buffer by the length of the input string * and copy the input string to it. */ tmp = realloc(*line, *lineLength + strlen(inbuf) + 1); if (tmp) { *line = tmp; (*line)[*lineLength] = 0; strcat(*line, inbuf); *lineLength += strlen(inbuf) + 1; } else { printf("Error allocating or extending buffer\n"); rval = 0; done = 1; } } else { if (feof(stream)) { printf("At end-of-file\n"); rval = EOF; } else { printf("Error during read\n"); rval = 0; } done = 1; } } return rval; } int main(void) { char *line = NULL; // line *MUST* be initialized to NULL size_t lineLength = 0; int status; for (;;) { int status = getNextLine(stdin, &line, &lineLength); if (status == 0 || status == EOF) break; printf("Read %lu characters in line: \"%s\"\n", (unsigned long) lineLength, line); } return 0; }
source share