/* Name: readfile5.c Purpose: Similar to readfile4.c, with a re-designed and improved readLine Author: Bill Slough */ #include #include #include #define FILE_NAME "words" /* name of the input file */ #define INITIAL_CAPACITY 10 /* size of first string allocation */ char *readLine(FILE *fp); void *safe_malloc(size_t size); void *safe_realloc(void *ptr, size_t size); int main(void) { FILE *fp; /* file pointer for an input stream */ int lineCount; /* number of lines processed */ char *line; /* string to hold one line of input */ /* Try to open the input stream for reading */ fp = fopen(FILE_NAME, "r"); if (fp == NULL) { fprintf(stderr, "Error: can't open %s for reading.\n", FILE_NAME); exit(EXIT_FAILURE); } /* Process the file, line by line */ lineCount = 0; while ((line = readLine(fp)) != NULL) { printf("Current line = \"%s\"\n", line); lineCount++; free(line); /* release the space held by line */ } printf("Lines processed = %d\n", lineCount); /* Close the stream */ fclose(fp); return 0; } /* Read and store one line of input from a given input file. Return NULL if stream is at eof or there was a read error; otherwise returns a pointer to a null-terminated string of the correct size. The terminating newline character marking the end of the line is not stored in the resulting string. */ char *readLine(FILE *fp) { int capacity; /* maximum number of characters in the string */ int size; /* number of characters stored in the string */ int ch; /* most recent character read from the file */ int count; /* number of characters read from the file */ char *s; /* the string */ /* allocate space sufficient for "small" strings */ capacity = INITIAL_CAPACITY; s = safe_malloc(capacity); size = 0; /* so far, no characters have been stored */ count = 0; /* and no characters have been read from the current line */ while (((ch = getc(fp)) != '\n') && (ch != EOF)) { count++; s[size++] = ch; if (size == capacity) { /* last available slot was used; get more space! */ capacity *= 2; s = safe_realloc(s, capacity); } } if ((count == 0) && (ch == EOF)) { /* no characters read: at eof */ free(s); /* release space held for string */ return NULL; } /* Properly terminate the string and trim to the proper size */ s = safe_realloc(s, size + 1); /* +1 for the terminating \0 character */ s[size] = '\0'; printf("readLine: %d bytes allocated.\t", size + 1); /* REMOVE later... */ return s; } /* safely allocate a block of storage, aborting program if not possible */ void *safe_malloc(size_t size) { void *p; p = malloc(size); if (p == NULL) { fprintf(stderr, "error - out of space!"); exit(EXIT_FAILURE); } else return p; } /* safely reallocate a block of storage, aborting program if not possible */ void *safe_realloc(void *ptr, size_t size) { void *p; p = realloc(ptr, size); if (p == NULL) { fprintf(stderr, "error - out of space!"); exit(EXIT_FAILURE); } else return p; }