Please Help "EXC_BAD_ACCESS(Code 2)" - c++

im writing a C++ program that reads info about books from an external text file, stores the info in an array and writes a new file with the titles and prices of each book. at compile time there is no error but when I run the program I get a bunch of memory locations that pop up on the screen and an error
"thread 1: EXC_BAD_ACCESS(Code 2)"
if it matters im using xcode on an intel mac. The code is below with a few screen shots of the problem. Thanks
The Code:
//main.cpp
include <iostream>
include <fstream>
include "Book.h"
include "textbook.h"
include "Name.h"
using namespace std;
int main()
{
string title, authorf, authorl, publisher, isbn, subject;
int pages, i = 0, j = 0;
float price, rentalp;
char code;
static int bookCount = 0, textbookCount = 0;
ifstream file1, file2;
ofstream newFile;
file1.open("/Users/TVaughn/Documents/School Stuff/Fall 2012/CS 246/In Class Programs/Book/Book/Data.txt", ios::in); //Opening the data.txt file to read from.
newFile.open("/Users/TVaughn/Documents/School Stuff/Fall 2012/CS 246/In Class Programs/Book/Book/Title.txt", ios::out); //Creating a new file to store titles & prices of all the books.
book bookList[3];
while (!file1.eof()) {
getline (file1, title, ',');
getline (file1, authorf, ',');
getline (file1, authorl, ',');
getline (file1, publisher, ',');
getline (file1, isbn, ',');
file1 >> pages;
file1.ignore();
file1 >> price;
file1.ignore();
file1 >> code;
file1.ignore(10, '\n');
book b1(title, authorf, authorl, publisher, pages, isbn, price, code);
bookList[i] = b1; //initalizing the first element of the array to b1
newFile << "Title: " << bookList[i].getTitle() << "\n" << "Price: " << bookList[i].getPrice() << "\n\n"; //storing the title and price of all the books in a new file called titles.
bookList[i].PrintBook();
i++;
bookCount++;
}
file1.close();
file2.open("/Users/TVaughn/Documents/School Stuff/Fall 2012/CS 246/In Class Programs/Book/Book/TextbookData.txt", ios::in); //Opening the TextbookData.txt file to read from.
textbook TbookList[2];
while (!file2.eof()) {
getline (file2, title, ','); //retrieving info from data.txt and storing that info into variables so the variable may be passed as arguments in my textbook object b2.
getline (file2, authorf, ',');
getline (file2, authorl, ',');
getline (file2, isbn, ',');
file2 >> pages;
file2.ignore();
file2 >> price;
file2.ignore();
getline(file2, subject, ',');
file2 >> code;
file2 >> rentalp;
file2.ignore(10, '\n');
textbook b2(title, authorf, authorl, publisher, pages, isbn, price, code, subject, rentalp);
TbookList[j] = b2; //initalizing the first element of the array to b2.
newFile << "Title: " << bookList[j].getTitle() << "\n" << "Price: " << bookList[j].getPrice() << "\n\n";
TbookList[j].PrintBook();
j++;
textbookCount++;
}
file2.close();
newFile.close();
cout << "Number of books: " << bookCount << "\nNumber of textbooks: " << textbookCount << endl;
book b3("C++ Data Structures", "Nell B.", "Dale", "Jones & Bartlett Publishers", 781, "9780763741587", 107.67, 'A'); //This line is used to test the exception handeling.
try {
b3.setPrice(price);
b3.setPages(pages);
}
catch (book::negativeNumber) {
cout << "Negative price was entered \n\n" << "End of program \n";
}
return 0;
}
//book.h
#include <iostream>
#include "Name.h"
#include <string>
using namespace std;
#ifndef BOOK_H
#define BOOK_H
class book
{
private:
string title;
Name aurthor;
string publisher;
string ISBN;
int pages;
float price;
char code;
public:
class negativeNumber{};
void setTitle(string);
void setAurthor(string f, string l);
void setPublisher(string);
void setISBN(string);
void setPages(int);
void setPrice(float);
void setCode(char);
string getTitle();
Name getAurthor();
string getPublisher();
string getISBN();
int getPages();
float getPrice();
char getCode();
void PrintBook();
book(); //default constructor
book(string, string, string, string, int, string, float, char);
~book(); //Destructor
};
#endif
//Book.cpp
#include <iostream>
#include <string>
#include "Book.h"
#include "Name.h"
using namespace std;
book::book() {
title = "Southern Charm";
Name::Name();
publisher = "Impact Publishers";
pages = 223;
ISBN = "234-232-10009045";
price = 14.99;
code = 'L';
}
book::book(string the_title, string f, string l, string the_pub, int page_num, string the_ISBN, float the_price, char the_c)
{
title = the_title;
//Name(f, l);
aurthor.setfName(f);
aurthor.setlName(l);
publisher = the_pub;
pages = page_num;
ISBN = the_ISBN;
price = the_price;
code = the_c;
}
book::~book()
{
}
void book::setTitle(string t)
{
title = t;
}
void book::setAurthor(string f, string l)
{
aurthor.setfName(f);
aurthor.setlName(l);
}
void book::setPublisher(string pub)
{
publisher = pub;
}
void book::setISBN(string ISBN_num)
{
ISBN = ISBN_num;
}
void book::setPages(int p) {
if (pages > 0)
pages = p;
else
throw negativeNumber();
}
void book::setPrice(float cost) {
if (price >= 0) //This is called exception handling.
price = cost;
else
throw negativeNumber();
}
void book::setCode(char c) {
code = c;
}
string book::getTitle() {
return title;
}
Name book::getAurthor(){
return aurthor;
}
string book::getPublisher() {
return publisher;
}
string book::getISBN(){
return ISBN;
}
int book::getPages() {
return pages;
}
float book::getPrice() {
return price;
}
char book::getCode() {
return code;
}
void book::PrintBook() {
cout << "Title: " << getTitle() << "\n" << "Aurthor: ";
getAurthor().printName();
cout << "Publisher: " << getPublisher() << "\n" << "Pages: " << getPages() << "\n" << "ISBN: " << getISBN() << "\n" << "Price: " << getPrice() << "\n" << "Code: " << getCode() << "\n \n \n";
}

