/* Name: util.c Purpose: Implementation of utility functions Author: Bill Slough */ #include #include #include "util.h" #define INITIAL_CAPACITY 10 /* size of the first memory allocation */ /* 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 *read_line(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); s[size] = '\0'; 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!\n"); 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!\n"); exit(EXIT_FAILURE); } else return p; } /* read all lines from a given input file */ char **read_lines(FILE *fp) { char *line; char **lines; int size; int capacity; capacity = INITIAL_CAPACITY; /* allocate an initial amount for the lines */ lines = (char **) safe_malloc(INITIAL_CAPACITY*sizeof(char *)); size = 0; while ((line = read_line(fp)) != NULL) { lines[size++] = line; if (size == capacity) { /* last slot used up: allocate more space */ capacity *= 2; lines = safe_realloc(lines, capacity*sizeof(char *)); } } /* trim to the correct size and terminate with NULL */ lines = safe_realloc(lines, (size + 1)*sizeof(char *)); lines[size] = NULL; return lines; } /* display all lines in a NULL-terminated array of strings */ void display_lines(char *p[ ]) { int i; i = 0; while (p[i] != NULL) { printf("%s\n", p[i]); i++; } } /* display all lines in a NULL-terminated array of strings in reverse order */ void display_lines_in_reverse(char *p[ ]) { int i; i = count_lines(p) - 1; while (i >= 0) { printf("%s\n", p[i]); i--; } } /* counts the number of lines stored in a NULL-terminated array of strings */ int count_lines(char *p[ ]) { int i; i = 0; while (p[i] != NULL) { i++; } return i; }