Hello idk6199,
Starting in the "main" file:
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
|
#include <iostream>
#include <limits> // <--- Added.
#include <string>
#include <vector>
#include <fstream>
//using namespace std; // <--- Best not to use.
// The most recent post that is worth reading. http://www.cplusplus.com/forum/beginner/258335/
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::ifstream;
using std::vector;
#include "Movie.h"
bool openFile(std::ifstream& movieDataFile);
void fillVector(std::ifstream& movieDataFile, vector<Movie>& newMoviesList);
void printVector(vector<Movie>&);
int main()
{
ifstream movieDataFile; // <--- Moved to here.
if(openFile(movieDataFile)) // <--- Changed.
return 1; // <--- No reason to continue.
vector<Movie> moviesList;
fillVector(movieDataFile, moviesList); // <--- Changed.
printVector(moviesList);
return 0; // <--- Not required, but makes a good break point.
}
|
Lines 1 - 17 I find this to work out the best. It may not be considered the most proper way, but it works. By placing
#include "Movie.h"
after everything else when that code is loaded into the ".cpp" file everything above it covers what is in the header file.
For the function "openFile":
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
|
bool openFile(std::ifstream& movieDataFile)
{
string fileName{ "File 2.txt" };
std::string availableFiles[]
{
"File 1.txt",
"File 2.txt",
"File 3.txt"
};
std::cout << "\n Available Files:\n";
for (std::string file : availableFiles)
std::cout << " " << file << '\n';
//cout << "\n Enter the name of your movie database(file name): ";
//std::getline(std::cin, fileName);
cout << "\n Enter the name of your movie database(file name): " << fileName; // <--- Used for testing. Comment or remove when finished.
//ifstream movieData;
movieDataFile.open(fileName);
if (!movieDataFile.is_open()) // <--- Changed.
{
cout << "Could not find database." << endl;
return true; // <--- Added.
}
else
cout << "\n Database successfully accessed!\n" << endl;
return false; // <--- Added.
}
|
And what shows up on the screen is:
Available Files:
File 1.txt
File 2.txt
File 3.txt
Enter the name of your movie database(file name): File 2.txt
Database sucessfully accessed!
|
The problem with your original code is that you are asking the user to enter a file name and expecting said user to get it right. This example is just one way you could solve the problem.
I did get a problem with the "fillVector" function:
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
|
void fillVector(std::ifstream& movieDataFile, vector<Movie>& newMoviesList)
{
char junk{}; // <--- As lastchance suggested.
string title, directorLastName, directorFirstName, starLastName, starFirstName, studio, language;
int year = 0;
double rating = 0.0;
while(getline(movieDataFile, title))
{
getline(movieDataFile, directorLastName);
getline(movieDataFile, directorFirstName);
getline(movieDataFile, starLastName);
getline(movieDataFile, starFirstName);
getline(movieDataFile, studio);
getline(movieDataFile, language);
movieDataFile >> year;
movieDataFile >> rating;
//movieDataFile >> junk; // <--- As lastchance suggested.
movieDataFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // <--- Requires header file <limits>. The more protable method.
//Movie newMovie(title, directorLastName, directorFirstName, starLastName, starFirstName, studio, year, language, rating);
newMoviesList.emplace_back
(
title,
directorLastName,
directorFirstName,
starLastName,
starFirstName,
studio,
year,
language,
rating
);
}
}
|
The while loop will serve you better than the for loop, but you still change the for loop to work similar to the while loop. This way it will not matter how little or how much is in the input file it will continue until the "eof" bit is set and the stream fails.
The problem I had reading your input file is that your file did not match the way you had your reads set up. In your original code your were reading "studio", "year", "language" and rating, but the input file was set up as "studio",
"language" , "year", and rating.
Once I rearranged the input as above it worked.
Note: when it tried to input "year" the input file was at a point to read a string which caused the stream to fail because it was expecting number to be read.
Other than adjusting how the output looks I did not have to change anything for the "printVector" function. Except for the for loop:
for (size_t i = 0; i < newMoviesList.size(); i++)
. The ".size()" function returns a "size_t", an alais for "unsigned int", which means that "i" is the same type as the returned type of the "size()" function.
For the "Movie.h" file I did this:
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
|
#ifndef MOVIE_H
#define MOVIE_H
class Movie
{
private:
string title;
string directorLastName;
string directorFirstName;
string starLastName;
string starFirstName;
string studio;
int year;
string language;
double rating;
public:
Movie();
Movie(string mTitle, string mDirectorLastName, string mDirectorFirstName, string mStarLastName, string mStarFirstName, string mStudio, int mYear, string mLanguage, double mRating);
string getTitle() { return title; }
string getDirectorLastName() { return directorLastName; }
string getDirectorFirstName() { return directorFirstName; }
string getStarLastName() { return starLastName; }
string getStarFirstName() { return starFirstName; }
string getStudio() { return studio; }
int getYear() { return year; }
string getLanguage() { return language; }
double getRating() { return rating; }
void setTitle();
//void setTitle(string mTitle){title = mTitle;}
void setDirectorFirstName();
void setDirectorLastName();
//void setDirectorLastName(string mDirectorLastName){directorLastName = mDirectorLastName;};
//void setDirectorFirstName(string mDirectorFirstName){directorFirstName = mDirectorFirstName;};
void setStarLastName();
//void setStarLastName(string mStarLastName){starLastName = mStarLastName;};
void setStarFirstName();
//void setStarFirstName(string mStarFirstName){starFirstName = mStarFirstName;};
void setStudio();
//void setStudio(string mStudio){studio = mStudio;};
void setYear();
//void setYear(int mYear){year = mYear;};
void setLanguage();
//void setLanguage(string mLanguage){language = mLanguage;};
void setRating();
//void setRating(float mRating){rating = mRating;};
};
#endif // !MOVIE_H
|
Lines 1,2 and 49 are called an include guard and something that you should get use to using.
The "private" section is OK. The use of the key word "private" is not necessary in this format because everything in a class starts is private unless you tell it differently. Leaving "private;" is OK and does not make any difference.
One thing I would suggest is
string m_title;
. I have seen the "m_" prefix in many tutorials and it helps to let you know that it is a member variable of a class. Not necessary to change here, but keep in mind for the future.
I rearranges the "public:" section To me it is easier to keep track of things. I also noticed that you originally wrote
string getTitle(){return title;};
. The (;) at the end is not needed. It is not a declaration it is a full function.
For now the section for the "set" functions are not used at this time, but I do see a use later if the program would take new input.
In the "Movie.cpp" file other than the opening it compiles, so I did not have to change anything there.
1 2 3 4 5 6 7 8 9 10 11 12
|
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
#include "Movie.h"
Movie::Movie()
|
When finished it loaded 10 records and printed 10 records to the screen.
Andy