Here are a few points that jumped out at me:
My mantra: Thou shalt check reading worked after thy read.
Use of std::ios_base::eof() is only good to determine why the previous read failed.
You actual problem is: what happens if there are more than 3 books? (no need to answer: I know what happens...)
Expert programmers struggle with getting long functions right. Beginners stand no chance! Split your code into digestable and coherent chunks!
Fix the problems and retry.

Related

How to extract string with comma delimiter from txt file and parse every element separete by comma delimiter into a class constructor

Source: text file stores list of account info. e.g:
10041249,Mr,Vincent,Rogan,Rogan Locksmiths Ltd,Nell,5287.000000,,491.691000,
10021250,Mrs,Adele,Cunningham,Cunningham Demolition Ltd,Dr Scott,2941.000000,,273.513000,
10051251,Mr,Rodney,Shaw,Shaw Meat Packaging Ltd,Eddie,7552.000000,,740.096000,
10001252,Mrs,Christine,Nichols,Nichols Scaffolding Ltd,Brad,6723.000000,Eddie:Brad:,672.300000,
10021253,Mr,Alexander,Marshall,Marshall Chemicals Ltd,Dr Scott,1768.000000,,173.264000,
10021254,Ms,Shirley,Hagman,On Point Sportswear Ltd,Dr Scott,52.000000,,5.200000,
....
....
....
How to extract string with comma delimiter from txt file and parse every element separate by comma delimiter into a class constructor?
I have try to use stringstream to extract data from every line. But it does not work.
The EmployeeAccount class I got is down below:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
class EmployeeAccount {
private:
//member variable
string acountNumber;
string title;
string firstname;
string lastname;
string company;
string salesperson;
double purchaseValue;
string prev_salestaff;
double commission;
public:
//overload constructor
EmployeeAccount(const string& employeeAccountInfo)
{
string str;
stringstream employeeAccountStream(employeeAccountInfo);
while (getline(employeeAccountStream, str, ','))
{
stringstream sso(str);
sso >> acountNumber;
sso >> title;
sso >> firstname;
sso >> lastname;
sso >> company;
sso >> salesperson;
sso >> purchaseValue;
sso >> prev_salestaff;
sso >> commission;
}
}
//Access methods
string getAccountNumber() { return acountNumber; };
string getTitle() { return title; };
string getFirstname() { return firstname; };
string getLastname() { return lastname; };
string getCompany() { return company; };
double getPurchaseValue() { return purchaseValue; };
string getPrev_salesstaff() { return prev_salestaff; };
double getCommission() { return commission; };
string getAccountDetail() { return acountNumber + " " + title + " " + firstname + " " + lastname + " " + company;};
//Destructor
~EmployeeAccount() {};
};
The testing code is this:
cout << testEmployee.getAccountDetail() << endl;
cout << testEmployee.getAccountNumber() << endl;
cout << testEmployee.getTitle() << endl;
cout << testEmployee.getFirstname() << endl;
cout << testEmployee.getLastname() << endl;
cout << testEmployee.getCompany() << endl;
cout << testEmployee.getPurchaseValue() << endl;
cout << testEmployee.getPrev_salesstaff() << endl;
cout << testEmployee.getCommission() << endl;
}
Parsing CSV file is an old topic. You will find at least 100 answers with code examples here on stackoverflow. Very often you will find a solution with the function std::getline. Please read the documentation here. It can read characters from a std::ifstream until or up to a delimiter (a comma , in our case), then store the result, without the comma, in a string and discard the comma from the stream. So, throwing that away. The characters will be stored in a std::string. If numbers or other types are needed, we need to convert the string to the other type, using the appropriate function.
Example: We have a string consisting of characters ‘1’, ‘2’ and ‘3’, so, “123”. The quotes indicate the string type. If we want to convert this string into an integer, we can use for example the function std::stoi.
In your case, you have 2 double values. So, we would split the input of the file into strings and then convert the 2 strings with the double values in it, using the function std::stod.
What you need to know additionally is, that often a 2 step approach is used. This is done to prevent potential problems arising from extracting all the string parts from one csv line. So,
we first read a complete line,
then put that line into a std::istringstream, and finally
read input and split the CSV from there.
Then, the rest is simple. Just use std::getline to al the data that you need.
Last but not least, to read the file, we will simply open it, read line by line, create an “EmployeeAccount” and push that into a std::vector
At the end we do some debug output.
Please see below one of may potential implementation proposals:
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
class EmployeeAccount {
private:
//member variable
std::string acountNumber;
std::string title;
std::string firstname;
std::string lastname;
std::string company;
std::string salesperson;
double purchaseValue;
std::string prev_salestaff;
double commission;
public:
//overload constructor
EmployeeAccount(const std::string& employeeAccountInfo)
{
std::istringstream employeeAccountStream(employeeAccountInfo);
std::getline(employeeAccountStream, acountNumber, ',');
std::getline(employeeAccountStream, title, ',');
std::getline(employeeAccountStream, firstname, ',');
std::getline(employeeAccountStream, lastname, ',');
std::getline(employeeAccountStream, company, ',');
std::getline(employeeAccountStream, salesperson, ',');
std::string temp;
std::getline(employeeAccountStream, temp, ',');
purchaseValue = std::stod(temp);
std::getline(employeeAccountStream, prev_salestaff, ',');
std::getline(employeeAccountStream, temp, ',');
commission = std::stod(temp);
}
//Access methods
std::string getAccountNumber() const { return acountNumber; };
std::string getTitle() const { return title; };
std::string getFirstname() const { return firstname; };
std::string getLastname() const { return lastname; };
std::string getCompany() const { return company; };
double getPurchaseValue() const { return purchaseValue; };
std::string getPrev_salesstaff() const { return prev_salestaff; };
double getCommission() const { return commission; };
std::string getAccountDetail() const { return acountNumber + " " + title + " " + firstname + " " + lastname + " " + company;};
//Destructor
~EmployeeAccount() {};
};
int main() {
std::ifstream ifs{ "accounts.txt" };
if (ifs) {
// Here we will store all accounts
std::vector<EmployeeAccount> accounts{};
// Read the file line by line
std::string line{};
while (std::getline(ifs, line)) {
// Create one account by splitting the input line
EmployeeAccount account(line);
// Add the new accounts to the vector of accounts
accounts.push_back(account);
}
// Debug output. For all accounts that we read, output all data
for (const EmployeeAccount& account : accounts) {
std::cout << "\n--------------------------\n"
<< account.getAccountDetail() << '\n'
<< account.getAccountNumber() << '\n'
<< account.getTitle() << '\n'
<< account.getFirstname() << '\n'
<< account.getLastname() << '\n'
<< account.getCompany() << '\n'
<< account.getPurchaseValue() << '\n'
<< account.getPrev_salesstaff() << '\n'
<< account.getCommission() << '\n';
}
}
else
std::cerr << "\n*** Error: Could not open source file\n\n";
}

