/* MALLOC DEMO #4 Illustrates: declaring a dynamic array of pointers malloc'ing that pointer in a function use of malloc function on that array use of the free function on that array passing pointers into functions the ** prototype (pointer to a pointer) the *** prototype (pointer to a pointer to a pointer) */ #include #include #include #define INITIAL_CAP 5 #define MAX_WORD_LENGTH 30 void mallocArray(char ***arr, int wordCapacity); /* ptr to ptr to ptr (pointer to array of strings) */ void loadArray(char *inFile, char ***arr, int *wordCount, int *wordCapacity); void printArray(char **arr, int wordCount); void freeArray(char **arr, int wordCount); int main(int argc, char *argv[]) { char **wordArray; /* ptr to ptr (array of strings) */ int wordCount, wordCapacity = INITIAL_CAP; if (argc < 2) { printf("Must enter a text input filename on cmd line.\n"); exit(EXIT_FAILURE); } /* Note that with a dynamically sized array of ponters we need two additional variables to track both the capacity (maxWords) of the array and the current count of elements in use We will dimension the array to some initial value (a constant). That should be a good estimate of the number of words in the file */ loadArray(argv[1], &wordArray, &wordCount, &wordCapacity); printf("Printing wordArray:\n\n"); printArray(wordArray, wordCount); freeArray(wordArray, wordCount); wordArray = NULL; return 0; } /* Takes 2 arg: ptr to a char** ptr and the number of elements to be allocated to that char** pointer */ void mallocArray(char ***array, int wordCapacity) { *array = malloc(wordCapacity * sizeof(char *)); if (!*array) { printf("malloc of array failed\n"); exit(EXIT_FAILURE); } } void loadArray(char *infileName, char ***arr, int *wordCount, int *wordCapacity) { char buffer[MAX_WORD_LENGTH]; FILE *infile; infile = fopen(infileName, "r"); if (!infile) { printf("Can't open %s for input.\n", infileName); exit(EXIT_FAILURE); } mallocArray(arr, *wordCapacity); *wordCount=0; /* DANGER: fscanf of string vulnerable to overflow */ while ((*wordCount < *wordCapacity) && fscanf(infile, "%s", buffer) == 1) { (*arr)[*wordCount] = malloc((strlen(buffer)+1) * sizeof(char)); if ((*arr)[*wordCount] == NULL) /* ALWAYS CHECK FOR NULL AFTER malloc */ { printf("malloc failed: Exiting Program!\n\n"); exit(EXIT_FAILURE); } strcpy((*arr)[*wordCount], buffer); ++(*wordCount); } fclose(infile); } /* Takes 2 args: the name of an array of pointers, and a count of how many pointers have been malloc'd. Prints each string. */ void printArray(char **arr, int wordCount) { int i; for(i = 0; i < wordCount; ++i) printf("wordArray[%d]: %s\n", i, arr[i]); } /* Takes 2 arg: the name of an array of pointers and a count of how many have been malloc'd. Visits each malloc'd pointer in the array and frees the memory allocated to it. Then frees the block of pointers. */ void freeArray(char **arr, int wordCount) { int i; for(i = 0; i < wordCount; ++i) free(arr[i]); /* free the strings hanging off each pointer */ free(arr); /* lastly, free the block of pointers */ }