2022-03-21 18:00:27 +08:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
#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;
|
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
const char *genreMap[] = {"Action", "Adventure", "Animation", "Children",
|
|
|
|
|
"Comedy", "Crime", "Documentary", "Drama",
|
|
|
|
|
"Fantasy", "Film-Noir", "Horror", "IMAX", "Musical",
|
|
|
|
|
"Mystery", "Romance", "Sci-Fi", "Thriller",
|
|
|
|
|
"War", "Western"};
|
|
|
|
|
|
2022-03-21 18:00:27 +08:00
|
|
|
|
//输入电影风格返回其映射的id
|
2022-03-22 21:12:30 +08:00
|
|
|
|
int getGenreID(char *style)
|
2022-03-21 18:00:27 +08:00
|
|
|
|
{
|
2022-03-22 21:12:30 +08:00
|
|
|
|
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;
|
2022-03-21 18:00:27 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 函数原型
|
|
|
|
|
Movies *appendMovies(Movies *last, int id);
|
2022-03-22 21:12:30 +08:00
|
|
|
|
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.
|
2022-03-21 18:00:27 +08:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
// 看每个用户喜欢什么电影
|
2022-03-22 21:12:30 +08:00
|
|
|
|
int userID, movieID, rating;
|
2022-03-21 18:00:27 +08:00
|
|
|
|
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';
|
2022-03-22 21:12:30 +08:00
|
|
|
|
loc++;
|
|
|
|
|
|
|
|
|
|
// ATOI(3) Linux Programmer's Manual ATOI(3)
|
|
|
|
|
// NAMint count[], E
|
|
|
|
|
// atoi, atol, atoll - convert a string to an integer
|
|
|
|
|
|
2022-03-21 18:00:27 +08:00
|
|
|
|
movieID = atoi(input);
|
|
|
|
|
// printf("movieID: %d\n", movieID);
|
2022-03-22 21:12:30 +08:00
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
}
|
2022-03-21 18:00:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
fp = fopen("./movies.csv", "r");
|
2022-03-21 18:00:27 +08:00
|
|
|
|
|
|
|
|
|
// 下标表示电影id
|
|
|
|
|
Genres *movies[NUM_MOVIES];
|
|
|
|
|
|
|
|
|
|
// TODO: 仿照我的代码填充*movies数组
|
|
|
|
|
// 李王子写 ok 你写吧
|
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
for (int i = 0; i < NUM_MOVIES; i++)
|
2022-03-21 18:00:27 +08:00
|
|
|
|
{
|
2022-03-22 21:12:30 +08:00
|
|
|
|
movies[i] = NULL;
|
2022-03-21 18:00:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
char *str = (char *)malloc(256 * sizeof(char));
|
2022-03-21 18:00:27 +08:00
|
|
|
|
|
|
|
|
|
//读第一行
|
2022-03-22 21:12:30 +08:00
|
|
|
|
fgets(str, 256 * sizeof(char), fp);
|
|
|
|
|
|
2022-03-21 18:00:27 +08:00
|
|
|
|
// fgets() returns s on success, and NULL on error or when end of file
|
|
|
|
|
// occurs while no characters have been read.
|
|
|
|
|
// 你那个该写!=NULL 你看注释
|
2022-03-22 21:12:30 +08:00
|
|
|
|
// ok
|
2022-03-21 18:00:27 +08:00
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
int movie_id = 0;
|
2022-03-21 18:00:27 +08:00
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
while (fgets(str, 256 * sizeof(char), fp) != NULL)
|
2022-03-21 18:00:27 +08:00
|
|
|
|
{
|
2022-03-22 21:12:30 +08:00
|
|
|
|
// get the movie's id
|
|
|
|
|
loc = 0;
|
|
|
|
|
input[0] = '\0';
|
2022-03-21 18:00:27 +08:00
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
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);
|
2022-03-21 18:00:27 +08:00
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
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';
|
2022-03-21 18:00:27 +08:00
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
while (str[loc] != '\n' && str[loc] != '\0' && str[loc] != '\r')
|
|
|
|
|
{
|
|
|
|
|
input[loc1++] = str[loc++];
|
|
|
|
|
}
|
|
|
|
|
input[loc1] = '\0';
|
|
|
|
|
parseGenreString(input, movie_id, movies);
|
|
|
|
|
}
|
2022-03-21 18:00:27 +08:00
|
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
|
|
// 开始输出答案到文件answer.txt
|
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
fp = fopen("./answer.txt", "w+"); // w+: 如果文件已存在先清空
|
2022-03-21 18:00:27 +08:00
|
|
|
|
|
|
|
|
|
int count[NUM_GENRES] = {};
|
|
|
|
|
|
|
|
|
|
// 开始从第一个用户循环 (1)
|
|
|
|
|
Movies *ptr;
|
2022-03-22 21:12:30 +08:00
|
|
|
|
for (int i = 1; i < NUM_USERS; i++)
|
|
|
|
|
{
|
|
|
|
|
clearArrInt(count, NUM_GENRES);
|
2022-03-21 18:00:27 +08:00
|
|
|
|
// 便历他喜欢的电影
|
|
|
|
|
ptr = users[i];
|
2022-03-22 21:12:30 +08:00
|
|
|
|
while (ptr != NULL)
|
|
|
|
|
{
|
|
|
|
|
incremendGenres(count, ptr->movieID, movies);
|
|
|
|
|
printf("Debug: userID: %d, movieID: %d\n", i, ptr->movieID);
|
2022-03-21 18:00:27 +08:00
|
|
|
|
ptr = ptr->next;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
// 输出答案
|
|
|
|
|
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");
|
|
|
|
|
}
|
2022-03-21 18:00:27 +08:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
void incremendGenres(int count[], int movieID, Genres **movies)
|
|
|
|
|
{
|
2022-03-21 18:00:27 +08:00
|
|
|
|
Genres *ptr = movies[movieID];
|
2022-03-22 21:12:30 +08:00
|
|
|
|
while (ptr != NULL)
|
|
|
|
|
{
|
|
|
|
|
count[ptr->genreID]++;
|
|
|
|
|
printf("Debug: movidID: %d, genreID: %d, genre: %s\n", movieID, ptr->genreID, genreMap[ptr->genreID]);
|
|
|
|
|
ptr = ptr->next;
|
|
|
|
|
}
|
2022-03-21 18:00:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-03-22 21:12:30 +08:00
|
|
|
|
void clearArrInt(int *arr, int size)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
|
{
|
2022-03-21 18:00:27 +08:00
|
|
|
|
arr[i] = 0;
|
|
|
|
|
}
|
2022-03-22 21:12:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2022-04-02 14:31:05 +08:00
|
|
|
|
}
|