#ifndef TOWERS_HEADER #include "towers.h" #endif #define BASE_10 10 #define MAX_CSV_ENTRY_LEN 512 #define MAX_FIELD_LEN 128 #define NUM_CSV_FIELDS 6 tower_t **readTowers(tower_t **towers, FILE *datasetFile, int *numTowers) { /* Maximum length of a single CSV line */ size_t lineBufferSize = MAX_CSV_ENTRY_LEN + 1; /* Stores the current line from the CSV */ char *lineBuffer = malloc(lineBufferSize * sizeof(*lineBuffer)); checkNullPointer(lineBuffer); int maxSizetowers = 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 towers array */ if (*numTowers == maxSizetowers) { maxSizetowers *= 2; tower_t **temp = realloc(towers, maxSizetowers * sizeof(*towers)); checkNullPointer(temp); towers = temp; } /* The current tower being filled in with information */ towers[*numTowers] = malloc(sizeof(*towers[*numTowers])); readCurrentTower(lineBuffer, towers[*numTowers]); *numTowers += 1; } free(lineBuffer); return towers; } void readCurrentTower(char *lineBuffer, tower_t *tower) { /* Stores the current CSV field for the current line */ char *token = strtok(lineBuffer, ","); size_t tokenLength; for (int i = 0; i < NUM_CSV_FIELDS; i++) { tokenLength = strlen(token); switch(i) { /* Case 0, 1, and 3 deal with strings * Case 2 deals with an integer * Case 4 and 5 deal with doubles * Each case is handled seperately to fill in the * tower with no space wasted. */ case 0: tower->id = malloc(sizeof(char) * tokenLength + 1); checkNullPointer(tower->id); strcpy(tower->id, token); tower->id[tokenLength] = '\0'; break; case 1: tower->postcode = malloc(sizeof(char) * tokenLength + 1); checkNullPointer(tower->postcode); strcpy(tower->postcode, token); tower->postcode[tokenLength] = '\0'; break; case 2: tower->population = strtol(token, NULL, BASE_10); break; case 3: tower->manager = malloc(sizeof(char) * tokenLength + 1); checkNullPointer(tower->manager); strcpy(tower->manager, token); tower->manager[tokenLength] = '\0'; break; case 4: tower->x = strtod(token, NULL); break; case 5: tower->y = strtod(token, NULL); break; } token = strtok(NULL, ","); } } void freeTowers(tower_t **towers, int numTowers) { for (int i = 0; i < numTowers; i++) { free(towers[i]->id); free(towers[i]->manager); free(towers[i]->postcode); free(towers[i]); } free(towers); }