#include #include #include #define NUM_USERS 611 #define NUM_MOVIES 9743 #define NUM_GENRES 20 typedef struct Movies { int movieID; struct Movies *next; } Movies; typedef struct Genres { int genreID; struct Genres *next; } Genres; const char *genreMap[] = {"Action", "Adventure", "Animation", "Children", "Comedy", "Crime", "Documentary", "Drama", "Fantasy", "Film-Noir", "Horror", "IMAX", "Musical", "Mystery", "Romance", "Sci-Fi", "Thriller", "War", "Western"}; //输入电影风格返回其映射的id int getGenreID(char *style) { // int index = 0; // const char *genreMap[] = {"Action", "Adventure", "Animation", "Children's", // "Comedy", "Crime", "Documentary", "Drama", // "Fantasy", "Film-Noir", "Horror", "IMAX", "Musical", // "Mystery", "Romance", "Sci-Fi", "Thriller", // "War", "Western"}; // while (strcmp(genreMap[index], style) != 0) // { // index++; // } int found = 0; int i; for (i = 0; i < NUM_GENRES - 1; i++) { if (strcmp(genreMap[i], style) == 0) { found = 1; break; } } if (found == 1) { return i; } else { return -1; } } // 函数原型 Movies *appendMovies(Movies *last, int id); Genres *appendGenres(Genres *head, int id); void incremendGenres(int count[], int movieID, Genres **movies); // 传入movieID,输出风格下标 void clearArrInt(int *arr, int size); // 将所有元素设为0 void parseGenreString(char *inputStr, int movieID, Genres **movies_arr); // inputStr: "Adventure|IMAX..." movieID: the id to make genre linked list. movies_arr[]: to store the linked list. int main(void) { // Firstly open the ratings.csv FILE *fp; fp = fopen("./ratings.csv", "r"); char *buf = malloc(256 * sizeof(char)); // Declare the users table and init with null. Movies *users[NUM_USERS]; for (int i = 0; i < NUM_USERS; i++) { users[i] = NULL; } fgets(buf, 256 * sizeof(char), fp); // 看每个用户喜欢什么电影 int userID, movieID, rating; char input[64]; int loc, loc1; while (fgets(buf, 256 * sizeof(char), fp) != NULL) { loc = 0; input[0] = '\0'; // clear the array // get userID while (buf[loc] != ',') { input[loc] = buf[loc]; loc++; } input[loc++] = '\0'; userID = atoi(input); // printf("UserID: %d\n", userID); // get movieID loc1 = 0; input[0] = '\0'; while (buf[loc] != ',') { input[loc1++] = buf[loc]; loc++; } input[loc1] = '\0'; loc++; // ATOI(3) Linux Programmer's Manual ATOI(3) // NAMint count[], E // atoi, atol, atoll - convert a string to an integer movieID = atoi(input); // printf("movieID: %d\n", movieID); // get ratings input[0] = '\0'; loc1 = 0; while (buf[loc] != ',') { input[loc1++] = buf[loc]; loc++; } input[loc1] = '\0'; rating = atoi(input); if (rating >= 3) { printf("Rate: %d, userID: %d, movieID: %d\n", rating, userID, movieID); users[userID] = appendMovies(users[userID], movieID); } } fclose(fp); fp = fopen("./movies.csv", "r"); // 下标表示电影id Genres *movies[NUM_MOVIES]; // TODO: 仿照我的代码填充*movies数组 // 李王子写 ok 你写吧 for (int i = 0; i < NUM_MOVIES; i++) { movies[i] = NULL; } char *str = (char *)malloc(256 * sizeof(char)); //读第一行 fgets(str, 256 * sizeof(char), fp); // fgets() returns s on success, and NULL on error or when end of file // occurs while no characters have been read. // 你那个该写!=NULL 你看注释 // ok int movie_id = 0; while (fgets(str, 256 * sizeof(char), fp) != NULL) { // get the movie's id loc = 0; input[0] = '\0'; while (str[loc] != ',') { input[loc] = str[loc]; loc++; } input[loc++] = '\0'; // 现在loc指向电影名字的第0个字符 movie_id = atoi(input); printf("Debug: movie_id: %d\n", movie_id); if (str[loc] == '"') { // in case the title has comma inside. loc++; while (str[loc] != '"') { loc++; } loc += 2; // 现在指向genres第0个字符 } else { // go to genres while (str[loc] != ',') loc++; loc++; // 现在loc指向风格 } loc1 = 0; input[0] = '\0'; while (str[loc] != '\n' && str[loc] != '\0' && str[loc] != '\r') { input[loc1++] = str[loc++]; } input[loc1] = '\0'; parseGenreString(input, movie_id, movies); } fclose(fp); // 开始输出答案到文件answer.txt fp = fopen("./answer.txt", "w+"); // w+: 如果文件已存在先清空 int count[NUM_GENRES] = {}; // 开始从第一个用户循环 (1) Movies *ptr; for (int i = 1; i < NUM_USERS; i++) { clearArrInt(count, NUM_GENRES); // 便历他喜欢的电影 ptr = users[i]; while (ptr != NULL) { incremendGenres(count, ptr->movieID, movies); printf("Debug: userID: %d, movieID: %d\n", i, ptr->movieID); ptr = ptr->next; } // 输出答案 fprintf(fp, "User id: %d\n", i); for (int j = 0; j < NUM_GENRES - 1; j++) { fprintf(fp, "%s: %d\t", genreMap[j], count[j]); } fprintf(fp, "\n"); } fclose(fp); return 0; } Movies *appendMovies(Movies *last, int id) { Movies *new = malloc(sizeof(Movies)); new->movieID = id; new->next = NULL; // 1.如果是null if (last == NULL) { return new; } // 2.不是null,在最后加上新节点 Movies *ptr = last; while (ptr->next != NULL) { ptr = ptr->next; } ptr->next = new; return last; } void incremendGenres(int count[], int movieID, Genres **movies) { Genres *ptr = movies[movieID]; while (ptr != NULL) { count[ptr->genreID]++; printf("Debug: movidID: %d, genreID: %d, genre: %s\n", movieID, ptr->genreID, genreMap[ptr->genreID]); ptr = ptr->next; } } void clearArrInt(int *arr, int size) { for (int i = 0; i < size; i++) { arr[i] = 0; } } void parseGenreString(char *inputStr, int movieID, Genres **movies_arr) { // 处理输入的string int strLen = strlen(inputStr); char buf[64]; int locPtr = 0; printf("Debug: inputStr: %s\n", inputStr); int genreID; for (int i = 0; i < strLen; i++) { if (inputStr[i] == '|') { // time to divide the string and make magic happen buf[locPtr] = '\0'; printf("Debug: buf: %s, genreID: %d\n", buf, getGenreID(buf)); genreID = getGenreID(buf); if (genreID != -1) movies_arr[movieID] = appendGenres(movies_arr[movieID], genreID); locPtr = 0; } else { buf[locPtr++] = inputStr[i]; } } // do this again buf[locPtr] = '\0'; printf("Debug: buf: %s, genreID: %d\n", buf, getGenreID(buf)); genreID = getGenreID(buf); if (genreID != -1) movies_arr[movieID] = appendGenres(movies_arr[movieID], genreID); locPtr = 0; } Genres *appendGenres(Genres *head, int id) { Genres *new = malloc(sizeof(Genres)); new->genreID = id; new->next = NULL; if (head == NULL) { return new; } Genres *ptr = head; while (ptr->next != NULL) { ptr = ptr->next; } ptr->next = new; return head; }