Printing a text file which is stored line by line

I trying to write a function which searches for an ID and prints the book name and author name. I have been able to match the ID, however not able to properly print the book and author name. Text file is stored as such:
ID
book name
author name
Following is the code for my search function:
void searching() {
string search, id, name;
ifstream myfile("books.txt");
bool found = false;
string line;
cout << "\nEnter ID to search : ";
cin >> search;
int srchlen = search.length();
if(myfile.is_open()) {
while(getline(myfile, line)) {
id = line.substr(0, srchlen);
if(id == search) {
found = true;
break;
} else {
found = false;
}
}
if(found == true) {
name = line;
cout << "ID\tNAME\tAUTHOR\n";
cout << name;
} else {
cout << "ID doesnt exist";
}
}
}
Here is how the text file looks like (there is a blank line between each book):
98
crime and punishment
Dostoevsky
70
The Da Vinci Code
Dan Brown
So there's a logical flaw in your code that makes it harder to do what you want. The book data is stored on three separate lines, but your code reads one line at a time. Logically you should be reading three lines at a time. By doing this you'll have all the information available for one book at the same time.
Like this
string id, title, author;
while (getline(myfile, id) && getline(myfile, title) && getline(myfile, author)) {
string blank;
getline(myfile, blank); // skip the blank line between books
id = id.substr(0, srchlen);
if (id == search) {
found = true;
break;
} else {
found = false;
}
}
if (found == true) {
cout << "ID\tNAME\tAUTHOR\n";
cout << id << ' ' << title << ' ' << author << '\n';;
} else {
cout << "ID doesnt exist";
}
Note that reading the blank line is not part of the while condition. We don't want not to consider a book just because it wasn't followed by a blank line. This might happen at the end of the file for example.
To make it easier to deal with the data, I recommend putting the information about a book into a class (struct) and to add operators for reading/writing one book at a time from/to an istream/ostream.
#include <algorithm>
#include <fstream>
#include <iostream>
#include <limits>
#include <string>
struct Book {
std::string id;
std::string title;
std::string author;
};
// operator for reading one book title from any istream
std::istream& operator>>(std::istream& is, Book& b) {
std::getline(is, b.id);
std::getline(is, b.title);
std::getline(is, b.author);
// ignore the blank line between books in the file:
is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return is;
}
// operator for writing one book title to any ostream
std::ostream& operator<<(std::ostream& os, const Book& b) {
return os << b.id << '\n' << b.title << '\n' << b.author << "\n\n";
}
int main() {
std::string search;
std::cout << "\nEnter ID to search : ";
std::cin >> search;
if(std::ifstream myfile("books.txt"); myfile) {
Book book;
// read one book at a time from the stream using the added
// operator>>
while(myfile >> book) {
if(book.id == search) {
// book found, write it to cout using the added
// operator<<
std::cout << book;
break;
}
}
}
}
By taking some advantages of C++ such as vector, you can make the code easier:
#include <iostream>
#include <vector>
#include <fstream>
const char *fileName = "books.txt";
// structure of the file
struct book {
int ID;
std::string author;
std::string bookName;
};
int main(void) {
std::ifstream file(fileName); // to read the file
std::vector<book> vec; // to find the content required
int ID; // the ID to find
book temp; // temporary 'book' to insert in vector
bool found = false;
// if the file was unable to open
if (!file.is_open()) {
std::cout << "Unable to open the file." << std::endl;
return -1;
}
// getting the content of the file
while (file >> temp.ID >> temp.bookName >> temp.author)
vec.push_back(temp);
std::cout << "Enter the ID to find: ";
std::cin >> ID;
// matching the IDs
for (size_t i = 0, len = vec.size(); i < len; i++)
// prints when ID asked to show is present in the file
if (vec[i].ID == ID) {
std::cout << "ID: " << vec[i].ID << " | Author: "
<< vec[i].author << " | Name: " << vec[i].bookName;
found = true;
break;
}
if (!found)
std::cout << "The ID does not exist." << std::endl;
return 0;
}
Supposing the books.txt contains:
// FORMAT: ID _ Book _ Author
10 BookABC John
20 BookXYZ Ben
30 CodingBook Rock
Then the output would be something like:
Enter the ID to find: 30
ID: 30 | Author: Rock | Name: CodingBook

