#include #include #include #include #define MAX_LINE_LENGTH 1024 // Define the struct to hold the parsed data for each line typedef struct { char *titleId; // Dynamically allocated int ordering; char *title; // Dynamically allocated char *region; // Dynamically allocated char *language; // Dynamically allocated char *types; // Dynamically allocated char *attributes; // Dynamically allocated int isOriginalTitle; } TitleLanguages; char *strdup(const char *s); // Function to read and store all lines (as strings) int processAkaLines(FILE *fh, TitleLanguages **parsed_lines) { char line[MAX_LINE_LENGTH]; // Buffer for each line int line_count = 0; int alloc_size = 10; // Initial memory allocation size *parsed_lines = malloc(alloc_size * sizeof(TitleLanguages)); // Allocate memory for the array of TitleLanguages structs if (!*parsed_lines) { perror("Memory allocation failed"); return 0; } // Read the file line by line while (fgets(line, sizeof(line), fh)) { // Remove newline character from line line[strcspn(line, "\n")] = 0; // If we've reached the allocated size, reallocate more memory for TitleLanguages array if (line_count >= alloc_size) { alloc_size *= 2; // Double the allocated size *parsed_lines = realloc(*parsed_lines, alloc_size * sizeof(TitleLanguages)); if (!*parsed_lines) { perror("Memory reallocation failed"); return 0; } } TitleLanguages *current_line = &(*parsed_lines)[line_count]; // Parse the fields from the line and directly store them into the struct current_line->titleId = strdup(strtok(line, "\t")); current_line->ordering = atoi(strtok(NULL, "\t")); current_line->title = strdup(strtok(NULL, "\t")); current_line->region = strdup(strtok(NULL, "\t")); current_line->language = strdup(strtok(NULL, "\t")); current_line->types = strdup(strtok(NULL, "\t")); current_line->attributes = strdup(strtok(NULL, "\t")); current_line->isOriginalTitle = atoi(strtok(NULL, "\t")); // If any memory allocation fails, free all previously allocated memory if (!current_line->titleId || !current_line->title || !current_line->region || !current_line->language || !current_line->types || !current_line->attributes) { perror("Memory allocation failed"); return 0; } line_count++; } return line_count; // Return the total number of lines read } // Function to read the Akas file and process lines int readAkas(TitleLanguages **languages) { int line_count = 0; FILE *fh = NULL; // Open the file specified by the constant FILENAME fh = fopen("imdb/title.akas.tsv", "r"); if (!fh) { perror("Error opening file"); return 1; } // Process lines and get the result line_count = processAkaLines(fh, languages); // Print a message once all lines are read printf("Processing complete. Total lines read: %d\n", line_count); // Return the number of lines processed return line_count; } int main(void) { TitleLanguages *languages = NULL; int line_count = 0; // Pass the address of languages to readAkas line_count = readAkas(&languages); // Print the first 4 lines and last 4 lines of the struct array printf("First and last 4 lines processed:\n"); for (int i = 0; i < line_count; i++) { // Print first 4 lines if (i < 4) { printf("Line %d: %s, %d, %s, %s, %s, %s, %d\n", i + 1, languages[i].titleId, languages[i].ordering, languages[i].title, languages[i].region, languages[i].language, languages[i].types, languages[i].isOriginalTitle); } // Print last 4 lines if (i >= line_count - 4) { printf("Line %d: %s, %d, %s, %s, %s, %s, %d\n", i + 1, languages[i].titleId, languages[i].ordering, languages[i].title, languages[i].region, languages[i].language, languages[i].types, languages[i].isOriginalTitle); } } // Clean up the array of structs and the dynamically allocated strings for (int i = 0; i < line_count; i++) { free(languages[i].titleId); free(languages[i].title); free(languages[i].region); free(languages[i].language); free(languages[i].types); free(languages[i].attributes); } free(languages); return 0; }