Yet another question about my project for my university! We are creating a cash register program which has an inventory, both held in their own respective header files with their own classes and objects.
Here is our current iteration of our header files, thought it may be messy from debugging.
Inventory.h:
class inventory
{
protected:
vector <item> itemList;
fstream infile;
public:
void printList();
void fillInventory();
void fileOpen();
};
class item
{
protected:
double price;
string name;
int amount;
friend class inventory;
};
Register.h:
class cashRegister : protected inventory
{
private:
vector <int> userChoice;
double total = 0;
public:
void input();
void printReceipt();
void calcTotal();
const double getTotal();
};
void cashRegister::input()
{
int temp;
try
{
do
{
cout << "\nPlease select an item using the corresponding item number.\n=> ";
cin >> temp;
if (cin.fail())
{
throw(256);
}
else
{
if (temp == -1)
{
break;
}
else if (temp >= 0 && temp <= 10)
{
if (inventory.stockChecker(temp) == 1)
{
userChoice.push_back(temp);
}
}
else
{
throw(1);
}
}
cout << "\n\n";
printInventory();
} while (true);
}
catch (int error)
{
cout << "Input error: " << error << endl;
cout << "Please enter a value from 0 to 10 to select an item (-1 to exit).\n";
cout << "----------------------------------------------------------------\n";
cin.clear();
cin.ignore(256, '\n');
input();
}
}
The problem here is once we pass ourselves into Register.h, we take user input then call the printInventory inventory method after every entry. But when we go to printInventory we no longer have the itemList data that the inventory object held.
Here is main.cpp for clarification on the objects:
#include"Inventory.h"
#include"Register.h"
int main()
{
inventory inv;
inv.fileOpen();
inv.fillInventory();
inv.printInventory();
cashRegister register1;
register1.input();
register1.calcTotal();
register1.printReceipt();
}
Our object inv holds a vector of item objects, which has the data members price amount name. So when we create the register1 object then try to print the inventory again, we now have an empty vector. How would I achieve being able to print the inv object's itemList or other data in general?
EDIT: Also to note I did try passing the inv object by reference and then calling the methods with that object. It did work but it felt awfully messy.
If you want to access the data of inv from a cashRegister object; instead of passing the inv object as reference every time you use it's data, you may want to hold a pointer in cashRegister class. inventory class will have member functions for manupilating and accessing it's data. Therefore you will be able to access to same cashRegister from multiple inventory objects, easily doing operations on cashRegister. With this approach, you will just need to initialize your cashRegister class with a pointer to inventory class.
class inventory
{
public:
void printList();
void changeData();
...
};
class cashRegister
{
private:
inventory* inv;
public:
cashRegister(inventory *inv)
:
inv(inv)
{}
void printInventory()
{
inv->printList();
}
...
};
int main()
{
inventory inv;
inv.fileOpen();
inv.fillInventory();
inv.printInventory();
cashRegister register1(&inv);
cashRegister register2(&inv);
register1.input();
register1.calcTotal();
register1.printReceipt();
register1.printInventory();
register2.printInventory();
}
Related
I'm getting the error after I delete a pointer from the vector and try to delete a second one. I'm still new to pointers
I created a base class of shapes and have multiple shapes derived classes not shown here and I have to store them in a vector of pointers.
I ask the user to add shapes of their choice measures and calculate the volumes
then I also ask what shapes they want to remove.
#include <string>
#include <iostream>
#include <vector>
#include <iomanip>
#define _USE_MATH_DEFINES
#include <cmath>
using namespace std;
class Luggage {
private:
static double totalVolume;
protected:
string type;
static int count;
static int serialGen;
int serialNum;
public:
Luggage() {
type = "Luggage";
count++;
serialNum = serialGen++;
cout<<"Generating Luggage"<<getSN()<<endl;
}
// 'static' can only be specified in the class header file not source
void static updateVolume(double inVolume) {
totalVolume += inVolume;
}
virtual
~Luggage() {
cout<<"Luggage Destructor"<<getSN()<<endl;
count--;
}
static int getCount() {
return count;
}
string getType() {
return type;
}
string getSN() {
return "(SN: " + to_string(serialNum) + ")";
}
virtual double getVolume()=0;
static double getLuggageVolume() {
return totalVolume;
};
friend ostream & operator<<(ostream & out, Luggage * lptr) {
out<<setw(10)<<left<<lptr->getType()<<": "
<<setw(6)<<right<<setprecision(1)
<<fixed<<lptr->getVolume()<<" ~ "<<lptr->getSN();
return out;
}
};
class Box : public Luggage {
private:
double length, width, height;
static int count;
static double totalVolume;
public:
Box(double l, double w, double h){
count++;
type = "Box";
length = l;
width = w;
height = h;
cout<<"Generating a Box with a Volume: "<<getVolume()<<getSN()<<endl;
updateVolume(getVolume());
}
~Box() {
count--;
updateVolume(getVolume() * -1);
cout<<"Destroying a Box with Volume: "<<getVolume()<<getSN()<<endl;
}
double getVolume() {
return length*width*height;
}
static int getCount() {
return count;
}
static double getTotalVolume() {
return totalVolume;
}
};
int main() {
// Your main program will create a container of luggage and be able to add luggage items
// and remove them as well. This container will be a vector of luggage pointers.
vector<Luggage*> container;
int input; // Main Menu User input
bool io = true;
while(io){
// Main Menu
cout << "\n----Main Menu----\n"
"1) Add Luggage to storage container\n"
"2) Remove Luggage from storage container\n"
"3) Show all luggage\n"
"4) Show total volumes\n"
"5) Exit\n\n"
"Enter: ";
Luggage *lptr;
cin >> input;
if(input == 1){
int shapeChoice;
cout<<"\nWhat Shape do you want? "<<endl
<<"1) Box"<<endl
<<"2) Cube"<<endl
<<"3) Cylinder"<<endl
<<"4) Pyramid"<<endl
<<"5) Sphere"<<endl;
cin>>shapeChoice;
switch (shapeChoice){
case 1: { // Box
double length, width, height;
cout << "\nEnter length of Box: ";
cin >> length;
cout << "Enter width of Box: ";
cin >> width;
cout << "Enter height of Box: ";
cin >> height;
lptr = new Box(length, width, height);
container.push_back(lptr);
break;
}
default:
cout << "Bad choice! Please try again later.\n";
break;
}
}else if(input == 2) {
int count = 0;
for(auto l:container) // container is vector<Luggage*>
cout << ++count << ") "<< l << endl;
cout<<"What element do you want to remove? "<<endl;
int removeChoice;
cin>>removeChoice;
removeChoice-=1;
delete (lptr);
container.erase(container.begin()+removeChoice);
}
}
delete (lptr);
This statement is wrong.
lptr is pointing at the last Box object pushed into the vector. If nothing was pushed yet, this statement causes undefined behavior since lptr is uninitialized before the 1st push. Otherwise, you are destroying the last object pushed, and then you are left with a dangling pointer, which will then fail on the next delete, causing undefined behavior again, unlese you push a new object that updates lptr beforehand.
That statement should be this instead:
delete container[removeChoice];
or safer:
delete container.at(removeChoice);
since you are not validating removeChoice beforehand.
But either way, you really shouldn't new/delete objects manually in modern C++. Use smart pointers instead, in this case std::unique_ptr<Luggage>, and let it deal with destroying objects for you.
I am trying to implement a character selection method, for a text based game and i know that it will not work the way i did it, because i am returning a refernce to an object with a lifetime limited to the scope of the method call. I have also tried to implement the method without referencing the Fighter parent class and returning a child class (Samus and Ryu) based on the players character choice, but then i would get this error: invalid abstract return type 'Fighter'.
Fighter characterSelection(int player,bool checkForBot, Fighter &fig)
{
int input;
string newName;
if(checkForBot)
{
input = (rand()%2)+1;
}
else{
cout << "Please choose your Fighter player"<<player<<": \n1. Samus\n2. Ryu\n";
input = readInput<int>();
}
if(input == 1)
{
Samus sam;
if(checkForBot)
{
cout << "Bot selected Samus!";
}
else{
cout << "Player"<<player<<" selected Samus!\nDo you wish to change your fighters name?\n1.Yes\n2.No\n";
input = readInput<int>();
if(input == 1)
{
cout << "new Name: ";
newName = readInput<string>();
changeName(newName,sam);
}
}
return sam;
}
else if(input == 2)
{
Ryu ry;
if(checkForBot)
{
cout << "Bot selected Ryu!";
}
else {
cout << "Player"<<player<<" selected Ryu!\nDo you wish to change your fighters name?\n1.Yes\n2.No\n";
input = readInput<int>();
if(input == 1)
{
cout << "new Name: ";
newName = readInput<string>();
changeName(newName,ry);
}
}
return ry;
}
}
After having chosen one character and the end of the function call, the destructor of the object is called upon, thus making the reference linked to a non-existing object.
int main()
{
int input;
string newName;
bool checkForBot;
int player=1;
while(true)
{
cout << "1. PVP \n2. PVE\n";
input = readInput<int>();
if(input == 1)
{
checkForBot = false;
//Character Selection
Fighter &fig1 = characterSelection(player,checkForBot,fig1);
player++;
Fighter &fig2 = characterSelection(player,checkForBot,fig2);
//Battle
fightPVP(fig1, fig2);
}
else if(input ==2)
{
//Character Selection
Fighter &fig1 = characterSelection(player,checkForBot,fig1);
checkForBot = true;
Fighter &bot = characterSelection(player,checkForBot,bot);
//Battle
fightPVE(fig1, bot);
}
}
return 0;
}
Is there any other way i could solve this problem, instead of referencing the parent class and then creating the child in the function call?
In this:
Fighter &fig1 = characterSelection(player,checkForBot,fig1);
you are making a reference to a local object copy returned by the function.
Returning a parent object has also the issue of object slicing; you should have that in account.
If that's not a problem, however, you can add a copy constructor to the class and just remove the reference when declaring the receiving variable:
Fighter fig1 = characterSelection(player,checkForBot,fig1);
If your object is not suited to copy, other way is to new the object in characterSelection and return a pointer (or better, shared pointer) of the base class.
In the case of your code, the compiler is right. From the function 'characterSelection' you return an instance of the abstract class Fighter which is wrong as abstract classes cannot be instantiated. You can only return a pointer or a reference (Fighter* or Figther&) to an abstract class (the pointer is generally the preferred way). From my knowledge the single way to achieve what you want using inheritance form an abstract class and a choice of a kind of Fighter at runtime is that:
#include <iostream>
class Fighter
{
public:
virtual void f() = 0;
virtual ~Fighter() {};
};
class Samus : public Fighter
{
public:
void f() { std:: cout << "Samus\n"; }
};
class Ryu : public Fighter
{
public:
void f() { std:: cout << "Ryu\n"; }
};
Fighter* getFigther()
{
int fighterCode;
std::cin >> fighterCode;
switch (fighterCode)
{
case 0: return new Samus();
case 1: return new Ryu();
default: return nullptr;
}
}
int main()
{
Fighter* myF = getFigther();
// Do what you want with the fighter
myF->f();
// Release the resources
delete myF;
}
If you want to avoid heap allocation from whatever reason, you can do that by using placement new syntax:
#include <iostream>
class Fighter
{
public:
virtual void f() = 0;
virtual ~Fighter() {};
};
class Samus : public Fighter
{
public:
void f() { std:: cout << "Samus\n"; }
};
class Ryu : public Fighter
{
public:
void f() { std:: cout << "Ryu\n"; }
};
constexpr std::size_t size()
{
constexpr std::size_t samusS = sizeof(Samus);
constexpr std::size_t ryuS = sizeof(Ryu);
return samusS < ryuS ? ryuS : samusS;
}
void getFigther(Fighter*& f)
{
int fighterCode;
std::cin >> fighterCode;
// If figtherCode is invaild you can print a message or throw an exception
switch (fighterCode)
{
case 0: new (f) Samus(); break;
case 1: new (f) Ryu(); break;
}
}
int main()
{
char space[size()];
Fighter* myF = (Fighter*) (space);
getFigther(myF);
// Do what you want with the fighter
// No delete requied
myF->f();
}
However, if you have multiple fighter classes with different sizes you will need a compile-time function to give you the maximum size of any class (representing a fighter). I don't think that approach worth the effort in your case.
I'm doing an assignment with virtual classes, I need to implement a pure virtual method which later will be implemented in an inherited class.
I solved a problem before with pure virtual methods which worked flawlessly, solving by myself the error i receive now ( error C2259: 'Playlist': cannot instantiate abstract class) - by implementing a method in an inherited class.
class Record
{
char* artist;
char* titlu;
int durata;
public:
Record()
{
artist = new char[50];
titlu = new char[50];
durata = 0;
}
void setArtist(char *s)
{
strcpy(artist, s);
}
char* getArtist()
{
return artist;
}
void setTitlu(char* s)
{
strcpy(titlu, s);
}
char* getTitlu()
{
return titlu;
}
void setDurata(int n)
{
int durata = n;
}
int getDurata()
{
return durata;
}
};
class Playlist
{
Record* p; /// "Record" is another class
public:
Playlist(int n)
{
p = new Record[n];
}
virtual void sortare(int n) = 0;
};
class PlaylistImplementation :public Playlist
{
public:
void sortare(int n)
{
if (n == 1)
{
cout << "1";
}
else if (n == 2)
{
cout << "2";
}
else
cout << "3";
}
};
Here is the main():
int main()
{
int n;
cout << "Number of tracks ?";
cin >> n;
Playlist x(n); /// I use VS 2019 and "x" has a red tilde underneath,
/// also error is at this line.
cin.ignore();
cin.get();
return 0;
}
I expect to instantiate an object from class Playlist.
You can't instantiate Playlist directly because it is abstract, so in main, instead of:
Playlist x(n);
you need
PlaylistImplementation x(n);
And you need a constructor in PlaylistImplementation like so:
PlaylistImplementation (int n) : PlayList (n) { }
Member 'p' of type Record in class Playlist is implicitly declared private. For access you need to add public member functions (e.g. to store data to a record).
A problem has come up in my application where my PrintAll function will not work correctly and only ultimately crash my application. My app is supposed to read strings from a file and insert them into an array. The problem is it is reading incorrectly and will ultimately crash my app. Here is where I think the problem lies:
int main()
{
LoadMovies();
MovieList *movies = LoadMovies();
//movies->MovieList::PrintAll();
// // test methods for the Movie and MovieList classes
//PrintAllMoviesMadeInYear(movies, 1984);
//PrintAllMoviesWithStartLetter(movies, 'B');
//PrintAllTopNMovies(movies, 5);
//delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
MovieList ml = MovieList(movies.size());
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
}
Complete Example:
/*
* File: MovieStatsProgram.cpp
* Author:
* Date:
* ===============================================================
* This is a console app to test the Movie and MovieList classes.
*
* TODO:
*
* You need to finish the implementation of the loadMovies method
* to create and initialize the MovieList object.
*
* You also need to create three static methods:
*
* PrintAllMoviesMadeInYear - it will print all the movies made in a
* given year once sort in alphabetical order and once sorted by the number
* of votes with the movie with the most number of votes printed first.
*
* PrintAllMoviesWithStartLetter - it will print all the movies started with
* a given letter sorted in alphabetical order
*
* PrintAllTopNMovies - it will display the top N movies based on the number of
* votes
*/
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <iomanip>
#include <fstream>
using namespace std;
class Movie {
public:
Movie();
Movie(string n, int y, int v, double r);
string get_name();
void set_name(string n);
int get_year();
void set_year(int y);
int get_votes();
void set_votes(int v);
double get_rating();
void set_rating(double r);
string PrintMovie();
private:
string name;
int year_made;
int votes;
double rating;
};
Movie::Movie() {
name = "null";
year_made = 0;
votes = 0;
rating = 0.0;
}
Movie::Movie(string n, int y, int v, double r) {
name = n;
year_made = y;
votes = v;
rating = r;
}
string Movie::get_name() {
return name;
}
void Movie::set_name(string n) {
name = n;
}
int Movie::get_year() {
return year_made;
}
void Movie::set_year(int y) {
year_made = y;
}
int Movie::get_votes() {
return votes;
}
void Movie::set_votes(int v) {
votes = v;
}
double Movie::get_rating() {
return rating;
}
void Movie::set_rating(double r) {
rating = r;
}
string Movie::PrintMovie() {
cout << fixed << setprecision(1) << rating << "\t\t" << votes << "\t\t" << "(" <<
year_made << ")" << "\t" << name << endl;
}
class MovieList {
public:
MovieList(int size);
~MovieList();
int Length();
bool IsFull();
void Add(Movie const& m);
string PrintAll();
private:
Movie* movies;
int last_movie_index;
int movies_size;
int movie_count = 0;
};
MovieList::MovieList(int size) {
movies_size = size;
movies = new Movie[movies_size];
last_movie_index = -1;
}
MovieList::~MovieList() {
delete [] movies;
}
int MovieList::Length() {
return last_movie_index;
}
bool MovieList::IsFull() {
return last_movie_index == movies_size;
}
void MovieList::Add(Movie const& m)
{
if (IsFull()) {
cout << "Cannot add movie, list is full" << endl;
return;
}
++last_movie_index;
movies[last_movie_index] = m;
}
string MovieList::PrintAll() {
for (int i = 0; i < last_movie_index; i++) {
movies[last_movie_index].Movie::PrintMovie();
//cout << movies[last_movie_index] << endl;
}
}
void ReadMovieFile(vector<string> &movies);
MovieList* LoadMovies();
enum MovieSortOrder
{
BY_YEAR = 0,
BY_NAME = 1,
BY_VOTES = 2
};
int main()
{
LoadMovies();
MovieList *movies = LoadMovies();
//movies->MovieList::PrintAll();
// // test methods for the Movie and MovieList classes
//PrintAllMoviesMadeInYear(movies, 1984);
//PrintAllMoviesWithStartLetter(movies, 'B');
//PrintAllTopNMovies(movies, 5);
//delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
MovieList ml = MovieList(movies.size());
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
}
void ReadMovieFile(vector<string> &movies)
{
ifstream instream;
instream.open("imdbtop250.txt");
if (instream.fail())
{
cout << "Error opening imdbtop250.txt" << endl;
exit(1);
}
while (!instream.eof())
{
string movie;
getline(instream, movie);
movies.push_back(movie);
}
instream.close();
}
When I use MovieList::PrintAll in the main function, my function just crashes, and when I put it in the LoadMovies function, it will read and add data incorrectly before crashing. The size of the list is 251 and the application will just read the same data 251 times.
You have a two part problem:
1: As Brad S stated, your function returns nothing. This is a no-no.
MovieList* LoadMovies()
{
MovieList ml = MovieList(movies.size());
// Your function returns a pointer to a MovieList, so...
return &ml;
}
So, problem #2 is that you're going to return a pointer to something you created on the stack in your function. When you try to access it outside of your function, you'll run into undefined behavior.
Option 1:
MovieList* ml = new MovieList( movies.size() );
return ml;
You now need to delete ml when you're done w/ it.
Option 2:
Change your function to return a non-pointer... then you don't have the hassle of managing the memory.
EDIT: Try this
int main()
{
// Don't need this
// LoadMovies();
MovieList *movies = LoadMovies();
// Uncommented this
delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
// CHANGE
MovieList* ml = new MovieList(movies.size());
// CHANGE
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
// CHANGE
return ml;
}
Your MovieList class has a fundamental problem. This comes to light on this line:
MovieList ml = MovieList(movies.size());
Your MovieList class has a member that is a pointer to dynamically allocated memory. Once you have this, you have to manage copying and assignment by creating a user-defined copy constructor and assignment operator.
The easiest fix for this is to use std::vector<Movie> instead of Movie * as a member variable of MovieList. Then copy-assignment comes for free and you don't need to implement further functions.
However, if you can't use std::vector for some reason, the following functions can be added:
class MovieList {
public:
//...
MovieList(const MovieList& m);
MovieList& operator=(MovieList m);
//...
};
#include <algorithm>
//...
// copy constructor
MovieList::MovieList(const MoveList& m) {
movies_size = m.size;
movie_count = m.movie.count;
last_movie_index = m.last_movie_index;
movies = new Movie[movies_size];
for (int i = 0; i < movies_size; ++i)
movies[i] = m.movies[i];
}
//...
// assignment operator
MovieList& MovieList::operator=(MoveList m) {
std::swap(m.movie_size, movie_size);
std::swap(m.last_movie_index, last_movie_index);
std::swap(m.movies, movies);
std::swap(m.movie_count, moviE_count);
return *this;
}
The easiest way to describe this to you is not to describe what these do. The best thing for you is to use your debugger and put a breakpoint in any of these functions and step through the code. When you hit the line I mentioned above, you will more than likely see that the copy constructor function is called -- then you can see it in action as to what it is doing.
The assignment operator is the function that's called when you assign an existing MovieList to another MovieList. It's implemented via the copy/swap idiom. This relies on a working copy constructor (provided above), and a destructor (which you already provided in your code). It works by creating a temporary MovieList, and swapping out the internals of the current MovieList with the temporary MovieList. There are many threads on SO as to how this works.
As to the reason why you need these functions above is that without the above functions, the line:
MovieList ml = MovieList(movies.size());
will create two MovieList objects, one temporary and one non-temporary, however the movies pointer for both will be pointing to the same memory. When the temporary is destroyed, the destructor is called, thus deleting the memory pointed to by movies. Now you have m1 pointing to memory that has gone up in smoke. Bad news when you try to use m1.
The user-defined copy and assignment functions above properly copy the object so that you get two distinct memory allocations for movies, so that when the destructor is called, the memory deleted will be unique to that object.
Again, all of this would be alleviated if you used std::vector and forego having to write copy ctor/assignment operators.
I'm still a bit stuck on another part on my assignment.
Here is what the prompt is asking:
Now you can modify the LoadMovies function to create a MovieList
object and add each of the Movie objects to it. The function
LoadMovies should return a pointer to the MovieList object. That means
you need to create the MovieList object dynamically and on the heap.
Change the main function and store the returned MovieList pointer in a
variable. To test if everything works as expected, you can use the
PrintAll function of the MovieList object.
Here is my code so far:
class MovieList {
public:
Movie* movies;
int last_movie_index;
int movies_size;
int movie_count = 0;
MovieList(int size) {
movies_size = size;
movies = new Movie[movies_size];
last_movie_index = -1;
}
~MovieList() {
delete [] movies;
}
int Length() {
return movie_count;
}
bool IsFull() {
return movie_count == movies_size;
}
void Add(Movie const& m)
{
if (IsFull())
{
cout << "Cannot add movie, list is full" << endl;
return;
}
++last_movie_index;
movies[last_movie_index] = m;
}
void PrintAll() {
for (int i = 0; i < movie_count; i++) {
movies[last_movie_index].PrintMovie();
}
}
};
void ReadMovieFile(vector<string> &movies);
void LoadMovies();
enum MovieSortOrder
{
BY_YEAR = 0,
BY_NAME = 1,
BY_VOTES = 2
};
int main()
{
LoadMovies();
// TODO:
// You need to implement the Movie and MovieList classes and
// the methods below so that the program will produce
// the output described in the assignment.
//
// Once you have implemented everything, you should be able
// to simply uncomment the code below and run the program.
MovieList *movies = LoadMovies();
// // test methods for the Movie and MovieList classes
//PrintAllMoviesMadeInYear(movies, 1984);
//PrintAllMoviesWithStartLetter(movies, 'B');
//PrintAllTopNMovies(movies, 5);
//delete movies;
return 0;
}
void LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
movie.PrintMovie();
}
}
Now where I'm stuck at is where the professor asks me to modify the LoadMovies in the prompt and turn it into a pointer. I'm drawing blanks. Also for some reason if I try to compile it says:
C:\Users\Andy\Documents\C++ Homework\MovieStatisticsProgram\MovieStatsProgram.cpp:163: error: void value not ignored as it ought to be
MovieList *movies = LoadMovies();
^
The order of your constructor is wrong
MovieList(int size) {
movies = new int[movies_size]; // movies_size hasn't been initialized yet!
movies_size = size;
last_movie_index = -1;
}
It should be
MovieList(int size)
: movies_size{size}, movies{new int[size]}, last_movie_index{0}
{}
Though as #ScottMcP-MVP noted your array should be
Movie* movie;
So your constuctor would be
MovieList(int size)
: movies_size{size}, movies{new Movie[size]}, last_movie_index{0}
{}
Some advice for getting started on the remaining functions
Length function will return how many are current used from last_movie_index.
IsFull will check if last_movie_index == movies_size - 1
Add will need to use last_movie_index to figure out what element in your array to store the movie.
PrintAll will have to iterate from [0] to [movie_count] and print out each element.
Your Add function would look something like
void MovieList::Add(Movie const& m)
{
if (IsFull())
{
std::cout << "Cannot add movie, list is full" << std::endl;
return;
}
movies[last_movie_index] = m; // assigns a copy to your array
++last_movie_index; // Increment the movie index
}