How to store lines from a file as a variable

I'd like to show the employee number name, occupation, and department of employees from a text file called organisation.txt, and save them in the variables declared in the class OrganisationRecord.
How can I do that?
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#define ORGANISATIONALRECORDSFILE "organisation.txt"
#define HRRECORDSFILE "HR_records.txt"
#define PAYROLLRECORDSFILE "payroll_records.txt"
using namespace std;
class OrganisationRecord
{
private:
public:
string name;
string occupation;
string department;
};
class HRRecord
{
private:
public:
string address;
string phonenumber;
string ninumber;
};
class PayrollRecord
{
private:
public:
string ninumber;
double salary;
};
class PayrollProcessing
{
private:
ifstream inputfile;
ofstream outputfile;
vector<OrganisationRecord> OrganisationRecords;
vector<HRRecord> HRRecords;
vector<PayrollRecord> PayrollRecords;
public:
void loadOrganisationRecords(string filename);
void loadHRRecords(string filename);
void loadPayrollRecords(string filename);
void displayEmployeeOfSalaryGTE(double salary);
//GTE = greater than or equal to
};
void PayrollProcessing::loadOrganisationRecords(string filename)
{
inputfile.open(ORGANISATIONALRECORDSFILE);
if (!inputfile)
{
cout << "the organisation records file does not exist" << endl;
return;
}
OrganisationRecord _organisationrecord;
int employeenumber;
while (inputfile >> employeenumber)
{
while (inputfile >> _organisationrecord.name)
{
cout << _organisationrecord.name;
cout << _organisationrecord.occupation;
cout << _organisationrecord.department <<endl;
}
OrganisationRecords.push_back(_organisationrecord);
}
}
int main(void)
{
PayrollProcessing database1;
database1.loadOrganisationRecords(ORGANISATIONALRECORDSFILE);
return 0;
}
organisation.txt
0001
Stephen Jones
Sales Clerk
Sales
0002
John Smith
Programmer
OS Development
0003
Fred Blogs
Project Manager
Outsourcing
When you use inputfile >> _organisationrecord.name it stops at the first whitespace character. Hence, only Stephen will be read and stored in organisationrecord.name.
You need to change your strategy a bit.
Read the contents of the file line by line. Stop when there are no more lines left.
Process each line as you seem fit.
Here's one way to deal with the input.
std::string line;
while ( std::getline(inputfile, line) )
{
// Extract the employeenumber from the line
std::istringstream str(line);
if ( !(str >> employeenumber) )
{
// Problem reading the employeenumber.
// Stop reading.
break;
}
if (!std::getline(inputfile, line) )
{
// Problem reading the next line.
// Stop reading.
break;
}
_organisationrecord.name = line;
if (!std::getline(inputfile, line) )
{
// Problem reading the next line.
// Stop reading.
break;
}
_organisationrecord.occupation = line;
if (!std::getline(inputfile, line) )
{
// Problem reading the next line.
// Stop reading.
break;
}
_organisationrecord.department = line;
std::cout << _organisationrecord.employeenumber << std::endl;
std::cout << _organisationrecord.name << std::endl;
std::cout << _organisationrecord.occupation << std::endl;
std::cout << _organisationrecord.department << endl;
OrganisationRecords.push_back(_organisationrecord);
}

