Two Solutions to Problem 3, page 270 of Perry, John. "Advanced C Programming by Example" Belmont, CA: PWS Publishing, 1998.
The first copies the strings.
The second reuses the pointers in the array passes to it.
| // | |
| // Created by Noah Cardoza on 2019-03-21. | |
| // | |
| #include <unistd.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <stdio.h> | |
| #include <assert.h> | |
| /** | |
| * verifies that an array of files exists | |
| * @param filenames a double array of | |
| * pointers to c-strings | |
| * @return a subset of filenames only | |
| * including files that exist | |
| */ | |
| char **checkDelete(char **filenames) { | |
| // a pointer used to traverse filenames | |
| char *filename = NULL; | |
| // contains all the files that exist | |
| char **existing_files = NULL; | |
| // the number of files found | |
| int found = 0; | |
| // in the case where there are no valid | |
| // filenames we need to still return a | |
| // NULL terminated char* array | |
| existing_files = (char**)malloc(sizeof(char*)); | |
| assert(existing_files); // assure the malloc was successful | |
| *existing_files = NULL; | |
| while ((filename = *filenames)){ | |
| // returns -1 if the filename is not "ok" aka not readable/writable/non-existent | |
| if(access(filename, F_OK) != -1) { | |
| // add 2 because we need a null terminator | |
| existing_files = (char**)realloc(existing_files, (found + 2) * sizeof(char*)); | |
| assert(existing_files); // assure the realloc was successful | |
| // reuses the pointers passes to it | |
| existing_files[found - 1] = filename; | |
| existing_files[found + 1] = NULL; | |
| found += 1; | |
| } | |
| filenames++; | |
| } | |
| return existing_files; | |
| } | |
| int main(void){ | |
| char **ptr, **head; | |
| char *files[80] = { | |
| "main.c", | |
| "test_file/that/does/not.exist", | |
| "ec03", | |
| "ec03/EC_Tables.c", | |
| "hw04", | |
| "non.existent", | |
| NULL | |
| }; | |
| head = ptr = checkDelete(files); | |
| while (*ptr) { | |
| printf("%s\n", *ptr); | |
| ptr++; | |
| } | |
| free(head); | |
| return 0; | |
| } | |
| /* Output: | |
| * main.c | |
| * ec03 | |
| * ec03/EC_Tables.c | |
| * hw04 | |
| */ |
/
main.c
ec03/
EC_Tables.c
INPUT.TXT
hw04/
| // | |
| // Created by Noah Cardoza on 2019-03-21. | |
| // St | |
| // | |
| #include <unistd.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <stdio.h> | |
| #include <assert.h> | |
| /** | |
| * verifies that an array of files exists | |
| * @param filenames a double array of | |
| * pointers to c-strings | |
| * @return a subset of filenames only | |
| * including files that exist | |
| */ | |
| char **checkDelete(char **filenames) { | |
| // a pointer used to traverse filenames | |
| char *filename = NULL; | |
| // contains all the files that exist | |
| char **existing_files = NULL; | |
| // the number of files found | |
| int found = 0; | |
| // in the case where there are no valid | |
| // filenames we need to still return a | |
| // NULL terminated char* array | |
| existing_files = (char**)malloc(sizeof(char*)); | |
| assert(existing_files); // assure the malloc was successful | |
| *existing_files = NULL; | |
| while ((filename = *filenames)){ | |
| // returns -1 if the filename is not "ok" aka not readable/writable/non-existent | |
| if(access(filename, F_OK) != -1) { | |
| // add 2 because we need a null terminator | |
| existing_files = (char**)realloc(existing_files, (found + 2) * sizeof(char*)); | |
| assert(existing_files); // assure the realloc was successful | |
| existing_files[found] = (char*)malloc((strlen(filename) + 1) * sizeof(char)); | |
| assert(existing_files[found]); // assure the malloc was successful | |
| // copy the string so it can be safely mutated later | |
| strcpy(existing_files[found], filename); | |
| existing_files[found + 1] = NULL; | |
| found += 1; | |
| } | |
| filenames++; | |
| } | |
| return existing_files; | |
| } | |
| int main(void){ | |
| char **ptr, **head; | |
| char *files[80] = { | |
| "main.c", | |
| "test_file/that/does/not.exist", | |
| "ec03", | |
| "ec03/EC_Tables.c", | |
| "hw04", | |
| "non.existent", | |
| NULL | |
| }; | |
| head = ptr = checkDelete(files); | |
| while (*ptr) { | |
| printf("%s\n", *ptr); | |
| free(*ptr); | |
| ptr++; | |
| } | |
| free(head); | |
| return 0; | |
| } | |
| /* Output: | |
| * main.c | |
| * ec03 | |
| * ec03/EC_Tables.c | |
| * hw04 | |
| */ |