Tips and examples for Movie Inventory

So currently I'm doing a final project for my C++ course, this time it's a bit more open-ended. Thing is, there are several conditions that must be met and I'm stuck on how to do my code and suffice all the conditions.

Project details and stipulations:
Your project topic is a Movie Inventory System:
o Include information for a collection of movies.
o Allow people to manage their movie collection.
o Allow for selection of movies by a variety of sorting options.
o Make recommendations based on different users selections.

The following elements must be incorporated into your project and used in a meaningful way:
Strings
Classes AND Constructors
Vectors
Inheritance / Polymorphism and Composition/Aggregation/Initialization Lists
Files
Exception Handling
Templates
Additionally, your project must:
Be free from errors, including all data entry validation / exception handling

These elements would be considered Extra Credit:
Iterators
STL’s

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include<exception>
#include<vector>
#include<string>
#include<fstream>
using namespace std;
class Movie
{
private:
    vector<string>movies;
    string line;
    vector<string> movieTitle;
    vector<string>movieGenre;
    vector<int>movieYear;
    vector<int>movieRuntime;
    vector<float>movieRating;
    string mT, mG;
    int mY, mR;
    float mRa;
    void readFile()
    {
        ifstream myfile("movieCatalogue.txt");
     
        if (myfile.is_open())
        {
            
            while (getline(myfile, line,' '))
            {
           
                movies.push_back(line);
            }
            for (int i = 0; i < movies.size(); i++)
            {
                cout << movies[i] << " ";

        }
 }
        else { cout << "Unable to open file"; }

        myfile.clear();
        myfile.seekg(0, std::ios_base::beg);

    

            while (myfile>> mT>> mG>> mY>> mR>> mRa)
            {
                movieTitle.push_back(mT);
                movieGenre.push_back(mG);
                movieYear.push_back(mY);
                movieRuntime.push_back(mR);
                movieRating.push_back(mRa);
                
            }
            
            myfile.close();

      
    }

public:
    Movie(vector<string> movieTitle,vector<string>movieGenre,vector<int>movieYear,vector<int>movieRuntime,vector<float>movieRating)
    {
        this->movieTitle = movieTitle;
        this->movieGenre = movieGenre;
        this->movieYear = movieYear;
        this->movieRuntime = movieRuntime;
        this->movieRating = movieRating;
        readFile();
 
    }
   
};
int main()
{
    vector<string> movieTitle;
    vector<Movie>mo;
    vector<string> movieGenre;
     vector<int> movieYear;
    vector<int> movieRuntime;
    vector<float> imdbRating;
    Movie movie(movieTitle,movieGenre,movieYear,movieRuntime,imdbRating);
 
}


As my code is now I'm currently reading in my file twice, once for the entire line and again to separate each element into its own vector. My thought process was to allow the user to search by title,genre,year,runtime, or rating. How everything else will fit into that I'm not completely sure. I was thinking of doing it with polymorphism and sorting my vectors with a template. exception handling would most likely be for my data-validation in case any harmful inputs get used.
Last edited on
To maintain quick lookup you unfortunately must have a proper database.

For a CS 100-200 level project, however, you don’t need to be that complex. Just have a single Movie class and prepare a number of different lookup functions.

Also, a “Movie” should be a record for a single movie.
Create a container class if you wish to have special operations on a list of Movies.

For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct Movie
{
  std::string title;
  std::string genre;
  int         year;
  int         runtime;
  float       rating;
};

struct Movies
{
  std::vector<Movie> movies;

  int find_by_title( const std::string& title )
  {
    for (int n = 0; n < movies.size(); n++)
      if (movies[n].title == title)
        return n;
    return -1;
  }

  // and so on
};

Also, it is a good idea to split the file reading stuff between objects. Have Movie know how to read/write a single movie record from/to file.

Then Movies can use that method repeatedly to read/write an entire catalogue of movies.

The C++ way is to overload the << and >> operators (stream insertion and stream extraction), but you can easily do it with functions or object methods instead. The point is to let the stream signal termination when reading.