C++ Validate Emails Via Substrings

I'm trying to take the profile info(username, email, etc.) from one directory and put it in another. I've been debugging the code for this program, and while there are no errors, the program won't run, saying that the program "has stopped working". I have already looked on this website and others for any possible answers, and found none.
#include <string>
#include <cstring>
#include <iostream>
#include <istream>
#include <ostream>
#include <fstream>
#include <iomanip>
#include <filesystem>
using namespace std;
class path{
public:
string parent_directory;
string root_directory;
};
class Data{
public:
string userName;
string nickName;
string fName;
string arena_FName;
string lName;
string arena_LName;
string email;
string arenaEmail;
friend std::istream& operator>>(std::istream& input, Data& d);
};
std::istream& operator>>(std::istream& input, Data& d){
std::getline(input, d.userName);
std::getline(input, d.nickName);
//...
std::getline(input, d.arenaEmail);
return input;
}
int main(){
ifstream myfile("myfunk.txt", ios::in);
ofstream arena("arena.txt");
myfile.open("myfunk.txt", ios::in);
if(myfile){
cout << "Input file open." << endl;
}
arena.open("arena.txt", ios::out | ios::app);
if(arena){
cout << "Output file open." << endl;
}
cout << "file opening test: success" << endl;
int x = 0;
int y = 4101; //Total number of users in the directory.
int z = 0; //For inputting the required lines of info for each profile.
int profile = 0;
bool valid = false;
string role;
//string arenaRole;
bool post = false;
string line;
string p = "This PC/..."; //Path to the folder of the individual pictures.
//myVar.save("...");
string p = "...";
path path1;
path root_directory;
path parent_directory;
//bool is_directory(const std::filesystem::path& p, std::error_code& ec) noexcept; //Checks if current location is a directory.
//bool postPic;
const unsigned int MAXIMUM_DATA = 4100u;
Data database[MAXIMUM_DATA];
cout << "All variables but the filesystem have been accepted! Please install this program on the network." << endl;
while(x < y){
cout << "Primary loop functioning" << endl;
if(post = true){
getline(myfile, line); //Grab and read next line.
myfile >> line;
line = userName[x];
arena << "Username: " << userName[x] << "\n";
z++;
getline(myfile, line);
myfile >> line;
line = role[x];
arena << "Role: " << role[x] << "\n";
z++;
getline(myfile, line);
line = nickName[x];
myfile >> nickName[x];
arena << "nickname: " << nickName[x] << "\n";
z++;
getline(myfile, line);
line = fName[x];
myfile >> fName;
arena << "First Name: " << fName[x] << "\n";
z++;
getline(myfile, line);
line = lName[x];
myfile >> lName;
arena << "Last Name: " << lName[x] << "\n";
z++;
getline(myfile, line);
myfile >> line;
line = email[x];
arena << "Email: " << email[x] << "\n";
getline(myfile, line);
z = 0; //Next profile...
}
int data;
while(myfile >> data){
if(nickName[x] = NULL){
myfile >> "<Error> Some required information is missing! Contact user! </Error> /n";
valid = false;
post = false;
x++;
}
if(email[x] != NULL){
std::string str("#");
std::string str2(".com");
std::string str3(".net");
std::string str4(".edu");
if(std::size_t found = email[x].find(str) & (std::size_t found = email[x].find(str2) || std::size_t found = email[x].find(str3) || std::size_t found = email[x].find(str4)){
valid = true;
if(valid = true){
post = true;
}
}
else{
valid = false;
post = false;
x++;
}
}
}
}
}
}
x++;
}
//x++;
myfile.close(); //Closes the file in the directory.
arena.close(); //Closes the file in Arena.
return 0;
}
Let's rework your code.
First, let's create a data structure for the data:
class Data
{
public:
string userName;
string nickName;
string fName;
string arena_FName;
string lName;
string arena_LName;
string email;
string arenaEmail;
};
If you need an array for the data, it would be declared as:
const unsigned int MAXIMUM_DATA = 4100u;
Data database[MAXIMUM_DATA];
Next, let's overload the extraction operator>> to make reading easier:
class Data
{
public:
//...
friend std::istream& operator>>(std::istream& input, Data& d);
};
std::istream& operator>>(std::istream& input, Data& d)
{
std::getline(input, d.userName);
std::getline(input, d.nickName);
//...
std::getline(input, d.arenaEmail);
return input;
}
This simplifies your input loop to:
std::vector<Data> database;
Data d;
while (my_file >> d)
{
database.push_back(d);
}
You can query the amount of data read in by using the std::vector::size() method, i.e. database.size().
Also, you don't need a separate structure for a file path. A simple std::string will suffice. I recommend using forward slash, '/', because it is recognized by both Windows and *nix operating systems and won't be interpreted as an escape character.

