diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..686040f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "gcc-10 - Build and debug active file", + "type": "cppdbg", + "request": "launch", + "program": "${fileDirname}/${fileBasenameNoExtension}", + "args": ["dataset_1.csv", "poly_1split.txt", "output.txt"], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "C/C++: gcc-10 build active file", + "miDebuggerPath": "/usr/bin/gdb" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..df21863 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,27 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc-10 build active file", + "command": "/usr/bin/gcc-10", + "args": [ + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/Makefile b/Makefile index cda8daa..32c22e8 100755 --- a/Makefile +++ b/Makefile @@ -1,2 +1,2 @@ voronoi1 : voronoi.c - gcc -Wall -Wextra -pedantic -g -o voronoi1 voronoi.c + gcc -Wall -Wextra -Werror -pedantic -g -o voronoi1 voronoi.c diff --git a/voronoi.c b/voronoi.c index a6c9356..c76b593 100755 --- a/voronoi.c +++ b/voronoi.c @@ -12,7 +12,7 @@ #define OPEN_FILE_ERROR "Error: Unable to open file %s\n" #define NUM_FILE_ERROR "Error: Incorrect number of inputs (3 required).\n" -#define MALLOC_ERROR "Error: Cannot allocate memory.\n" +#define MEMORY_ALLOCATION_ERROR "Error: Cannot allocate memory.\n" #define ARGC_CORRECT_LEN 4 #define NUM_CSV_FIELDS 6 @@ -20,20 +20,24 @@ #define MAX_CSV_ENTRY_LEN 512 int main(int argc, char **argv) { - /* Input and output files */ + // /* Input and output files */ FILE *dataset = NULL, *polygonData = NULL, *output = NULL; checkInputArgs(argc, argv, &dataset, &polygonData, &output); /* Stores information about the watchtowers given in dataset file */ - watchtower_t *watchtowers = (watchtower_t *) malloc(sizeof(watchtower_t)); - if (watchtowers == NULL) { - fputs(MALLOC_ERROR, stderr); - exit(EXIT_FAILURE); - } - - readWatchtowers(watchtowers, dataset); + watchtower_t **watchtowers = malloc(sizeof(*watchtowers)); + checkNullPointer(watchtowers); + int numWatchtowers = 0; + watchtowers = readWatchtowers(watchtowers, dataset, &numWatchtowers); /* Cleaning up data */ + for (int i = 0; i < numWatchtowers; i++) { + free(watchtowers[i]->id); + free(watchtowers[i]->manager); + free(watchtowers[i]->postcode); + free(watchtowers[i]); + } + free(watchtowers); fclose(dataset); fclose(polygonData); @@ -68,25 +72,34 @@ void checkInputArgs(int argc, char **argv, FILE **datasetFile, \ } } -/* Reads the CSV file and stores the information in the watchtowers array */ -void readWatchtowers(watchtower_t *watchtowers, FILE* datasetFile) { +/* Reads the CSV file and stores the information in the watchtowers array. + * Returns the number of watchtowers read. + */ +watchtower_t** readWatchtowers(watchtower_t **watchtowers, FILE* datasetFile, \ + int *numWatchtowers) { /* Maximum length of a single CSV line */ - size_t lineBufferSize = MAX_CSV_ENTRY_LEN; + size_t lineBufferSize = MAX_CSV_ENTRY_LEN + 1; /* Stores the current line from the CSV */ char *lineBuffer = (char *) malloc(lineBufferSize * sizeof(char)); - if (lineBuffer == NULL) { - fprintf(stderr, MALLOC_ERROR); - exit(EXIT_FAILURE); - } + checkNullPointer(lineBuffer); - int numWatchtowers = 1; + int maxSizeWatchtowers = 1; /* Discard the header line, then read the rest of the CSV */ getline(&lineBuffer, &lineBufferSize, datasetFile); while (getline(&lineBuffer, &lineBufferSize, datasetFile) > 0) { + /* Check if there enough space in the watchtowers array */ + if (*numWatchtowers == maxSizeWatchtowers) { + maxSizeWatchtowers *= 2; + watchtower_t **temp = realloc(watchtowers, \ + maxSizeWatchtowers * sizeof(*watchtowers)); + checkNullPointer(temp); + watchtowers = temp; + } + /* The current tower being filled in with information */ - watchtower_t *currTower = (watchtower_t *) malloc(sizeof(watchtower_t)); + watchtowers[*numWatchtowers] = malloc(sizeof(*watchtowers[*numWatchtowers])); /* Stores the current CSV field for the current line */ char *token = strtok(lineBuffer, ","); @@ -103,48 +116,50 @@ void readWatchtowers(watchtower_t *watchtowers, FILE* datasetFile) { * watchtower with no space wasted. */ case 0: - currTower->id = (char *) malloc(sizeof(char) * \ - tokenLength + 1); - strcpy(currTower->id, token); - currTower->id[tokenLength] = '\0'; + watchtowers[*numWatchtowers]->id = (char *) malloc( \ + sizeof(char) * tokenLength + 1); + checkNullPointer(watchtowers[*numWatchtowers]->id); + strcpy(watchtowers[*numWatchtowers]->id, token); + watchtowers[*numWatchtowers]->id[tokenLength] = '\0'; break; case 1: - currTower->postcode = (char *) malloc(sizeof(char) * \ - tokenLength + 1); - strcpy(currTower->postcode, token); - currTower->postcode[tokenLength] = '\0'; + watchtowers[*numWatchtowers]->postcode = (char *) malloc( \ + sizeof(char) * tokenLength + 1); + checkNullPointer(watchtowers[*numWatchtowers]->postcode); + strcpy(watchtowers[*numWatchtowers]->postcode, token); + watchtowers[*numWatchtowers]->postcode[tokenLength] = '\0'; break; case 3: - currTower->manager = (char *) malloc(sizeof(char) * \ - tokenLength + 1); - strcpy(currTower->manager, token); - currTower->manager[tokenLength] = '\0'; + watchtowers[*numWatchtowers]->manager = (char *) malloc( \ + sizeof(char) * tokenLength + 1); + checkNullPointer(watchtowers[*numWatchtowers]->manager); + strcpy(watchtowers[*numWatchtowers]->manager, token); + watchtowers[*numWatchtowers]->manager[tokenLength] = '\0'; break; case 2: - currTower->population = strtol(token, NULL, 10); + watchtowers[*numWatchtowers]->population = \ + strtol(token, NULL, 10); break; case 4: - currTower->x = strtod(token, NULL); + watchtowers[*numWatchtowers]->x = strtod(token, NULL); break; case 5: - currTower->y = strtod(token, NULL); + watchtowers[*numWatchtowers]->y = strtod(token, NULL); break; } token = strtok(NULL, ","); } - // printf("ID: %s\nPostcode: %s\nManager: %s\n", \ - // currTower->id, currTower->postcode, currTower->manager); - // printf("Population: %d\nx: %f\ny: %f\n", \ - // currTower->population, currTower->x, currTower->y); - /* Add currTower to the watchtowers array */ - - - /* Clean up currTower before reading next CSV line */ - free(currTower->id); - free(currTower->manager); - free(currTower->postcode); - free(currTower); + *numWatchtowers += 1; } + free(lineBuffer); + return watchtowers; +} + +void checkNullPointer(void *ptr) { + if (!ptr) { + fputs(MEMORY_ALLOCATION_ERROR, stderr); + exit(EXIT_FAILURE); + } } diff --git a/voronoi.h b/voronoi.h index db6961d..cb34dcd 100755 --- a/voronoi.h +++ b/voronoi.h @@ -1,4 +1,4 @@ -typedef struct watchtower { +typedef struct Watchtower { char *id; char *postcode; char *manager; @@ -9,4 +9,6 @@ typedef struct watchtower { void checkInputArgs(int argc, char **argv, FILE **datasetFile, \ FILE **polygonFile, FILE **outputFile); -void readWatchtowers(watchtower_t *watchtowers, FILE* datasetFile); \ No newline at end of file +watchtower_t** readWatchtowers(watchtower_t **watchtowers, FILE* datasetFile, \ + int *numWatchtowers); +void checkNullPointer(void *ptr); diff --git a/voronoi1 b/voronoi1 index d2723d6..41afb53 100755 Binary files a/voronoi1 and b/voronoi1 differ