I am unsure about why I am getting this error message when I hover over purchaseArray in my string Customer::save() method in the customer.cpp file:
identifier is undefined
And this error message when I hover over getline in the void Customer::parse(string line) method in the customer.cpp file:
no instance of overloaded function "getline" matches the argument list argument types are: (std::stringstream, int, char)
Code in the Customer.cpp file:
#include "Customer.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include<utility>
using namespace std;
//default constructor
Customer::Customer() {
}
//Full constructor
Customer::Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type)
{
this->customerID = customerID;
this->title = title;
this->name = name;
this->numOfPurchases = numOfPurchases;
purchases = new int[3];
purchases[0] = purchase1;
purchases[1] = purchase2;
purchases[2] = purchase3;
this->type = type;
}
Customer::Customer(const Customer& source) //copy constructor
{
cout << "copy constructor called" << endl;
this->customerID = source.customerID;
this->title = source.title;
this->name = source.name;
this->numOfPurchases = source.numOfPurchases;
this->purchases = new int[3];
purchases[0] = source.purchases[0];
purchases[1] = source.purchases[1];
purchases[2] = source.purchases[2];
this->type = source.type;
}
//overloaded assignment operator=
Customer& Customer::operator= (Customer& otherCustomer)
{
cout << "Overloaded assignment operator= called" << endl;
//self-assignment guard
if (this == &otherCustomer)
return *this; //refernce to the same object
// copy data from the source (rhs) to this object (the destination)
name = otherCustomer.name;
//must make a new scores object to store a copy of the other student
if (purchases != nullptr)
delete[] purchases;
purchases = new int[3];
for (int i = 0; i < 3; i++) {
purchases[i] = otherCustomer.purchases[i];
}
//return this existing object so we can chain this operator
return *this;
}
string Customer::save()
{
stringstream out;
out << this->customerID << ";";
out << this->title << ";";
out << this->name << ";";
out << this->numOfPurchases << ";";
int* purchases = 0;
purchases = purchases | (purchaseArray[0] << 24);
purchases = purchases | (purchaseArray[1] << 16);
purchases = purchases | (purchaseArray[2] << 8);
out << this->type << ";";
out.flush();
return out.str();
}
void Customer::parse(string line)
{
stringstream in(line);
string customerIDLine;
getline(in, customerIDLine, ';');
customerID = stoi(customerIDLine);
getline(in, title, ';');
getline(in, name, ';');
int numOfPurchases;
getline(in, numOfPurchases, ';');
int s = stoi(numOfPurchases);
purchasesArray[0] = (s & (255 << 16)) >> 16;
purchasesArray[1] = (s & (255 << 8)) >> 8;
purchasesArray[2] = s & 255;
getline(in, type, ';');
}
Customer::~Customer() {
cout << "Destructor ~Customer called" << endl;
delete[] purchases;
}
// Overloaded insertion operator (Outputs Character object data as an output stream)
// Defined in header file as a "friend" function, as it is not a member function
//
ostream& operator<<(ostream& out, Customer& customer)
{
cout << "Customer details ( output by insertion operator<< )" << endl;
cout << "Customer ID: " << customer.customerID << endl;
cout << "Title: " << customer.title << endl;
cout << "Name: " << customer.name << endl;
cout << "Number of purchases: " << customer.numOfPurchases << endl;
cout << "Purchases: ";
for (int i = 0; i < 3; i++)
{
if (i > 0) cout << ",";
cout << customer.purchases[i];
}
cout << "Type: " << customer.type << endl;
return out;
}
istream& operator>> (istream& in, Customer& customer)
{
cout << "Enter Customer details ( using the extraction operator>> )" << endl;
cout << "Enter Customer ID: " << endl;
cin >> customer.customerID;
cout << "Enter Title: " << endl;
getline(cin, customer.title);
cout << "Enter Name: " << endl;
getline(cin, customer.name);
cout << "Enter Number of Purchases: ";
cin >> customer.numOfPurchases;
cout << "Enter Purchases: ";
cin >> customer.purchases[0];
cin >> customer.purchases[1];
cin >> customer.purchases[2];
cout << "Enter Type";
getline(cin, customer.type);
cout << endl;
return in;
}
int Customer::getCustomerID()
{
return customerID;
}
string Customer::getTitle()
{
return title;
}
string Customer::getName()
{
return name;
}
int Customer::getNumOfPurchases()
{
return numOfPurchases;
}
int* Customer::getPurchases()
{
return purchases;
}
string Customer::getType()
{
return type;
}
void Customer::setCustomerID(int customerID)
{
if (customerID < 1) {
cout << "Customer ID has to be equal to 1 or more" << endl; //Changed all the "throw invalid_argument" messages to cout as they were causing an issue with my main.cpp file and an abort message kept appearing every time I ran my main.cpp file.
}
this->customerID = customerID;
}
void Customer::setTitle(string title)
{
if (title.length() < 2) {
cout << "Title has to be more than or equal to 2 characters" << endl;
}
this->title = title;
}
void Customer::setName(string name)
{
if (name.length() < 4) {
cout << "Length of name should be more than or equal to 4 characters" << endl;
}
this->name = name;
}
//Got help ith this on stack overflow as I was using "&&" instead of using "||" for the if statement
void Customer::setNumOfPurchases(int numOfPurchases)
{
if(numOfPurchases <0 || numOfPurchases > 10000){
cout << "Number of purchases should be between 0 to 10000" << endl;
}
this->numOfPurchases = numOfPurchases;
}
void Customer::setPurchases(int purchase1, int purchase2, int purchase3)
{
if (purchase1 < 0 || purchase2 < 0 || purchase3 < 0) {
cout << "Purchases must be more than or equal to zero" << endl;
}
}
//Got help from stack overflow on comparing strings as I originally didnt use "type.compare"
void Customer::setType(string type) {
if (type.compare("New") !=0 || type.compare("Either") !=0) {
cout << "Type of purchase has to be New or Either" << endl;
}
}
Code in the Customer.h file:
#pragma once
#include<iostream>
using namespace std;
#include<string>
class Customer
{
private:
int customerID;
string title;
string name;
int numOfPurchases;
int* purchases;
string type;
public:
Customer(); // default constructor
Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type);
//copy overload assignment
Customer& operator=(Customer& otherCustomer);
Customer(const Customer& source);
string save();
void parse(string line);
~Customer(); //destructor
//Getters and Setters
void setCustomerID(int customerID);
void setTitle(string title);
void setName(string name);
void setNumOfPurchases(int numOfPurchases);
void setPurchases(int purchase1, int purchase2, int purchase3);
void setType(string type);
int getCustomerID();
string getTitle();
string getName();
int getNumOfPurchases();
int* getPurchases();
string getType();
void printCustomer() {
cout << customerID << "," << title << "," << name << "," << numOfPurchases << "," << purchases << "," << type << endl;
}
friend std::ostream& operator<<(std::ostream& out, Customer& customer); // overloaded operator<<
friend istream& operator>> (istream& in, Customer& customer); // overloaded operator >>
};
Code from the Main.cpp file:
// Repeat_Assessment_C++_AislingSmith.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include "Customer.h"
using namespace std;
void OutputFileStream();
void parseLine(const string& str);
void InputFileStream();
void save(vector<Customer> customers);
void load(vector<Customer>& customers);
void addCustomer(vector<Customer>& vect);
//void printActions();
void OutputFileStream()
{
cout << "Creating and writing to file: Customer.txt" << endl;
ofstream outStream("customers.txt"); // write mode (overwrites existing data)
if (outStream.good())
{
int customerID = 150033;
outStream << "This is a line of text.\n";
outStream << "This is another line of text.\n";
outStream << "This is a line of text.\n";
int numOfPurchases = 4;
int purchases = 0;
outStream << customerID << "Mr" << "Jack" << "New" << numOfPurchases << purchases << endl;
outStream.close(); // close file
cout << "File written.\n" << endl;
}
else
cout << "Unable to open file";
}
void parseLine(const string& str) {
stringstream strStream(str); //create string stream from the string
// int customerID;
string title;
string name;
string type;
//int numOfPurchases;
//int purchases;
string s;
int customerID = 150033;
getline(strStream, s, ';');
customerID = stoi(s);
getline(strStream, title, ';');
getline(strStream, name, ';');
getline(strStream, type, ';');
int numOfPurchases = 4;
getline(strStream, s, ';');
numOfPurchases = stoi(s);
int purchases = 0;
getline(strStream, s, ';');
purchases = stoi(s);
int* purchasesArray = new int[3];
purchasesArray[0] = (purchases & (255 << 16)) >> 16;
purchasesArray[1] = (purchases & (255 << 8)) >> 8;
purchasesArray[2] = purchases & 255;
for (int i = 0; i < 3; i++)
{
int purchasesArray[3];
}
cout << " CustomerID: " << customerID << "Title:" << title << " Name: " << name << " Type:" << type << " Number of Purchases: " << numOfPurchases << "Purchases: " << purchases << endl;
}
void InputFileStream() {
cout << "Reading from a semi-colon delimited txt file" << endl;
string line;
ifstream inStream("customers.txt"); //opens file as an input file stream
if (inStream.good()) //if the file is opened successfully and not empty
{
while (getline(inStream, line)) //reads line until false return
{
parseLine(line);
}
inStream.close();
}
else
cout << "unable to open file or the file is empty!";
}
void save(vector<Customer> customers)
{
ofstream out("customers.txt");
if(out)
{
for (Customer& c : customers)
{
out << c.save();
}
out.flush();
out.close();
}
else
{
cout << "Error Writing to File" << endl;
}
}
void load(vector<Customer>& customers)
{
ifstream in("customers.txt");
if (in) {
string line;
while (!in.eof())
{
getline(in, line);
if (line != "")
{
Customer c;
c.parse(line);
customers.push_back(c);
}
}
}
}
void addCustomer(vector<Customer>& customers) {
Customer customer;
cin >> customer;
customers.push_back(customer);
}
int main()
{
InputFileStream();
vector<Customer> customers;
Customer c;
Customer cust1;
cust1.setCustomerID(150032);
cust1.setTitle("Mr");
cust1.setName("Joey");
cust1.setNumOfPurchases(3);
cust1.setPurchases(366, 352, 334);
cust1.setType("New");
cout << cust1.getCustomerID() << endl;
cout << cust1.getTitle() << endl;
cout << cust1.getName() << endl;
cout << cust1.getNumOfPurchases() << endl;
cout << cust1.getPurchases() << endl;
cout << cust1.getType() << endl;
return 0;
}
First Problem
The first error is pretty clear, purchaseArray is nowhere defined (at least not in the code you show here) and you probably meant just purchases or this->purchases? Allthough I got no clue what you tried to achieve with the int *purchases there.
Second Problem
The second one occurs, because the way you try to read an integer from a stream is flawed.
It's about this piece of code from Customer::parse
int numOfPurchases; // declare int
getline(in, numOfPurchases, ';'); // error, second parameter must be std::string!
int s = stoi(numOfPurchases); // numOfPurchases is already an int
You probably wanted this:
std::string numOfPurchasesBuf; // temporary buffer
getline(in, numOfPurchasesBuf, ';'); // read data to string
int s = stoi(numOfPurchasesBuf); // convert to int
and since all of those lines read some member variable you probably want to set this one as well:
this->numOfPurchases = s;
Related
The code compiles it does not read staff.txt. Not sure how to fix in the code. the error must be in reading the staff.txt of the code. Does anyone have an idea? output is in the image provided. Background on the question:
You are tasked to create 2 ADTs: customers and staff. Each customer will have a first and last name, an indication if the customer is enrolled in the “preferred” program, the car they are driving, and the amount of money owed to the company. On the other hand, each staff member will have a first and last name, the car they are driving, and their salary. In a real-world problem, there would obviously be more records associated with each staff member and customer.
ODU rentals would like you to automatically process txt files and print the information to the console screen. When you perform this process, ensure that your member variables are private. In addition, be sure to use getter and setter functions to manipulate and print your data. You may print your data in any format as long as it is organized. An example of correct output can be seen below.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cstdlib>
using namespace std;
class Customer {
string fname;
string lname;
int enroll;
string car;
float amount;
public:
//Defining the customer ADT
Customer();
void setFirstName(string fnm);
void setLastName(string lnm);
void setEnroll(int e);
void setCarName(string cnm);
void setAmount(float amt);
string getFirstName();
string getLastName();
int getEnroll();
string getCarName();
float getAmount();
void printData();
};
Customer::Customer() {
fname = lname = car = "";
enroll = 0;
amount = 0;
}
void Customer::setFirstName(string fnm) {
fname = fnm;
}
void Customer::setLastName(string lnm) {
lname = lnm;
}
void Customer::setEnroll(int e) {
enroll = e;
}
void Customer::setCarName(string cnm) {
car = cnm;
}
void Customer::setAmount(float amt) {
amount = amt;
}
string Customer::getFirstName() {
return(fname);
}
string Customer::getLastName() {
return(lname);
}
int Customer::getEnroll() {
return(enroll);
}
string Customer::getCarName() {
return(car);
}
float Customer::getAmount() {
return(amount);
}
void Customer:: printData() {
cout << left << setw(25) << getFirstName()+" "+getLastName() << left <<setw(15) << getEnroll();
cout << left << setw(15) << getCarName() << left << setw(15) << fixed << setprecision(2) << getAmount() << endl;
}
class Staff {
string fname;
string lname;
string car;
float salary;
public:
//Defining staff ADT
Staff();
void setFirstName(string fnm);
void setLastName(string lnm);
void setCarName(string cnm);
void setSalary(float sal);
string getFirstName();
string getLastName();
string getCarName();
float getSalary();
void printData();
};
Staff::Staff() {
fname = lname = car = "";
salary = 0;
}
void Staff::setFirstName(string fnm) {
fname = fnm;
}
void Staff:: setLastName(string lnm) {
lname = lnm;
}
void Staff::setCarName(string cnm) {
car = cnm;
}
void Staff::setSalary(float sal) {
salary = sal;
}
string Staff::getFirstName() {
return(fname);
}
string Staff::getLastName() {
return(lname);
}
string Staff::getCarName() {
return(car);
}
float Staff::getSalary() {
return(salary);
}
void Staff:: printData() {
cout << left << setw(25) << getFirstName()+" "+getLastName() << left << setw(15);
cout << getCarName() << left << setw(15) << fixed << setprecision(2) << getSalary() <<endl;
}
//Main function
//Read txt files
int main() {
string fnm, lnm, carnm;
float amt, sal;
int e, i=0, recno;
ifstream fstaff("staff.txt");
if(!fstaff) {
cout << "File can not be opened" << endl;
exit(1);
}
fstaff >> recno;
Staff s[recno];
cout << left<<setw(25) << "Name" << left << setw(15) << "Car" << left << setw(15) << "Salary" <<endl;
cout << "____________________________________________________________________________" << endl;
for(i=0; i<recno; i++) {
fstaff>>fnm>>lnm>>carnm>>sal;
s[i].setFirstName(fnm);
s[i].setLastName(lnm);
s[i].setCarName(carnm);
s[i].setSalary(sal);
s[i].printData();
}
fstaff.close();
ifstream fcust("customers.txt");
if(!fcust) {
cout << "File can not be opened"<<endl;
exit(1);
}
fcust >> recno;
Customer c[recno];
cout << endl << endl;
cout << left << setw(25) << "Name" << left << setw(15) << "Preferred" << left << setw(15) << "Car" << left << setw(15) << "Bill" << endl;
cout <<"____________________________________________________________________________"<<endl;
for(i=0; i<recno; i++) {
fcust >> fnm >> lnm >> e >> carnm >>amt;
c[i].setFirstName(fnm);
c[i].setLastName(lnm);
c[i].setEnroll(e);
c[i].setCarName(carnm);
c[i].setAmount(amt);
c[i].printData();
}
fcust.close();
return 1;
}
Code Output
I have been trying to separate a number stored in a .txt file as "365048" to "36, 50, 48" when it has been read into my program using a dynamic array and i'm not sure where I am going wrong. The variable i'm having the issue with is int* purchases.
Code from Main.cpp
// Repeat_Assessment_C++_Aisling.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include "Customer.h"
using namespace std;
void OutputFileStream();
void parseLine(const string& str);
void InputFileStream();
//void printActions();
void OutputFileStream()
{
cout << "Creating and writing to file: Customer.txt" << endl;
ofstream outStream("customers.txt"); // write mode (overwrites existing data)
if (outStream.good())
{
int customerID = 150033;
outStream << "This is a line of text.\n";
outStream << "This is another line of text.\n";
outStream << "This is a line of text.\n";
int numOfPurchases = 4;
int purchases = 0;
outStream << customerID << "Mr" << "Jack" << "New" << numOfPurchases << purchases << endl;
outStream.close(); // close file
cout << "File written.\n" << endl;
}
else
cout << "Unable to open file";
}
void parseLine(const string& str) {
stringstream strStream(str); //create string stream from the string
// int customerID;
string title;
string name;
string type;
//int numOfPurchases;
//int purchases;
string s;
int customerID = 150033;
getline(strStream, s, ';');
customerID = stoi(s);
getline(strStream, title, ';');
getline(strStream, name, ';');
getline(strStream, type, ';');
int numOfPurchases = 4;
getline(strStream, s, ';');
numOfPurchases = stoi(s);
int purchases = 0;
getline(strStream, s, ';');
purchases = stoi(s);
int* purchasesArray = new int[3];
purchasesArray[0] = (purchases & (255 << 24)) >> 24;
purchasesArray[1] = (purchases & (255 << 16)) >> 16;
purchasesArray[2] = (purchases & (255 << 8)) >> 8;
for (int i = 0; i < 3; i++)
{
int purchasesArray[3];
}
cout << " CustomerID: " << customerID << "Title:" << title << " Name: " << name << " Type:" << type << " Number of Purchases: " << numOfPurchases << "Purchases: " << purchases << endl;
}
void InputFileStream() {
cout << "Reading from a semi-colon delimited txt file" << endl;
string line;
ifstream inStream("customers.txt"); //opens file as an input file stream
if (inStream.good()) //if the file is opened successfully and not empty
{
while (getline(inStream, line)) //reads line until false return
{
parseLine(line);
}
inStream.close();
}
else
cout << "unable to open file or the file is empty!";
}
int main()
{
InputFileStream();
Customer cust1;
cust1.setCustomerID(150032);
cust1.setTitle("Mr");
cust1.setName("Joey");
cust1.setNumOfPurchases(3);
cust1.setPurchases(366, 352, 334);
cust1.setType("New");
cout << cust1.getCustomerID() << endl;
cout << cust1.getTitle() << endl;
cout << cust1.getName() << endl;
cout << cust1.getNumOfPurchases() << endl;
cout << cust1.getPurchases() << endl;
cout << cust1.getType() << endl;
return 0;
}
Code from Customer.h
#pragma once
#include<iostream>
using namespace std;
#include<string>
class Customer
{
private:
int customerID;
string title;
string name;
int numOfPurchases;
int* purchases;
string type;
public:
Customer(); // default constructor
Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type);
//copy overload assignment
Customer& operator=(Customer& otherCustomer);
Customer(const Customer& source);
~Customer(); //destructor
//Getters and Setters
void setCustomerID(int customerID);
void setTitle(string title);
void setName(string name);
void setNumOfPurchases(int numOfPurchases);
void setPurchases(int purchase1, int purchase2, int purchase3);
void setType(string type);
int getCustomerID();
string getTitle();
string getName();
int getNumOfPurchases();
int* getPurchases();
string getType();
void printCustomer() {
cout << customerID << "," << title << "," << name << "," << numOfPurchases << "," << purchases << "," << type << endl;
}
friend std::ostream& operator<<(std::ostream& out, Customer& customer); // overloaded operator<<
friend istream& operator>> (istream& in, Customer& customer); // overloaded operator >>
};
Code from Customer.cpp
#include "Customer.h"
#include <iostream>
#include <string>
#include<utility>
using namespace std;
//default constructor
Customer::Customer() {
}
//Full constructor
Customer::Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type)
{
this->customerID = customerID;
this->title = title;
this->name = name;
this->numOfPurchases = numOfPurchases;
purchases = new int[3];
purchases[0] = purchase1;
purchases[1] = purchase2;
purchases[2] = purchase3;
this->type = type;
}
Customer::Customer(const Customer& source) //copy constructor
{
cout << "copy constructor called" << endl;
this->customerID = source.customerID;
this->title = source.title;
this->name = source.name;
this->numOfPurchases = source.numOfPurchases;
this->purchases = new int[3];
purchases[0] = source.purchases[0];
purchases[1] = source.purchases[1];
purchases[2] = source.purchases[2];
this->type = source.type;
}
//overloaded assignment operator=
Customer& Customer::operator= (Customer& otherCustomer)
{
cout << "Overloaded assignment operator= called" << endl;
//self-assignment guard
if (this == &otherCustomer)
return *this; //refernce to the same object
// copy data from the source (rhs) to this object (the destination)
name = otherCustomer.name;
//must make a new scores object to store a copy of the other student
if (purchases != nullptr)
delete[] purchases;
purchases = new int[3];
for (int i = 0; i < 3; i++) {
purchases[i] = otherCustomer.purchases[i];
}
//return this existing object so we can chain this operator
return *this;
}
Customer::~Customer() {
cout << "Destructor ~Customer called" << endl;
delete[] purchases;
}
// Overloaded insertion operator (Outputs Character object data as an output stream)
// Defined in header file as a "friend" function, as it is not a member function
//
ostream& operator<<(ostream& out, Customer& customer)
{
cout << "Customer details ( output by insertion operator<< )" << endl;
cout << "Customer ID: " << customer.customerID << endl;
cout << "Title: " << customer.title << endl;
cout << "Name: " << customer.name << endl;
cout << "Number of purchases: " << customer.numOfPurchases << endl;
cout << "Purchases: ";
for (int i = 0; i < 3; i++)
{
if (i > 0) cout << ",";
cout << customer.purchases[i];
}
cout << "Type: " << customer.type << endl;
return out;
}
istream& operator>> (istream& in, Customer& customer)
{
cout << "Enter Customer details ( using the extraction operator>> )" << endl;
cout << "Enter Customer ID: " << endl;
cin >> customer.customerID;
cout << "Enter Title: " << endl;
getline(cin, customer.title);
cout << "Enter Name: " << endl;
getline(cin, customer.name);
cout << "Enter Number of Purchases: ";
cin >> customer.numOfPurchases;
cout << "Enter Purchases: ";
cin >> customer.purchases[0];
cin >> customer.purchases[1];
cin >> customer.purchases[2];
cout << "Enter Type";
getline(cin, customer.type);
cout << endl;
return in;
}
int Customer::getCustomerID()
{
return customerID;
}
string Customer::getTitle()
{
return title;
}
string Customer::getName()
{
return name;
}
int Customer::getNumOfPurchases()
{
return numOfPurchases;
}
int* Customer::getPurchases()
{
return purchases;
}
string Customer::getType()
{
return type;
}
void Customer::setCustomerID(int customerID)
{
if (customerID < 1) {
cout << "Customer ID has to be equal to 1 or more" << endl; //Changed all the "throw invalid_argument" messages to cout as they were causing an issue with my main.cpp file and an abort message kept appearing every time I ran my main.cpp file.
}
this->customerID = customerID;
}
void Customer::setTitle(string title)
{
if (title.length() < 2) {
cout << "Title has to be more than or equal to 2 characters" << endl;
}
this->title = title;
}
void Customer::setName(string name)
{
if (name.length() < 4) {
cout << "Length of name should be more than or equal to 4 characters" << endl;
}
this->name = name;
}
//Got help ith this on stack overflow as I was using "&&" instead of using "||" for the if statement
void Customer::setNumOfPurchases(int numOfPurchases)
{
if(numOfPurchases <0 || numOfPurchases > 10000){
cout << "Number of purchases should be between 0 to 10000" << endl;
}
this->numOfPurchases = numOfPurchases;
}
void Customer::setPurchases(int purchase1, int purchase2, int purchase3)
{
if (purchase1 < 0 || purchase2 < 0 || purchase3 < 0) {
cout << "Purchases must be more than or equal to zero" << endl;
}
}
//Got help from stack overflow on comparing strings as I originally didnt use "type.compare"
void Customer::setType(string type) {
if (type.compare("New") !=0 || type.compare("Either") !=0) {
cout << "Type of purchase has to be New or Either" << endl;
}
}
Text in my customers.txt file:
150034;Mr;Sean Brennan;New;5;365048;\n
150035;Mrs;Aisling Smith;Regular;6;375149;\n
150036;Mr;John Smith;New;7;385250;\n
150037;Mrs;Sharon Hanratty;Regular;8;395351;
Trouble seems to be that you are trying to divide input into its hexadecimal digits and it looks like you are looking for decimal digits.
May be you can do something like following:
purchasesArray[0] = purchases / 10000;
purchasesArray[1] = (purchases / 100) % 100;
purchasesArray[2] = purchases % 100;
instead of
purchasesArray[0] = (purchases & (255 << 24)) >> 24;
purchasesArray[1] = (purchases & (255 << 16)) >> 16;
purchasesArray[2] = (purchases & (255 << 8)) >> 8;
Note: If your input is pretty big, above solution can be bad performancewise.
Note 2: Even if you really want hexadecimal digits, your parsing is problematic.
Edit for note 2:
To parse a 6 digit hexadecimal number you might do this:
purchasesArray[0] = (purchases & (255 << 16)) >> 16;
purchasesArray[1] = (purchases & (255 << 8)) >> 8;
purchasesArray[2] = purchases & 255;
your code seems to parse first 6 digits of an 8 digit hex number.
That is why I called it problematic.
I am currently working on a project in c++ and I have 3 files. A Customer.h, Customer.cpp and Main.cpp, whenever I try to run the main.cpp file I get an error message and the abort method is called. There are no issues or any other error messages with any of the code in my 3 files and i'm unsure of what could be causing the error, any help would be greatly appreciated!
Code from "Main.cpp" is below as I can't upload any images yet
#include "Customer.h"
using namespace std;
int main()
{
Customer cust1;
cust1.setCustomerID(150032);
cust1.setTitle("Mr");
cust1.setName("Joey");
cust1.setNumOfPurchases(3);
cust1.setPurchases(366, 352, 334);
cust1.setType("New");
cout << cust1.getCustomerID() << endl;
cout << cust1.getTitle() << endl;
cout << cust1.getName() << endl;
cout << cust1.getNumOfPurchases() << endl;
cout << cust1.getPurchases() << endl;
cout << cust1.getType() << endl;
return 0;
}
Code from the Customer.h file below
class Customer
{
private:
int customerID;
string title;
string name;
int numOfPurchases;
int* purchases;
string type;
public:
Customer(); // default constructor
Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type);
//copy overload assignment
Customer& operator=(Customer& otherCustomer);
Customer(const Customer& source);
~Customer(); //destructor
//Getters and Setters
void setCustomerID(int customerID);
void setTitle(string title);
void setName(string name);
void setNumOfPurchases(int numOfPurchases);
void setPurchases(int purchase1, int purchase2, int purchase3);
void setType(string type);
int getCustomerID();
string getTitle();
string getName();
int getNumOfPurchases();
int* getPurchases();
string getType();
void printCustomer() {
cout << customerID << "," << title << "," << name << "," << numOfPurchases << "," << purchases << "," << type << endl;
}
friend std::ostream& operator<<(std::ostream& out, Customer& customer); // overloaded operator<<
friend istream& operator>> (istream& in, Customer& customer); // overloaded operator >>
};
Code from the Customer.cpp file below
//default constructor
Customer::Customer() {
}
//Full constructor
Customer::Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type)
{
customerID = customerID;
title = title;
name = name;
numOfPurchases = numOfPurchases;
purchases = new int[3];
purchases[0] = purchase1;
purchases[1] = purchase2;
purchases[2] = purchase3;
type = type;
}
Customer::Customer(const Customer& source) //copy constructor
{
cout << "copy constructor called" << endl;
this->customerID = source.customerID;
this->title = source.title;
this->name = source.name;
this->numOfPurchases = source.numOfPurchases;
this->purchases = new int[3];
purchases[0] = source.purchases[0];
purchases[1] = source.purchases[1];
purchases[2] = source.purchases[2];
this->type = source.type;
}
//overloaded assignment operator=
Customer& Customer::operator= (Customer& otherCustomer)
{
cout << "Overloaded assignment operator= called" << endl;
//self-assignment guard
if (this == &otherCustomer)
return *this; //refernce to the same object
// copy data from the source (rhs) to this object (the destination)
name = otherCustomer.name;
//must make a new scores object to store a copy of the other student
if (purchases != nullptr)
delete[] purchases;
purchases = new int[3];
for (int i = 0; i < 3; i++) {
purchases[i] = otherCustomer.purchases[i];
}
//return this existing object so we can chain this operator
return *this;
}
Customer::~Customer() {
cout << "Destructor ~Customer called" << endl;
delete[] purchases;
}
// Overloaded insertion operator (Outputs Character object data as an output stream)
// Defined in header file as a "friend" function, as it is not a member function
//
ostream& operator<<(ostream& out, Customer& customer)
{
cout << "Customer details ( output by insertion operator<< )" << endl;
cout << "Customer ID: " << customer.customerID << endl;
cout << "Title: " << customer.title << endl;
cout << "Name: " << customer.name << endl;
cout << "Number of purchases: " << customer.numOfPurchases << endl;
cout << "Purchases: ";
for (int i = 0; i < 3; i++)
{
if (i > 0) cout << ",";
cout << customer.purchases[i];
}
cout << "Type: " << customer.type << endl;
return out;
}
istream& operator>> (istream& in, Customer& customer)
{
cout << "Enter Customer details ( using the extraction operator>> )" << endl;
cout << "Enter Customer ID: " << endl;
cin >> customer.customerID;
cout << "Enter Title: " << endl;
getline(cin, customer.title);
cout << "Enter Name: " << endl;
getline(cin, customer.name);
cout << "Enter Number of Purchases: ";
cin >> customer.numOfPurchases;
cout << "Enter Purchases: ";
cin >> customer.purchases[0];
cin >> customer.purchases[1];
cin >> customer.purchases[2];
cout << "Enter Type";
getline(cin, customer.type);
cout << endl;
return in;
}
int Customer::getCustomerID()
{
return customerID;
}
string Customer::getTitle()
{
return title;
}
string Customer::getName()
{
return name;
}
int Customer::getNumOfPurchases()
{
return numOfPurchases;
}
int* Customer::getPurchases()
{
return purchases;
}
string Customer::getType()
{
return type;
}
void Customer::setCustomerID(int customerID)
{
if (customerID < 1) {
throw invalid_argument("Customer ID has to be equal to 1 or more");
}
this->customerID = customerID;
}
void Customer::setTitle(string title)
{
if (title.length() < 2) {
throw invalid_argument("Title has to be more than or equal to 2 characters");
}
this->title = title;
}
void Customer::setName(string name)
{
if (name.length() < 4) {
throw invalid_argument("Length of name should be more than or equal to 4 characters");
}
this->name = name;
}
void Customer::setNumOfPurchases(int numOfPurchases)
{
if(numOfPurchases > 0 && numOfPurchases < 10000){
throw invalid_argument("Number of purchases should be between 0 to 10000");
}
this->numOfPurchases = numOfPurchases;
}
void Customer::setPurchases(int purchase1, int purchase2, int purchase3)
{
if (purchase1 < 0 || purchase2 < 0 || purchase3 < 0) {
throw invalid_argument("Purchases must be more than or equal to zero");
}
}
void Customer::setType(string type) {
if (type != "New" || type != "Either") {
throw invalid_argument("Type of purchase has to be New or Either");
}
}
You're missing a few directives (namespace std, iostream, etc), but I fixed that and reproduced the issue up to here:
libc++abi.dylib: terminating with uncaught exception of type std::invalid_argument: Number of purchases should be between 0 to 10000 Abort trap: 6
Using the Customer.cpp code you provided (thanks for adding that), I see you have a logic error on line 161
void Customer::setNumOfPurchases(int numOfPurchases)
{
if(numOfPurchases > 0 && numOfPurchases < 10000){
throw invalid_argument("Number of purchases should be between 0 to 10000");
}
this->numOfPurchases = numOfPurchases;
}
Clearly if numOfPurchases is between 0 and 1000 an invalid_argument error is thrown, by your very design. You should change it to something like this:
void Customer::setNumOfPurchases(int numOfPurchases)
{
if(numOfPurchases < 0 || numOfPurchases > 10000){
throw invalid_argument("Number of purchases should be between 0 to 10000");
}
this->numOfPurchases = numOfPurchases;
}
Fixing that revealed another error:
libc++abi.dylib: terminating with uncaught exception of type std::invalid_argument: Type of purchase has to be New or Either Abort trap: 6
This led me to line 176:
void Customer::setType(string type) {
if (type != "New" || type != "Either") {
throw invalid_argument("Type of purchase has to be New or Either");
}
}
Ahh, the classic string comparison issue. This is NOT how you compare strings in C++. Try something like this instead, using the compare method in the string library.
void Customer::setType(string type) {
if (type.compare("New") != 0 && type.compare("Either") != 0) {
throw invalid_argument("Type of purchase has to be New or Either");
}
}
Those changes fixed the issue for me and it runs fine. Also, I asked for the compile command you were using, which doesn't appear to be provided, so I just used g++ main.cpp.
my program is supposed to parse through strings from a file and store in the array of structs.
Example: Skyfall, 1.109, Sam Mendes, 11/9/12, 143. Program will parse the string and store the title, gross, director name etc.
Whenever i run the code it doesn't seem to store it properly.
Also, I'm getting this error.
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
Here's my struct:
struct Movie
{
string Title; // Movie title
string Gross; // Gross total in billion dollars
string Director; // Director name
string Date; // Release date
string Runtime; // Runtime in minutes
};
This function is to create the array of objects and open the file
Movie* createDatabase(int& number_Of_Lines)
{
// input file
ifstream movie_file;
string filename;
do
{
cout << "Please enter filename: " ;
getline (cin , filename);
movie_file.open(filename.c_str());
if(movie_file.fail())
cout << "Invalid file" << endl ;
}while(movie_file.fail());
// array of objects
number_Of_Lines = numberOfLines(movie_file);
Movie* ptr = new Movie [number_Of_Lines];
//Looping through array of objects
for(int i = 0 ; i < number_Of_Lines ; i++)
populateMovieFromFile(movie_file, ptr[i]);
return ptr;
}
This function populates the objects
void populateMovieFromFile(ifstream& movie_file, Movie& movies)
{
getline(movie_file, movies.Title, ',');
movie_file.ignore();
getline(movie_file, movies.Gross, ',');
movie_file.ignore();
getline(movie_file, movies.Director, ',');
movie_file.ignore();
getline(movie_file, movies.Date, ',');
movie_file.ignore();
getline(movie_file, movies.Runtime);
}
Full program:
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <cctype>
using namespace std;
struct Movie
{
string Title; // Movie title
string Gross; // Gross total in billion dollars
string Director; // Director name
string Date; // Release date
string Runtime; // Runtime in minutes
};
int numberOfLines(ifstream&);
void populateMovieFromFile(ifstream&, Movie&);
void displayMovie(const Movie&);
Movie* createDatabase(int&);
bool caseInsensitiveCmp(string, string);
void findMovie(Movie*, int);
void saveToFile(const Movie&);
bool promptToContinue();
//void displayFavorites();
int main ()
{
int number_Of_Lines = 0;
Movie* ptr_movies = createDatabase(number_Of_Lines);
do
{
findMovie(ptr_movies , number_Of_Lines);
}while (!promptToContinue());
//displayFavorites();
return 0;
}
int numberOfLines(ifstream& movie_file)
{
int number_Of_Lines = 0;
string lines;
if(movie_file)
{
while(getline(movie_file, lines))
number_Of_Lines++ ;
}
movie_file.seekg (0, ios::beg);
return number_Of_Lines;
}
void populateMovieFromFile(ifstream& movie_file, Movie& movies)
{
getline(movie_file, movies.Title, ',');
movie_file.ignore();
getline(movie_file, movies.Gross, ',');
movie_file.ignore();
getline(movie_file, movies.Director, ',');
movie_file.ignore();
getline(movie_file, movies.Date, ',');
movie_file.ignore();
getline(movie_file, movies.Runtime);
}
void displayMovie(const Movie& movie)
{
cout << right << setw(13) << "Title: " << left << movie.Title << endl;
cout << right << setw(13) << "Gross Total: " << left << movie.Gross << " billion dollars" << endl;
cout << right << setw(13) << "Director: " << left << movie.Director << endl;
cout << right << setw(13) << "Release date: " << left << movie.Date << endl;
cout << right << setw(13) << "Runtime: " << left << movie.Runtime << " minutes" << endl;
}
Movie* createDatabase(int& number_Of_Lines)
{
// input file
ifstream movie_file;
string filename;
do
{
cout << "Please enter filename: " ;
getline (cin , filename);
movie_file.open(filename.c_str());
if(movie_file.fail())
cout << "Invalid file" << endl ;
}while(movie_file.fail());
// array of objects
number_Of_Lines = numberOfLines(movie_file);
Movie* ptr = new Movie [number_Of_Lines];
//Looping through array of objects
for(int i = 0 ; i < number_Of_Lines ; i++)
populateMovieFromFile(movie_file, ptr[i]);
return ptr;
}
bool caseInsensitiveCmp(string input, string list) //list will be from the object of array
{
int i = 0 , j = 0;
while (input[i])
{
char c = input[i];
input[i] = tolower(c);
i++;
}
while (list[j])
{
char c = list[j];
list[j] = tolower(c);
j++;
}
if (input == list)
return true;
else
return false;
}
void findMovie(Movie* ptr_movie, int number_Of_Lines)
{
cout << endl;
int i = 0;
char save;
string input_title;
bool found = false;
bool No_Match = false;
cout << "Enter a movie title to search for: ";
getline(cin , input_title);
do
{
found = caseInsensitiveCmp(ptr_movie[i].Title , input_title); //loop it
if (found == false)
i++;
if (i>=number_Of_Lines)
No_Match = true;
} while (found == false || No_Match == false);
if(found == true)
{
displayMovie(ptr_movie[i]);
cout << endl ;
cout << "Would you like to save the above movie? (Y or N)" << endl;
cin >> save;
if (save == 'y' || save == 'Y')
saveToFile(ptr_movie[i]);
}
else
cout << input_title << " not found in database. Please try again." << endl;
}
void saveToFile(const Movie& movie)
{
ofstream outfile;
outfile.open("favourites.txt", ios::app);
cout << movie.Title << "," << movie.Gross << ","
<< movie.Director << "," << movie.Date << ","
<< movie.Runtime << endl;
}
bool promptToContinue()
{
char Quit;
bool exit = false;
cout << "Would you like to exit? (Y or N): ";
cin >> Quit;
switch (Quit)
{
case 'Y':
case 'y':
exit = true;
case 'N':
case 'n':
exit = false;
}
return exit;
}
Any help is appreciated
The problem is:
In your "saveToFile" function, you open a ofstream, but do not use it. Instead you write to std::cout. So, you do not store the data.
Additionally, you are calling new but never delete. With that you are creating a memory leak.
Then, you still thinking to much in C. You should not use new or plain C-Style arrays. Never.
You should instead use STL containers and a more object oriented approach. At the moment you are using a lot of global functions, working with data.
In C++ you should use objects and associated data and methods. For example, a Movie knows how to read and store its data. Therefore implement that as a method.
And a Movie database is an additional object that contains a vector of movies.
To give you an idea of a more object oriented approach, I create a small example for you.
Please see and try to understand.
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <regex>
#include <string>
class Movie
{
public:
// Overload Extractor Operator to read data from somewhere
friend std::istream& operator >> (std::istream& is, Movie& m);
// Overload Inserter operator. Insert data into output stream
friend std::ostream& operator << (std::ostream& os, const Movie& m);
// Show movie data on std::out
void display() const;
// Check if a movie has a certain title
bool hasTitle(const std::string& t) const { return t == title; }
private:
// Data
std::string title{}; // Movie title
std::string gross{}; // Gross total in billion dollars
std::string director{}; // Director name
std::string date{}; // Release date
std::string runtime{}; // Runtime in minutes
};
// Overload Extractor Operator to read data from somewhere
std::istream& operator >> (std::istream& is, Movie& m) {
std::vector<std::string> dataInOneLine{}; // Here we will store all data that we read in one line;
std::string wholeLine; // Temporary storage for the complete line that we will get by getline
std::regex separator(","); ; // Separator for a CSV file
std::getline(is, wholeLine); // Read one complete line
// Parse the line and split it into parts
std::copy(std::sregex_token_iterator(wholeLine.begin(), wholeLine.end(), separator, -1),
std::sregex_token_iterator(),
std::back_inserter(dataInOneLine));
// If we have read all expted strings, then store them in our struct
if (dataInOneLine.size() == 5) {
m.title = dataInOneLine[0];
m.gross = dataInOneLine[1];
m.director = dataInOneLine[2];
m.date = dataInOneLine[3];
m.runtime = dataInOneLine[4];
}
return is;
}
std::ostream& operator << (std::ostream& os, const Movie& m) {
// Copy csv data to ostream
return os << m.title << "," << m.gross << "," << m.director << "," << m.date << "," << m.runtime << "\n";
}
void Movie::display() const {
std::cout << " Title: " << title << "\n Gross Total: " << gross << " billion dollars\n Director: " << director
<< "\nRelease date: " << date << "\n Runtime: " << runtime << " minutes\n";
}
// Database for Movies
class MovieDatabase {
public:
// Constructor. Open and read the database
explicit MovieDatabase(const std::string pafn) : pathAndFileName(pafn) { open(); }
// Destructor automatically saves and closes the database
~MovieDatabase() { close(); };
// Open/close the database
bool open();
void close();
// Add a new movie
void addMovie(const Movie& m) { data.push_back(m); }
// Find and display a movie
bool findAndDisplay (const std::string& title);
private:
const std::string pathAndFileName{};
std::vector<Movie> data{};
};
// Destructor
void MovieDatabase::close() {
// Save data
std::ofstream outFileStream{ pathAndFileName, std::ios::trunc };
if (outFileStream) {
// then save all data in csv format
std::copy(data.begin(), data.end(), std::ostream_iterator<Movie>(outFileStream));
}
}
// Open database and read the data from disk
bool MovieDatabase::open() {
bool success{ false };
// Open the file
std::ifstream inFileStream{ pathAndFileName };
// If the file could be opened
if (inFileStream) {
success = true;
// Then copy all data from disk, parse the csv and store it in our data vector
std::copy(std::istream_iterator<Movie>(inFileStream), std::istream_iterator<Movie>(), std::back_inserter(data));
}
return success;
}
// Find and display a value
bool MovieDatabase::findAndDisplay (const std::string& title) {
bool found { false };
// Search for a given title
std::vector<Movie>::iterator md = std::find_if(data.begin(), data.end(), [&title](const Movie &m) { return m.hasTitle(title); });
if (data.end() != md) {
// If found, then display it
md->display();
found = true;
}
else {
std::cerr << "\n\nTitle '" << title << "' not found in database\n\n";
}
return found;
}
int main() {
// Get the name of the database
std::string pathNameDatabase{};
std::cout << "Enter the path/filename of the database:\n";
std::cin >> pathNameDatabase;
// Define database and open it
MovieDatabase md{ pathNameDatabase };
// Do some stuff
std::cout << "\n\nSearch for title. Please enter title:\n";
std::string title{};
std::cin >> title; std::cin.ignore();
// Search and display data
md.findAndDisplay(title);
// Add a new record
std::cout << "\n\nAdd new movie data\nPlease enter title, gross, director, date, runtime (in one line, seperated by comma):\n";
Movie m{};
std::cin >> m;
m.display();
md.addMovie(m);
return 0;
}
I currently have a main.cc and a database.cc file that work perfectly, but my main.cc file does not match the one that it is going to be tested with. I've tried to convert it but it keeps throwing errors and I don't have the time to break my whole code and start again.
This is my database.cc file:
#include<list>
#include<algorithm>
#include<iostream>
#include<string>
#include<fstream>
#ifndef passenger_h
#define passenger_h
using std::string;
using std::cin;
using std::cout;
using std::list;
using std::endl;
class Passenger {
public:
Passenger() {}
Passenger(string, string, string);
bool operator==(const Passenger&) const;
bool operator<(const Passenger&) const;
void print(std::ostream& os);
private:
string fname, lname, destination;
};
class Flightlist {
public:
int menu();
void read_from_file(string);
void insert(Passenger p);
void remove(Passenger p);
bool check_reservation(Passenger p);
void display_list();
void save_to_file(string);
private:
list<Passenger> flist;
};
#endif
Passenger::Passenger(string first, string last, string dest)
{
fname = first;
lname = last;
destination = dest;
}
bool Passenger::operator==(const Passenger& p) const
{
return fname == p.fname && lname == p.lname;
}
bool Passenger::operator<(const Passenger& p) const
{
return fname < p.fname || (fname == p.fname && lname < p.lname);
}
void Passenger::print(std::ostream& os)
{
os << fname << ' ' << lname << ' ' << destination << '\n';
}
int Flightlist::menu()
{
int option;
cout << endl;
cout << "Enter one of the following options:" << endl;
cout << "1. load reservations from file:" << endl;
cout << "2. reserve a ticket" << endl;
cout << "3. cancel a reservation" << endl;
cout << "4. check reservation" << endl;
cout << "5. display passenger list" << endl;
cout << "6. save passenger list" << endl;
cout << "7. exit" << endl << endl;
cin >> option;
cin.get();
return option;
}
void Flightlist::read_from_file(string filename)
{
string fname, lname, destination;
std::ifstream input(filename.c_str());
while (input >> fname >> lname >> destination)
{
flist.push_back(Passenger(fname, lname, destination));
}
input.close();
}
void Flightlist::insert(Passenger p)
{
flist.push_back(p);
}
void Flightlist::remove(Passenger p)
{
flist.remove(p);
}
bool Flightlist::check_reservation(Passenger p)
{
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
return flist.end() != find(flist.begin(), flist.end(), p);
}
void Flightlist::display_list()
{
flist.sort();
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
for ( ; i1 != i2; ++i1) {
i1->print(cout);
}
}
void Flightlist::save_to_file(string filename)
{
flist.sort();
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
std::ofstream output(filename.c_str());
for ( ; i1 != i2; ++i1) {
i1->print(output);
}
output.close();
}
This is my current main.cc file, which works perfectly with the above program:
#include "database.cc"
int main()
{
Flightlist flight_list;
string fname, lname, destination;
while (true)
{
switch (flight_list.menu())
{
case 1:
{
flight_list.read_from_file("ticket_reservations.dat");
break;
}
case 2:
{
cout << "first name of passenger:" << endl;
cin >> fname;
cout << "last name of passenger" << endl;
cin >> lname;
cout << "destination of passenger" << endl;
cin >> destination;
flight_list.insert(Passenger(fname, lname, destination));
break;
}
case 3:
{
cout << "first name of passenger:" << endl;
cin >> fname;
cout << "last name of passenger" << endl;
cin >> lname;
cout << "destination of passenger" << endl;
cin >> destination;
flight_list.remove(Passenger(fname, lname, destination));
break;
}
case 4:
{
cout << "first name of passenger:" << endl;
cin >> fname;
cout << "last name of passenger" << endl;
cin >> lname;
cout << "destination of passenger" << endl;
cin >> destination;
if (flight_list.check_reservation(Passenger(fname, lname, destination)))
cout << "this passenger has a ticket reservation" << endl;
else
cout << "this passenger does not have a ticket reservation" << endl;
break;
}
case 5:
{
flight_list.display_list();
break;
}
case 6:
{
flight_list.save_to_file("ticket_reservations.dat");
}
break;
case 7:
return 0;
}
}
return 0;
}
This is the main.cc file that my program will be tested with, and therefore what I need to convert my code to be compatible with:
#include "database.cc"
int main()
{
list<Passenger> flight_list;
string first_name, last_name, destination;
while (true)
{
switch (menu())
{
case 1:
{
read_from_file(flight_list, "ticket_reservations.dat");
break;
}
case 2:
{
cout << "name of passenger:" << endl;
cin >> first_name >> last_name;
cout << "destination:" << endl;
cin.ignore();
getline(cin, destination);
insert(flight_list, first_name, last_name, destination);
break;
}
case 3:
{
cout << "name of passenger:" << endl;
cin >> first_name >> last_name;
remove(flight_list, first_name, last_name);
break;
}
case 4:
{
cout << "name of passenger:" << endl;
cin >> first_name >> last_name;
if (check_reservation(flight_list, first_name, last_name))
cout << "this passenger has a ticket reservation" << endl;
else
cout << "this passenger does not have a ticket reservation" << endl;
break;
}
case 5:
{
display_list(flight_list);
break;
}
case 6:
{
save_to_file(flight_list, "ticket_reservations.dat");
}
break;
case 7:
return 0;
}
}
return 0;
}
I strongly apologise for the large amount of code, but I desperately need help with this. Thank you!
Your functions are not working because you have never defined them as general functions; they are class function members.
You need to iterate through your list and call the class member - I'm not going to rewrite all your code, but here's an illustration:
list<MyClass> MyList;
// ... your list is populated here ..
for(auto iter=MyList.begin(); iter!=MyList.end(); ++iter) {
// ... decide what to do here ...
*iter->MyMethod(argument1,argument2)
// ... etc ...
}
Note I'm calling MyMethod as a class member, not as a function (iter,first. You'll need to adjust your code to call your methods this way too, meaning you need to go through your list outside of the class instance.
The important bit to grasp is that you use . (or -> if you're accessing it through a pointer) to access your function member; you can't call it directly as a function.
The only other option you have is to add wrapper functions to your database.cc, defining the functions you're trying to call in your new main.cc.
Here is a new Database.cc that seems to compile.
It seems that the test main.cc calls free functions so I created new objects in every function stub.
And I added a constructor to Flightlist for list.
// #include "stdafx.h" // uncomment for MS version
#include<list>
#include<algorithm>
#include<iostream>
#include<string>
#include<fstream>
#ifndef passenger_h
#define passenger_h
using std::string;
using std::cin;
using std::cout;
using std::list;
using std::endl;
class Passenger {
public:
Passenger() {}
Passenger(string, string, string);
bool operator==(const Passenger&) const;
bool operator<(const Passenger&) const;
void print(std::ostream& os);
private:
string fname, lname, destination;
};
class Flightlist {
public:
int menu();
void read_from_file(string);
void insert(Passenger p);
void remove(Passenger p);
bool check_reservation(Passenger p);
void display_list();
void save_to_file(string);
// --- CHANGES START ----------------
Flightlist() {};
~Flightlist() {};
Flightlist(list<Passenger> flistInput) : flist(flistInput){};
private:
list<Passenger> flist;
};
int menu() {
static Flightlist FL;
return FL.menu();
}
void read_from_file(list<Passenger> flist, string s) {
Flightlist FL(flist);
FL.read_from_file(s);
}
void insert(list<Passenger> flist, string first, string last, string dest) {
Flightlist FL(flist);
Passenger p(first, last, dest);
FL.insert(p);
}
void remove(list<Passenger> flist, string first, string last) {
Flightlist FL(flist);
Passenger p(first, last, NULL);
FL.remove(p);
}
bool check_reservation(list<Passenger> flist, string first, string last) {
Flightlist FL(flist);
Passenger p(first, last, NULL);
return FL.check_reservation(p);
}
void display_list(list<Passenger> flist) {
Flightlist FL(flist);
FL.display_list();
}
void save_to_file(list<Passenger> flist, string s) {
Flightlist FL(flist);
FL.save_to_file(s);
}
// --- CHANGES STOP ----------------
#endif
Passenger::Passenger(string first, string last, string dest)
{
fname = first;
lname = last;
destination = dest;
}
bool Passenger::operator==(const Passenger& p) const
{
return fname == p.fname && lname == p.lname;
}
bool Passenger::operator<(const Passenger& p) const
{
return fname < p.fname || (fname == p.fname && lname < p.lname);
}
void Passenger::print(std::ostream& os)
{
os << fname << ' ' << lname << ' ' << destination << '\n';
}
int Flightlist::menu()
{
int option;
cout << endl;
cout << "Enter one of the following options:" << endl;
cout << "1. load reservations from file:" << endl;
cout << "2. reserve a ticket" << endl;
cout << "3. cancel a reservation" << endl;
cout << "4. check reservation" << endl;
cout << "5. display passenger list" << endl;
cout << "6. save passenger list" << endl;
cout << "7. exit" << endl << endl;
cin >> option;
cin.get();
return option;
}
void Flightlist::read_from_file(string filename)
{
string fname, lname, destination;
std::ifstream input(filename.c_str());
while (input >> fname >> lname >> destination)
{
flist.push_back(Passenger(fname, lname, destination));
}
input.close();
}
void Flightlist::insert(Passenger p)
{
flist.push_back(p);
}
void Flightlist::remove(Passenger p)
{
flist.remove(p);
}
bool Flightlist::check_reservation(Passenger p)
{
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
return flist.end() != find(flist.begin(), flist.end(), p);
}
void Flightlist::display_list()
{
flist.sort();
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
for (; i1 != i2; ++i1) {
i1->print(cout);
}
}
void Flightlist::save_to_file(string filename)
{
flist.sort();
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
std::ofstream output(filename.c_str());
for (; i1 != i2; ++i1) {
i1->print(output);
}
output.close();
}