File to Array to Struct

I'm working on this program that is to help manage a DVD rental store. What I have to do is take a text that contains info about DVD etc:
Mean girls; comedy; PG; 2009; Regina George; 12.07.2015;
The Conjuring; Horror; R; 2013; Sara Johnson; 16.05.2016;
Pokemon 2000; Kids; G; 2000; Ash Katchem; 15.04.2016;
etc..
And then takes this information and then reads it into an array and from there the array is read into the struct and then displayed in proper order like so:
Name: Mean Girls
Genre: Comedy
Rating: PG
etc...
This is my code so far:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
struct dvd{
string name;
string genre;
string rating;
string released;
string renter;
string rentday;
void print();
bool read(ifstream & file);
};
void dvd::print(){
cout <<"Title: " << name << endl;
cout <<"Genre: " << genre << endl;
cout << "Rating: " << rating << endl;
cout << "Release date: " << released << endl;
cout << "Name of renter: " << renter << endl;
cout << "Date rented: " << rentday << endl;
}
bool dvd::read(ifstream & file)
{
getline(file, name, ';');
getline(file, genre, ';');
getline(file, rating,';');
getline(file, released, ';');
getline(file, renter, ';');
getline(file, rentday, ';');
return file.good();
}
int main() {
vector<dvd> dvds;
dvd dvd1;
ifstream file("DVD.txt");
if(! file.is_open()){
cout << "Failed to find input file" << endl;
return 1;
}
while(dvd1.read(file))
{ dvds.push_back(dvd1);
}
dvd1.print();
return 0;
}
So what I would like to do is have read the text file into the Array and from there read the Array into the struct. So instead of the text file reading into the vector I need it to read into the array and from there read the first line of the array (dvdArray[1]) into struct dvd and then print out that information using print function and then loop that until dvdArray[10] is read into struct dvd!
Thank you so much for your help! :)
Change
bool dvd::read(ifstream & file)
to
bool dvd::read(istream & file)
No other changes to its contents are required.
Then, take each line and put it into a std::istringstream, then pass it to dvd::read.
You should be able to figure out the rest on your own.
For simple reading from and writing to file, I would suggest overload << and >> for your struct class, in order to make the code easy to serialize and de-serialize in a readable fashion.
friend std::ostream& operator<< (std::ostream& stream, const dvd& dvdObj)
{
// your output stuff
// stream <<"Title: " << dvdObj.name << endl;
// ...
return stream;
}
friend std::istream& operator>> (std::istream& stream, dvd& dvdObj)
{
// your output stuff
// getline(stream, dvdObj.name, ';');
// ...
return stream;
}
Then,
// look for std::copy for reading directly into vector ... else
while( file >> dvd1 )
{
dvds.push_back(dvd1);
}
And,
for( const auto& dvd1: dvds )
{
std::cout << dvd1 ;
}