BUPT-homework/semester2/challenge1-moviedb/main.c

332 lines
7.7 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
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 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;
}