/* handling arbitrary length lines on input */ #include #include extern char *getline(FILE *fp); int main() { char *line; while ((line = getline(stdin)) != NULL) { printf(":<%s>:\n",line); free(line); } return 0; } /* Return next line without restrictions on line length and, like fgets(), return NULL if no characters read and there was EOF or read error. Although a line longer than 256 chars cannot come directly from a terminal, very long lines can come via redirection from files. For efficiency, extend line a CHUNK at a time instead of by a single char. */ #define CHUNK 80 char *getline(FILE *fp) { char *line = NULL; /* points to beginning of line */ int len_alloced = 0; /* allocated length excluding \0 terminator */ char *append_loc; /* location for appending next CHUNK of chars */ for (;;) { /* make space for next CHUNK of line and a \0 terminator) */ line = realloc(line, (len_alloced += CHUNK) + 1); if (NULL == line) {fprintf(stderr,"Out of memory."); exit(1)}; append_loc = line + len_alloced - CHUNK; /* After reading two CHUNKs YYYYYY and zzzzzz of size 6 the the line array just before third fgets() would be: YYYYYYzzzzzz******\0 ^ ^ ^ line append_loc line+len_alloced */ /* Read up to CHUNK chars starting at append_loc and \0 terminate */ if (NULL == fgets(append_loc, CHUNK + 1, fp)) { /* Read error or EOF encountered as first char */ if (len_alloced == CHUNK) { /* Nothing was read */ free(line); return NULL; } else return line; /* Had partial line when error or EOF occurred */ } /* if line was not filled to end then reclaim space at end */ if (strlen(append_loc) != CHUNK) return realloc(line, strlen(line) + 1); /* if line is filled to end and is \n terminated */ else if (line[len_alloced - 1] == '\n') return line; /* more of line yet to come - continue loop - rare if CHUNK large */ } }