diff --git a/BuildDataBase.c b/BuildDataBase.c index a81702bbe3d0a2084fdfbdd51918302aa0d310a1..ebc3ef0e44e3f7d05cbd95abbb928a7706bfbe4e 100644 --- a/BuildDataBase.c +++ b/BuildDataBase.c @@ -20,15 +20,13 @@ // Import headers. -//#include <string.h> -//#include <stdlib.h> -//#include <ctype.h> #include <fcntl.h> #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include "apue.h" +#include "HelperHeader.h" // Define Vars. @@ -47,7 +45,7 @@ typedef struct { } songs_struct; // Songs struct. int songs_array_max = ARRAY_SIZE; // Saves current size of songs array. -int current_song = 0; // Current song value to save. +int song_index = 0; // Current song index. songs_struct** songs_array; // The array which holds all song pointers. @@ -57,6 +55,10 @@ void read_file(); // Reads in chunk of file. void read_line(); // Separates file chunk into lines. void tokenize_line(); // Separates lines into fields. void populate_array(); // Populates array with fields. +void resize_array(); // Reallocates memory for array. +char* remove_quotes(); // Removes quotes from string value. +void print_song_info(); // Prints all info for provided song. +void exit_program(); // Frees memory and closes program. /** @@ -64,8 +66,23 @@ void populate_array(); // Populates array with fields. * Initializes and runs program. */ int main(int argc, char* argv[]) { + songs_array = calloc(songs_array_max, sizeof(songs_struct *)); int file_descriptor = open_file(); read_file(file_descriptor); + write(1, "\n\n\n\n\n", 10); + print_song_info(songs_array[1]); + print_song_info(songs_array[2]); + print_song_info(songs_array[3]); + print_song_info(songs_array[4]); + print_song_info(songs_array[5]); + print_song_info(songs_array[6]); + print_song_info(songs_array[7]); + print_song_info(songs_array[8]); + print_song_info(songs_array[9]); + print_song_info(songs_array[10]); + + + exit_program(); } @@ -108,8 +125,6 @@ void read_file(int file_descriptor) { *temp_buffer = *read_buffer; printf("Looping through buffer...\n"); while (index > 0) { - //printf("%s", read_buffer); - //printf("%c", temp_buffer[index]); if (temp_buffer[index] == '\n') { // Found first null terminator. Save location and exit loop. offset_amount = index; @@ -117,6 +132,7 @@ void read_file(int file_descriptor) { } index--; } + free(temp_buffer); // Set "Read Size" for lseek to travel to last null terminator. read_size = BUFFER_SIZE - offset_amount; @@ -126,10 +142,8 @@ void read_file(int file_descriptor) { } printf("Buffer: %d, Offset: %d, ReadSize: %ld\n\n", BUFFER_SIZE, offset_amount, read_size); - //write(1, read_buffer, BUFFER_SIZE); - //write(1, read_buffer, read_size); - printf("\n\n"); read_line(read_buffer, read_size); + free(read_buffer); } @@ -164,7 +178,10 @@ void read_line(char *read_buffer, size_t read_size) { chunk_index++; } } - printf("\n"); + // Last field so tokenize line one last time. + line_buffer[line_index] = '\0'; + tokenize_line(line_buffer); + free(line_buffer); } @@ -177,8 +194,8 @@ void tokenize_line(char *line_buffer) { int field_number = 0; char* field_buffer; - printf("\n\nTokenizing line...\n"); field_buffer = calloc(BUFFER_SIZE, sizeof(char)); + songs_array[song_index] = calloc(1, sizeof(songs_struct)); while (strcmp(&line_buffer[line_index], "\0") != 0) { // Check for comma to denote next field. @@ -187,30 +204,137 @@ void tokenize_line(char *line_buffer) { field_index = 0; line_index++; - if (strcmp(field_buffer, "") != 0) { - printf("%s\n", field_buffer); + //if (strcmp(field_buffer, "") != 0) { populate_array(field_number, field_buffer); field_number++; - } + //} free(field_buffer); field_buffer = calloc(BUFFER_SIZE, sizeof(char)); } else { // No comma found. field_buffer[field_index] = line_buffer[line_index]; - //printf("%c", line_buffer[line_index]); - //printf("%c", field_buffer[field_index]); field_index++; line_index++; } } - current_song++; + // Last field so populate values one last time. + populate_array(field_number, field_buffer); + song_index++; + free(field_buffer); } /** * Takes provided field value and associates with song in struct. */ -void populate_array(int field_number, char *field_value) { +void populate_array(int field_number, char *field_buffer) { + int temp_int; + int* temp_int_ptr; + float temp_float; + float* temp_float_ptr; + double temp_double; + double* temp_double_ptr; + + // Remove unecessary quotes from string value fields. + if (field_number == 3 || field_number == 8 || field_number == 17) { + field_buffer = remove_quotes(field_buffer); + } + + // Go through provided field and assign values appropriately with switch. + switch(field_number) { + case 3: // Album name. + songs_array[song_index]->album_name = copy_string(field_buffer); + break; + case 8: // Artist name. + songs_array[song_index]->artist = copy_string(field_buffer); + break; + case 10: // Duration. + temp_float = atof(field_buffer); + temp_float_ptr = &temp_float; + songs_array[song_index]->duration = copy_float(temp_float_ptr); + break; + case 14: // Hotttness. + temp_double = atof(field_buffer); + // Check if NAN. + if (temp_double != temp_double) { + temp_double = 0; + } + temp_double_ptr = &temp_double; + songs_array[song_index]->hotttnesss = copy_double(temp_double_ptr); + break; + case 17: // Song name. + songs_array[song_index]->song_name = copy_string(field_buffer); + break; + case 18: // Year. + temp_int = atoi(field_buffer); + temp_int_ptr = &temp_int; + songs_array[song_index]->year = copy_int(temp_int_ptr); + break; + default: + // Do nothing. This is not a field we care about. + break; + } +} + + +/** + * Removes quotes from provided string. + */ +char* remove_quotes(char* a_string) { + size_t string_length = strlen(a_string); + int orig_index; + int replace_index = 0; + + for (orig_index = 0; orig_index < string_length; orig_index++) { + if (a_string[orig_index] != '\"') { + a_string[replace_index] = a_string[orig_index]; + replace_index++; + } + } + // Fill rest of values with null terminators. + while (replace_index < string_length) { + a_string[replace_index] = '\0'; + replace_index++; + } + + return a_string; +} + + +/** + * Attempts to find song with provided name. Prints result. + */ +void print_song_info(songs_struct* song) { + float duration = *song->duration; + int year = *song->year; + double hotness = *song->hotttnesss; + + printf("Song Name: %s\n", song->song_name); + printf("Album Name: %s\n", song->album_name); + printf("Artist Name: %s\n", song->artist); + printf("Duration: %.2f\n", duration); + printf("year: %d\n", year); + printf("Hotttnesss: %f\n", hotness); + printf("\n"); +} + + +/** + * Frees remaining memory and so program can close cleanly. + */ +void exit_program() { + int index = 0; + while (songs_array[index] != NULL) { + free(songs_array[index]->album_name); + free(songs_array[index]->artist); + free(songs_array[index]->song_name); + free(songs_array[index]->duration); + free(songs_array[index]->year); + free(songs_array[index]->hotttnesss); + free(songs_array[index]); + index++; + } + free(songs_array); } diff --git a/CopyFunctions.c b/CopyFunctions.c new file mode 100644 index 0000000000000000000000000000000000000000..643ab8214883eaa0af4f2a1d1e6e0d29595a974e --- /dev/null +++ b/CopyFunctions.c @@ -0,0 +1,80 @@ +/** + * Brandon Rodriguez + * CS 3240 + * 09-19-17 + */ + + +/** + * Helper functions to have consistent value copying and error handling. + * + * All functions use memcpy to copy data, and error.c's err_dump on failure. + * + * All functions require a "source" pointer of equivalent typing, and returns + * a pointer to copied item's location. + */ + + +#include <stdlib.h> +#include <string.h> +#include "apue.h" + + +/** + * Copies string from destination to source. + */ +char* copy_string(char *source_ptr) { + char *copy_ptr; + copy_ptr = calloc((strlen(source_ptr) + 1), sizeof(char)); + if (copy_ptr != NULL) { + memcpy(copy_ptr, source_ptr, ((strlen(source_ptr) + 1) * sizeof(char))); + } else { + err_dump("Could not allocate memory for string calloc."); + } + return copy_ptr; +} + + +/** + * Copies float from destination to source. + */ +int* copy_int(int *source_ptr) { + int *copy_ptr; + copy_ptr = calloc(1, (sizeof(int) + 1)); + if (copy_ptr != NULL) { + memcpy(copy_ptr, source_ptr, sizeof(int)); + } else { + err_dump("Could not allocate memory for int calloc."); + } + return copy_ptr; +} + + +/** + * Copies float from destination to source. + */ +float* copy_float(float *source_ptr) { + float *copy_ptr; + copy_ptr = calloc(1, (sizeof(float) + 1)); + if (copy_ptr != NULL) { + memcpy(copy_ptr, source_ptr, sizeof(float)); + } else { + err_dump("Could not allocate memory for float calloc."); + } + return copy_ptr; +} + + +/** + * Copies double from destination to source. + */ +double* copy_double(double *source_ptr) { + double *copy_ptr; + copy_ptr = calloc(1, (sizeof(double) + 1)); + if (copy_ptr != NULL) { + memcpy(copy_ptr, source_ptr, sizeof(double)); + } else { + err_dump("Could not allocate memory for double calloc."); + } + return copy_ptr; +} diff --git a/HelperHeader.h b/HelperHeader.h new file mode 100644 index 0000000000000000000000000000000000000000..11f2fe63b0708ac49268069008a817dd90488ee9 --- /dev/null +++ b/HelperHeader.h @@ -0,0 +1,18 @@ +/** + * Brandon Rodriguez + * CS 3240 + * 09-19-17 + */ + + +/** + * A personal header for helper-functions. + */ + + +// Function prototypes. +char* copy_string(char* source_ptr); +int* copy_int(int* source_ptr); +float* copy_float(float* source_ptr); +double* copy_double(double* source_ptr); + diff --git a/makefile b/makefile index 3b97d6569c312a18f9d5be6a7a4844d6c5e00a89..a8602f869df5d7bafa1d8b653e676d31337f7542 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ all: - gcc -Wall -Wpedantic -std=c99 -g BuildDataBase.c error.c -o BuildDataBase + gcc -Wall -Wpedantic -std=c99 -g BuildDataBase.c error.c CopyFunctions.c -o BuildDataBase gcc -Wall -Wpedantic -std=c99 -g UseDataBase.c -o UseDataBase build: ./BuildDataBase