1
2
3
4
5
6
7
void Movies::read_from_file( const std::string& filename )
{
  std::ifstream f( filename );
  Movie movie;
  while (f >> movie)
    movies.push_back( movie );
}
OR
1
2
3
4
5
6
7
void Movies::read_from_file( const std::string& filename )
{
  std::ifstream f( filename );
  Movie movie;
  while (movie.read_from_stream( f ))  // see note below
    movies.push_back( movie );
}

note: Movie::read_from_stream() returns either the argument stream or a boolean indicating success or failure.

However you do it this kind of coupling is a common idiom in C++ and very efficient.

Hope this helps.


[edit]
Let us know if you are handling more than a thousand or two movies.
Last edited on
You're off to an inauspicious start. Does this seem right to you?
1
2
3
4
class Movie
{
private:
    vector<string>movies;
so currently I'm trying to do my calls for different types of information.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    Movie(vector<string> movieTitle,vector<string>movieGenre,vector<int>movieYear,vector<int>movieRuntime,vector<float>movieRating)
    {
        this->movies=movies;
        this->movieTitle = movieTitle;
        this->movieGenre = movieGenre;
        this->movieYear = movieYear;
        this->movieRuntime = movieRuntime;
        this->movieRating = movieRating;
         readFile();
    }
  
    vector<string>&getMovies() { 
        for (int i = 0; i < movies.size(); i++)
            cout << movies[i]<<"\n";
           return movies;
       }
    vector<string>&getMovieTitle() { 
        for (int i = 0; i < movieTitle.size(); i++)
               cout << movieTitle[i];
        return movieTitle; }
    vector<string>& getMovieGenre() {
        for (int i = 0; i < movieGenre.size(); i++)
            cout << movieGenre[i];
        return movieGenre;
    }
};

The first class will only gather information.
Zootopia Comedy 2016 110 8
Howl's_Moving_Castle Fantasy 2004 119 8.2
Deadpool Action 2016 109 8
Training_Day Thriller 2001 122 7.7
Parasite Thriller 2019 132 8.6
Ready_Player_One Action 2018 139 7.5
Fantastic_Beasts:_The_Crimes_of_Grindelwald Fantasy 2018 133 6.6
Venom Action 2018 112 6.7
John_Wick:_Chapter_2 Action 2017 122 7.5
Aquaman Action 2018 142 7

here's an example I was working with but yes I do want to increase the number of movies
These elements would be considered Extra Credit:
Iterators
STL’s

Wow, kiss your professor for me. Mine would give an instant 0% on an assignment using any STL functionalities.

Don't forget to update your code as it changes so we know what you're working with.

The first class will only gather information.

If you plan on making several classes, I'd recommend you don't. You don't want to complicate things.

You need a single class. Have a vector of that class in your main. You'll insert movies as they come into that vector and you can output it easily with I/O overloading if needed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<iostream>
#include <string>
#include <vector>

class Movie
{
private:
	std::string movieName;
	int date;
public:
	Movie(std::string a, int d) : movieName(a), date(d) //Constructor to easily initialize object variables
	{}

	friend std::ostream& operator<< (std::ostream &out, const Movie &p); //Optional overload
};

std::ostream & operator<<(std::ostream & out, const Movie & p) // //Optional overload
{
	std::cout << p.movieName << " Released: " << p.date << '\n';
	return out;
}

int main()
{
	std::vector<Movie> movies;
       
	movies.push_back(Movie("Twilight", 12)); //Create object with constructor and push it into the vector
	movies.push_back(Movie("Sucks", 21)); //Create object with constructor and push it into the vector

	for (auto &i : movies) //Iterator
	{
		std::cout << i;
	}
}
Last edited on
@zapshe how are you reading the file in? I understand that you're creating a constructor that accepts two arguments. As per her instructions (and I asked her twice for clarification) all project conditions must be sufficient. This includes inheritance, my idea was to have a customer inherit from movie collection. Basically my first class reads in my file of movies, and then in my second class I sort those movies by various ways. Finally a customer class will have a single value which will be a vector holding their selections. I need to somehow make it work with polymorphism, I'm looking for suggestions or tweaks I can make. I'll probably post an update to my could later today.
I see, so you'll need 2 classes, one for the movies and one for the people. Assuming an input file formatted like this:

Name
Movies Dates
Name
Movies Dates
etc...


The code would be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include<iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>

class Movie
{
private:
	std::string movieName;
	int date;
public:
	Movie(std::string a, int d) : movieName(a), date(d)
	{}

	friend std::ostream& operator<< (std::ostream &out, const Movie &p);
};

std::ostream & operator<<(std::ostream & out, const Movie & p)
{
	std::cout << p.movieName << " Released: " << p.date << '\n';
	return out;
}

class Person
{
private:
	std::string name;
	std::vector<Movie> movies;

public:
	Person(std::string n) : name(n) {}

	void insertMovie(std::string Name, int Date)
	{
		//Put the Name/Date into the movies vector
	}
};

int main()
{
	std::ifstream inFile;
	std::vector<Person> people;

	std::string tempName;
	while (inFile >> tempName)
	{
		people.push_back(Person(tempName));
		std::stringstream temp;
		std::string tempMovies;
		getline(inFile, tempMovies);
		temp << tempMovies;
		while (temp >> tempMovies)
		{
			int date;
			temp >> date;
			people[people.size() - 1].insertMovie(tempMovies, date);
		}
	}
	
}



This is just for reference, your code will be different depending on how the input file is formatted.
Last edited on
Could you explain how you're reading your file? I think your method is a bit cleaner than mine though I will be creating a customer object which will have it's own name and choices for movies.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include<string>
#include<vector>
#include<exception>
#include <fstream>
#include <sstream>
using namespace std;
class Movie
{
private:
	std::string movieName;
	int date;
public:
	Movie(std::string a, int d) : movieName(a), date(d) //Constructor to easily initialize object variables
	{}

	friend std::ostream& operator<< (std::ostream& out, const Movie& p); //Optional overload
};

std::ostream& operator<<(std::ostream& out, const Movie& p) // //Optional overload
{
	std::cout << p.movieName << " Released: " << p.date << '\n';
	return out;
}
class Person
{
private:
	std::string name;
	std::vector<Movie> movies;

public:
	Person(std::string n) : name(n) {}

	void insertMovie(std::string Name, int Date)
	{
		movies.emplace_back(Name, Date);

		for (size_t i = 0; i < movies.size(); i++)
		{
			cout << movies[i];
		}
	}
};

int main()
{
	std::ifstream inFile("movieCatalogue.txt");
	std::vector<Person> people;

	std::string tempName;
	while (inFile >> tempName)
	{
		people.push_back(Person(tempName));
		std::stringstream temp;
		std::string tempMovies;
		getline(inFile, tempMovies);
		temp << tempMovies;
		while (temp >> tempMovies)
		{
			int date;
			temp >> date;
			people[people.size() - 1].insertMovie(tempMovies, date);
		}
	}

}

@zapshe I think I want them to choose their name, plus I really want an explanation please.
Last edited on
Could you explain how you're reading your file?


This is the part of the code that does that:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main()
{
	std::ifstream inFile;
        inFile.open("Example.txt");
	std::vector<Person> people;

	std::string tempName;
	while (inFile >> tempName)
	{
		people.push_back(Person(tempName));
		std::stringstream temp;
		std::string tempMovies;
		getline(inFile, tempMovies);
		temp << tempMovies;
		while (temp >> tempMovies)
		{
			int date;
			temp >> date;
			people[people.size() - 1].insertMovie(tempMovies, date);
		}
	}
	
}


If you're not familiar with file streams then:

http://www.cplusplus.com/doc/tutorial/files/
@zapshe no, I'm referring to that code in particular. What's going on? Also I'm looking to create Person as a separate class from the total movies.
Last edited on
Created a vector of people, and a temporary string.

The while loop loops on the condition that inFile can feed data into tempName. Since I'm assuming a specific format, I read in the name from the loop condition, then I push a person object with that name into the vector.

