#define _POSIX_C_SOURCE 200809L #include #include #include #include #include // WE STORE OUR CONCORDANCE AS 'AN ARRAY OF STRINGS' // words IS A 'POINTER TO A POINTER TO A CHARACTER' // words STORES THE ADDRESS OF THE BEGINNING OF AN ARRAY OF POINTERS TO chars, // EACH OF WHICH POINTS TO A char (AND ASSUMED TO BE THE START OF A STRING) // c.f. https://i.stack.imgur.com/64Tgw.png char **words = NULL; int nwords = 0; // ITERATE THROUGH OUR CONCORDANCE, PRINTING EACH WORD (ONCE) void print_words(void) { for(int w=0 ; w 0) { word[w] = '\0'; // terminate our word (make it a string) add_word(word); } // SKIP ALL NON-ALPHABETIC CHARACTERS, ENSURE WE DON'T GO PAST END OF STRING while(str[s] != '\0' && !isalpha(str[s])) { ++s; } } } // READ THE INPUT TEXT - WE DON'T CARE HOW THE INPUT WAS PROVIDED void read_input_text(FILE *fp) { char line[BUFSIZ]; // READ THE TEXT INPUT LINE-BY-LINE, UNTIL REACHING END-OF-FILE while(fgets(line, sizeof line, fp) != NULL) { find_words(line); } } int main(int argc, char *argv[]) { // IF PROVIDED WITH A COMMAND-LINE ARGUMENT, ASSUME THAT IT'S A FILENAME if(argc > 1) { FILE *fp = fopen(argv[1], "r"); if(fp == NULL) { printf("Unable to open '%s'\n", argv[1]); exit(EXIT_FAILURE); } read_input_text(fp); fclose(fp); // we opened it, so we close it } // OTHERWISE READ INPUT FROM STANDARD-INPUT STREAM (a pipe or redirected file) else { read_input_text( stdin ); } print_words(); exit(EXIT_SUCCESS); return 0; }