From there, the object I'm working on is the last object, or people.size()-1. I then read in the next line with the movies/dates, and then put them into a string stream so I can read them in one word at a time. I then change the information in the object.
Comedy Released: 2016
Comedy Released: 2016
110 Released: 8
Fantasy Released: 2004
Fantasy Released: 2004
119 Released: 8
Fantasy Released: 2004
119 Released: 8
.2 Released: 8
Action Released: 2016
Action Released: 2016
109 Released: 8
Thriller Released: 2001
Thriller Released: 2001
122 Released: 7
Thriller Released: 2001
122 Released: 7
.7 Released: 7
Thriller Released: 2019
Thriller Released: 2019
132 Released: 8
Thriller Released: 2019
132 Released: 8
.6 Released: 8
Action Released: 2018
Action Released: 2018
139 Released: 7
Action Released: 2018
139 Released: 7
.5 Released: 7
Fantasy Released: 2018
Fantasy Released: 2018
133 Released: 6
Fantasy Released: 2018
133 Released: 6
.6 Released: 6
Action Released: 2018
Action Released: 2018
112 Released: 6
Action Released: 2018
112 Released: 6
.7 Released: 6
Action Released: 2017
Action Released: 2017
122 Released: 7
Action Released: 2017
122 Released: 7
.5 Released: 7
Action Released: 2018
Action Released: 2018
142 Released: 7
Zootopia Comedy 2016 110 8
Howl's_Moving_Castle Fantasy 2004 119 8.2
Deadpool Action 2016 109 8
Training_Day Thriller 2001 122 7.7
Parasite Thriller 2019 132 8.6
Ready_Player_One Action 2018 139 7.5
Fantastic_Beasts:_The_Crimes_of_Grindelwald Fantasy 2018 133 6.6
Venom Action 2018 112 6.7
John_Wick:_Chapter_2 Action 2017 122 7.5
Aquaman Action 2018 142 7
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include<string>
#include<vector>
#include<exception>
#include <fstream>
#include <sstream>
using namespace std;
class Movie
{
private:
	string movieName;
	int date;
	string genre;
	int runtime;
	float rating;
public:
	Movie(string movieName, string genre, int date, int runtime, float rating)
	{
		this->movieName = movieName;
		this->genre = genre;
		this->date = date;
		this->runtime = runtime;
		this->rating = rating;
	}
	string getMoviename() { return movieName; }
	void setMoviename(string movieName) { this->movieName = movieName; }
	string getMoviegenre() { return genre; }
	void setMoviegenre(string genre) { this->genre = genre; }
	int getMovieyear() { return date; }
	void setMovieyear(int date) { this->date = date; }
	int getRuntime() { return runtime; }
	void setRuntime(int runtime) { this->runtime = runtime; }
	float getRating() { return rating; }
	void setRating(float rating) { this->rating = rating; }
};
struct movies
{
	string name;
	string genre;
	int year;
	int runtime;
	double rating;
	movies(string name_,
		string genre_,
		int year_,
		int runtime_,
		double rating_):name(name_),genre(genre_),year(year_),runtime(runtime_),rating(rating_)
	{

	}

};
std::ostream& operator<<(std::ostream& os, const movies& pr)
{
	return os << pr.name << " " << pr.genre << " " << pr.year << '\n';
}
class customer : public Movie
{
public:

};
int main()
{
	vector<movies>movieCollection;
	movies a1 = { "Zootopia", "Comedy", 2016, 110 ,8 };
	movies a2 = { "Howl's Moving Castle" ,"Fantasy" ,2004 ,119 ,8.2};
	movies a3 = { "Deadpool"," Action ",2016 ,109 ,8 };
	movies a4 = { "Training Day","Thriller ",2001 ,122 ,7.7 };
	movies a5 = {" Parasite", "Thriller", 2019 ,132 ,8.6 };
	movies a6 = {"Ready Player One", "Action", 2018 ,139 ,7.5 };

	movieCollection.push_back(a1);
	movieCollection.push_back(a2); 
	movieCollection.push_back(a3); 
	movieCollection.push_back(a4); 
	movieCollection.push_back(a5);
	movieCollection.push_back(a6);

	for (int i = 0; i < movieCollection.size(); i++)
	{
		cout << movieCollection[i];
	}
   
}
Topic archived. No new replies allowed.