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();
}
Related
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;
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.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am building up a program where I create a vector of objects, the input variables that create the object are read from a .txt file. I want to check if the "ID" of the object introduced by the user exists in order to continue.
vector<Producto> vectorProductos;
while(file >> sID >> sDesc >> sUMed >> sFam >> sClass >> dVolumen >> dLongitud >> sPrecio){
vectorProductos.push_back(Producto(sID, sDesc, sUMed,sFam, sClass, dVolumen, dLongitud, stringToDouble(sPrecio)));
iNumProductos++;
}
file.close();
int iNumPartidas;
cout << "iNumPartidas? " << endl;
cin >> iNumPartidas;
for(unsigned int iP = 1; iP <= iNumPartidas; iP++){
cout << endl << "Partida " << iP << ":" << endl;
cout << "Clave de partida:\t";
cin >> sPartida;
for(unsigned int iPrd = 0; iPrd < iNumProductos; iPrd++){
cout << endl << "Clave de producto " << iPrd+1 << ":\t";
cin >> sClave;
if(sClave == vectorProductos[iPrd].getClave()){
cout << endl << "Cantidad:\t";
cin >> iCantProdxP;
}else{
cout << "Producto no existe" << endl;
}
}
}
Producto class
#ifndef Producto_h
#define Producto_h
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
class Producto{
protected:
string _sClave, _sDescripcion, _sUMed, _sClass, _sFam;
double _dVolumen, _dPrecio, _dLongitud;
public:
Producto();
Producto(string, string, string, string, string, double, double, double);
inline string getClave(){return _sClave;}
inline string getDescripcion(){return _sDescripcion;}
inline string getUMed(){return _sUMed;}
inline string getFam(){return _sFam;}
inline string getClass(){return _sClass;}
inline double getVol(){return _dVolumen;}
inline double getPrecio(){return _dPrecio;}
inline double getLongitud(){return _dLongitud;}
inline void setClave(string sClave){_sClave = sClave;}
inline void setDescripcion(string sDescripcion){_sDescripcion = sDescripcion;}
inline void setUMed(string sUMed){_sUMed = sUMed;}
inline void setFam(string sFam){_sFam = sFam;}
inline void setClass(string sClass){_sClass = sClass;}
inline void setVol(double dVolumen){_dVolumen = dVolumen;}
inline void setPrecio(double dPrecio){_dPrecio = dPrecio;}
inline void setLongitud(double dLongitud){_dLongitud = dLongitud;}
void toString();
};
Producto::Producto(){
_sClave = "";
_sDescripcion = "Falta descripcion";
_sUMed = "N/A";
_sFam = "Sin Familia";
_sClass = "Sin clase";
_dVolumen = 0.0;
_dPrecio = 0.0;
_dLongitud = 0.0;
}
Producto::Producto(string sClave, string sDescripcion, string sUMed, string sFam, string sClass, double dVolumen, double dLongitud, double dPrecio){
_sClave = sClave;
_sDescripcion = sDescripcion;
_sUMed = sUMed;
_sFam = sFam;
_sClass = sClass;
_dVolumen = dVolumen;
_dPrecio = dPrecio;
_dLongitud = dLongitud;
}
void Producto::toString(){
cout << "\nProducto: " << _sClave;
cout << "\nDescripcion: " << _sDescripcion;
cout << "\nUnidad de Medida: " << _sUMed;
cout << "\nFamilia: " << _sFam;
cout << "\nClase: " << _sClass;
cout << "\nVolumen: " << _dVolumen;
cout << "\nLongitud: " << _dLongitud;
cout << "\nPrecio: " << _dPrecio;
cout << endl;
}
What I need is to see if that "ID" that the user is going to input actually exists and if not mark error. When I run my program I have to type in the ID of the first product to match it with the index number of the loop, and that is the only way it works but I need the program to match it with any "Producto" regardless of the position or index.
In your inner loop, you are prompting the user for an ID on every loop iteration and then comparing that ID only to the product at the index of the current loop iteration. You need to prompt the user one time BEFORE entering the loop and then compare the ID to every product until you find a match:
std::cout << endl << "Clave de producto:\t";
std::cin >> sClave;
bool found = false;
for (std::size_t iPrd = 0; iPrd < vectorProductos.size(); ++iPrd)
{
if (sClave == vectorProductos[iPrd].getClave())
{
found = true;
break;
}
}
if (found) {
// do something ...
}
else {
std::cout << "Producto no existe" << std::endl;
}
Alternatively, you should use std::find_if() instead of searching manually, eg:
Producto.h
#ifndef Producto_h
#define Producto_h
#include <iostream>
#include <string>
class Producto
{
protected:
std::string _sClave, _sDescripcion, _sUMed, _sClass, _sFam;
double _dVolumen, _dPrecio, _dLongitud;
public:
Producto();
Producto(std::string, std::string, std::string, std::string, std::string, double, double, double);
std::string getClave() const { return _sClave; }
std::string getDescripcion() const { return _sDescripcion; }
std::string getUMed() const { return _sUMed; }
std::string getFam() const { return _sFam; }
std::string getClass() const { return _sClass; }
double getVol() const { return _dVolumen; }
double getPrecio() const { return _dPrecio; }
double getLongitud() const { return _dLongitud; }
void setClave(std::string sClave) { _sClave = sClave; }
void setDescripcion(std::string sDescripcion) { _sDescripcion = sDescripcion; }
void setUMed(std::string sUMed) { _sUMed = sUMed; }
void setFam(std::string sFam) { _sFam = sFam; }
void setClass(std::string sClass) { _sClass = sClass; }
void setVol(double dVolumen) { _dVolumen = dVolumen; }
void setPrecio(double dPrecio) { _dPrecio = dPrecio; }
void setLongitud(double dLongitud) { _dLongitud = dLongitud; }
std::string toString() const;
};
std::istream& operator>>(std::istream &in, Producto &p);
#endif
Producto.cpp
#include "Producto.h"
#include <sstream>
std::istream& operator>>(std::istream &in, Producto &p)
{
std::string sID, sDesc, sUMed, sFam, sClass, sPrecio;
double dVolumen, dLongitud;
if (in >> sID >> sDesc >> sUMed >> sFam >> sClass >> dVolumen >> dLongitud >> sPrecio)
{
p.setClave(sID);
p.setDescripcion(sDesc);
p.setUMed(sUMed);
p.setFam(sFam);
p.setClass(sClass);
p.setVol(dVolumen);
p.setLongitud(dLongitud);
p.setPrecio(stringToDouble(sPrecio));
}
return in;
}
Producto::Producto() :
_sClave(),
_sDescripcion("Falta descripcion"),
_sUMed("N/A"),
_sFam("Sin Familia"),
_sClass("Sin clase"),
_dVolumen(0.0),
_dPrecio(0.0),
_dLongitud(0.0)
{
}
Producto::Producto(std::string sClave, std::string sDescripcion, std::string sUMed, std::string sFam, std::string sClass, double dVolumen, double dLongitud, double dPrecio) :
_sClave(sClave),
_sDescripcion(sDescripcion),
_sUMed(sUMed),
_sFam(sFam),
_sClass(sClass),
_dVolumen(dVolumen),
_dPrecio(dPrecio),
_dLongitud(dLongitud)
{
}
std::string Producto::toString() const
{
std::ostringstream oss;
oss << "Producto: " << _sClave;
oss << "\nDescripcion: " << _sDescripcion;
oss << "\nUnidad de Medida: " << _sUMed;
oss << "\nFamilia: " << _sFam;
oss << "\nClase: " << _sClass;
oss << "\nVolumen: " << _dVolumen;
oss << "\nLongitud: " << _dLongitud;
oss << "\nPrecio: " << _dPrecio;
return oss.str();
}
Main
#include <vector>
#include <algorithm>
#include "Producto.h"
std::vector<Producto> vectorProductos;
Producto p;
while (file >> p) {
vectorProductos.push_back(p);
}
file.close();
...
std::string sClave;
std::cout << std::endl << "Clave de producto:\t";
std::cin >> sClave;
auto iter = std::find_if(vectorProductos.begin(), vectorProductos.end(),
[&](const Producto &p){ return (p.getClave() == sClave); });
if (iter == vectorProductos.end()) {
std::cout << "Producto no existe" << std::endl;
}
else {
std::cout << "Producto existe" << std::endl;
// use *iter as needed...
std::cout << iter->toString() << std::endl;
// if you need the index of the found product, you can use:
// auto index = std::distance(vectorProductos.begin(), iter);
}
...
I've spent pretty much all day trying to do this, I understand pointers and what a linked list does, but I don't know how to actually code it and all I've found are Java and C examples which don't help because I'm using C++.
Thanks in advance for taking a look at my code and helping me, I really appreciate it considering how many days I've spent stressed out and confused about this. I'm not going to lie so far most of my deleteNode function is probably trash. But like I've said I'm just lost I don't even know where to start or how to progress because I only understand the concepts.
This is my data file.
John Doe 80
Jane Smith 70
Bill Jones 50
Pat Hughes 90
Sam Sosa 40
This is my Header file
#include<string>
using namespace std;
class student {
public:
student(); // constructor method
void st_fn(string fn);
string st_fn();
void st_ln(string ln);
string st_ln();
void st_score(float s);
float st_score();
string st_pass_or_fail();
// need a pointer to the next object
student *nxt_ptr;
protected: // protected can be inherited
float m_score;
string m_ln;
string m_fn;
string m_pf_msg;
};
student::student() //constructor
{
nxt_ptr = NULL;
m_score = 0;
}
void student::st_fn(string fn)
{
m_fn = fn;
}
string student::st_fn()
{
return m_fn;
}
void student::st_ln(string ln)
{
m_ln = ln;
}
string student::st_ln()
{
return m_ln;
}
void student::st_score(float s)
{
m_score = s;
}
float student::st_score()
{
return m_score;
}
string student::st_pass_or_fail()
{
if (m_score >= 60)
m_pf_msg = "PASSED";
else
m_pf_msg = "FAILED";
return m_pf_msg;
}
This is my .cpp file.
#include<iostream>
#include<string>
#include<fstream>
#include "Header.h"
using namespace std;
int display_menu()
{
int option;
cout << endl << endl;
cout << "1. Display List" << endl;
cout << "2. Add a student" << endl;
cout << "3. Delete first student" << endl;
cout << "4. Search by Last Name" << endl;
cout << "5. Exit" << endl;
cin >> option;
return option;
}
student * search_last_name(student *h)
{
student *f = NULL;
student *t = NULL;
string s_ln;
// prompt for last name to search for
cout << "Enter Last Name of the Student";
cin >> s_ln;
if (h != NULL)
{
t = h;
while (t != NULL)
{
if (t->st_ln() == s_ln)
f = t; // found the last name so save t
t = t->nxt_ptr;
}
}
else
cout << "List is empty" << endl;
return f;
}
void add_student(student *&head) // h is the head of the list
{
student *new_st, *r;
string fn, ln;
float s;
cout << "Enter new students first name, last name and score";
cin >> fn >> ln >> s;
// instantiate a new node, use new_st
new_st = new student;
new_st->st_fn(fn);
new_st->st_ln(ln);
new_st->st_score(s);
if (head == NULL)
head = new_st;
else
{
// find the last node, use r for this
// write code
r = head;
while (r->nxt_ptr != nullptr)
r = r->nxt_ptr;
// add to the back of the list
// write code
r->nxt_ptr = new_st;
} // end of else
} // end of add student
student * delete_front(student * head)
{
student *t;
// delete front node
// check for empty list
if (head != NULL)
{
// delete first node
t = head;
head = head->nxt_ptr;
delete(t);
}
else
cout << "List is empty - nothing to delete" << endl;
return head;
}
void deleteNode(struct Node *head, struct Node *n)
{
// When node to be deleted is head node
if (head == n)
{
n = head->next;
//Remove the link of next node
head->next = head->next->next;
return;
}
//When not first node, folow the normal deletion process
//Find the previous node
struct Node *prev = head;
while (prev->next != NULL && prev->next != n)
prev = prev->next;
// Check if node really exists in Linked List
if (prev->next == NULL)
{
cout << endl << "Given node is not present in Linked List";
return;
}
//Remove node from linked list should it exist
prev->next = prev->next->next;
return;
}
void display_list(student *t)
{
if (t == NULL)
cout << "List is Empty!";
else
{
while (t != NULL)
{
cout << "******Student******" << endl;
cout << t->st_ln() << endl;
cout << t->st_fn() << endl;
cout << t->st_score() << endl << endl;
t = t->nxt_ptr;
}
}
}
int main()
{
string ln, fn;
float s;
int n;
ifstream infile;
student *head = NULL; //pointer to a student object
student *cp = NULL; // pointer to end of the list
student *new_st = NULL; // pointer to a new student object
student *f = NULL; // pointer to found node
int option; // the numbe of menu item the user selects
infile.open("lab8d.txt");
while (!infile.eof())
{
infile >> fn >> ln >> s;
//instantiate a student object
new_st = new student;
//load the object with data
new_st->st_fn(fn);
new_st->st_ln(ln);
new_st->st_score(s);
// check for empty list - its a special case
if (head == NULL)
{
head = new_st;
cp = new_st;
}
else // list is not empty
{
cp->nxt_ptr = new_st;
cp = new_st;
}
} // end of loop
// loop to give the user some options
option = display_menu();
while (option != 5)
{
if (option == 1)
display_list(head);
else if (option == 2)
add_student(head);
else if (option == 3)
head = delete_front(head);
else if (option == 4)
{
f = search_last_name(head);
if (f != NULL)
{
cout << f->st_fn() << endl;
cout << f->st_ln() << endl;
cout << f->st_score() << endl;
cout << f->st_pass_or_fail() << endl;
}
else
cout << "Name not in the list" << endl;
}
else if (option == 6)
{
cout << "Enter the number of the node you would like to delete: " << endl;
cin >> n;
}
option = display_menu();
}
system("pause");
return 0;
}
The simpler and self-contained your functions are, the easier they are to test and debug, and the less like they are to fail.
Try something more like this:
Student.h:
#include <string>
class student_list;
class student
{
public:
student();
student(const std::string &fn, const std::string &ln, float s, student *nxt = NULL);
void next(student *s);
student* next() const;
void firstName(const std::string &fn);
std::string firstName() const;
void lastName(const std::string &ln);
std::string lastName() const;
void score(float s);
float score() const;
std::string pass_or_fail() const;
void display(bool showPassOrFail = false) const;
friend class student_list;
protected: // protected can be inherited
student *m_next;
std::string m_fn;
std::string m_ln;
float m_score;
};
Student.cpp:
#include "Student.h"
#include <iostream>
student::student()
: m_next(NULL), m_score(0)
{
}
student::student(const std::string &fn, const std::string &ln, float s, student *nxt)
: m_next(nxt), m_fn(fn), m_ln(ln), m_score(s)
{
}
void student::next(student *s)
{
m_next = s;
}
student* student::next() const
{
return m_next;
}
void student::firstName(const std::string &fn)
{
m_fn = fn;
}
std::string student::firstName() const
{
return m_fn;
}
void student::lastName(const std::string &ln)
{
m_ln = ln;
}
std::string student::lastName() const
{
return m_ln;
}
void student::score(float s)
{
m_score = s;
}
float student::score() const
{
return m_score;
}
std::string student::pass_or_fail() const
{
if (m_score >= 60)
return "PASSED";
else
return "FAILED";
}
void student::display(bool showPassOrFail) const
{
std::cout << lastName() << std::endl;
std::cout << firstName() << std::endl;
std::cout << score() << std::endl;
if (showPassOrFail)
std::cout << pass_or_fail() << std::endl;
}
StudentList.h:
#include <string>
class student;
class student_list
{
public:
student_list();
~student_list();
student* search_last_name(const std::string &ln);
student* insert(const std::string &fn, const std::string &ln, float s, student* after = NULL);
bool remove(int idx);
void display() const;
private:
student *m_head;
};
StudentList.cpp:
student_list::student_list()
: m_head(NULL)
{
}
student_list::~student_list()
{
while (m_head)
remove(0);
}
student* student_list::search_last_name(const std::string &ln)
{
student *t = m_head;
while (t)
{
if (t->lastName() == ln)
break; // found the last name
t = t->next();
}
return t;
}
student* student_list::insert(const std::string &fn, const std::string &ln, float s, student* after)
{
student **r;
if (after)
{
// add to list after the specified node
// get pointer to next node
r = &(after->m_next);
}
else
{
// add to the back of the list
// find pointer to last node
r = &m_head;
while (*r)
r = &((*r)->m_next);
}
// instantiate a new node
student *new_st = new student(fn, ln, s);
if (after)
new_st->next(*r);
// add to list
*r = new_st;
return new_st;
}
bool student_list::remove(int idx)
{
// delete a node at index
// find pointer to node
student **r = &m_head;
while ((*r) && (idx-- > 0))
r = &((*r)->m_next);
if (*r)
{
// delete node
student *t = *r;
*r = t->next();
delete t;
return true;
}
return false;
}
void student_list::display() const
{
student *t = m_head;
if (!t)
std::cout << "List is Empty!" << std::endl;
else
{
do
{
std::cout << "******Student******" << std::endl;
t->display();
t = t->next();
}
while (t);
}
}
Main.cpp:
#include "Student.h"
#include "StudentList.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <limits>
#include <cstdlib>
int read_number()
{
int value;
while (!(std::cin >> value))
{
std::cout << "Must be a number, try again: ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return value;
}
int display_menu()
{
int option;
std::cout << std::endl << std::endl;
std::cout << "1. Display List" << std::endl;
std::cout << "2. Add a student" << std::endl;
std::cout << "3. Delete first student" << std::endl;
std::cout << "4. Search by Last Name" << std::endl;
std::cout << "5. Delete student by index" << std::endl;
std::cout << "6. Exit" << std::endl << std::endl;
std::cout << "Choice: ";
do
{
option = read_number();
if ((option >= 1) && (option <= 6))
break;
std::cout << "Must be 1..6, try again: ";
}
while (true);
return (option != 6) ? option : -1;
}
int main()
{
student_list students;
std::ifstream infile("lab8d.txt");
if (infile.is_open())
{
student *cp = NULL;
std::string ln, fn;
float s;
while (infile >> fn >> ln >> s)
cp = students.insert(fn, ln, s, cp);
infile.close();
}
// loop to give the user some options
int option; // the number of menu item the user selects
while ((option = display_menu()) != -1)
{
switch (option)
{
case 1:
{
students.display();
break;
}
case 2:
{
// prompt for student info
std::string info;
std::cout << "Enter new student's first name, last name, and score: ";
std::string ln, fn;
float s;
if (std::cin >> fn >> ln >> s)
students.insert(fn, ln, s);
break;
}
case 3:
{
if (!students.remove(0))
std::cout << "List is empty" << std::endl;
break;
}
case 4:
{
// prompt for last name to search for
std::string ln;
std::cout << "Enter Last Name of the Student: ";
if (std::cin >> ln)
{
student *f = students.search_last_name(ln);
if (f)
f->display(true);
else
std::cout << "Name not found in List" << std::endl;
}
break;
}
case 5:
{
std::cout << "Enter the index of the Student to Delete: " << std::endl;
int idx = read_number();
if (!students.remove(idx))
std::cout << "Index not found in List" << std::endl;
break;
}
}
}
std::system("pause");
return 0;
}
That being said, you really should be using the std::list container instead, eg:
Student.h:
#include <string>
class student_list;
class student
{
public:
student();
student(const std::string &fn, const std::string &ln, float s);
void firstName(const std::string &fn);
std::string firstName() const;
void lastName(const std::string &ln);
std::string lastName() const;
void score(float s);
float score() const;
std::string pass_or_fail() const;
void display(bool showPassOrFail = false) const;
friend class student_list;
protected: // protected can be inherited
std::string m_fn;
std::string m_ln;
float m_score;
};
Student.cpp:
#include "Student.h"
#include <iostream>
student::student()
: m_score(0)
{
}
student::student(const std::string &fn, const std::string &ln, float s)
: m_fn(fn), m_ln(ln), m_score(s)
{
}
void student::firstName(const std::string &fn)
{
m_fn = fn;
}
std::string student::firstName() const
{
return m_fn;
}
void student::lastName(const std::string &ln)
{
m_ln = ln;
}
std::string student::lastName() const
{
return m_ln;
}
void student::score(float s)
{
m_score = s;
}
float student::score() const
{
return m_score;
}
std::string student::pass_or_fail() const
{
if (m_score >= 60)
return "PASSED";
else
return "FAILED";
}
void student::display(bool showPassOrFail) const
{
std::cout << lastName() << std::endl;
std::cout << firstName() << std::endl;
std::cout << score() << std::endl;
if (showPassOrFail)
std::cout << pass_or_fail() << std::endl;
}
Main.cpp:
#include "Student.h"
#include <list>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <limits>
#include <algorithm>
#include <cstdlib>
int read_number()
{
int value;
while (!(std::cin >> value))
{
std::cout << "Must be a number, try again: ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return value;
}
int display_menu()
{
int option;
std::cout << std::endl << std::endl;
std::cout << "1. Display List" << std::endl;
std::cout << "2. Add a student" << std::endl;
std::cout << "3. Delete first student" << std::endl;
std::cout << "4. Search by Last Name" << std::endl;
std::cout << "5. Delete student by index" << std::endl;
std::cout << "6. Exit" << std::endl << std::endl;
std::cout << "Choice: ";
do
{
option = read_number();
if ((option >= 1) && (option <= 6))
break;
std::cout << "Must be 1..6, try again: ";
}
while (true);
return (option != 6) ? option : -1;
}
int main()
{
std::list<student> students;
std::ifstream infile("lab8d.txt");
if (infile.is_open())
{
std::string ln, fn;
float s;
while (infile >> fn >> ln >> s)
students.push_back(student(fn, ln, s));
infile.close();
}
// loop to give the user some options
int option; // the number of menu item the user selects
while ((option = display_menu()) != -1)
{
switch (option)
{
case 1:
{
if (students.empty())
std::cout << "List is Empty!" << std::endl;
else
{
for(const auto &s : students)
{
std::cout << "******Student******" << std::endl;
s.display();
}
}
break;
}
case 2:
{
// prompt for student info
std::string info;
std::cout << "Enter new student's first name, last name, and score: ";
std::string ln, fn;
float s;
if (std::cin >> fn >> ln >> s)
students.push_back(student(fn, ln, s));
break;
}
case 3:
{
if (students.empty())
std::cout << "List is empty" << std::endl;
else
students.erase(students.begin());
break;
}
case 4:
{
// prompt for last name to search for
std::string ln;
std::cout << "Enter Last Name of the Student: ";
if (std::cin >> ln)
{
auto f = std::find(students.begin(), students.end(),
[&](const student &s){ return (s.lastName() == ln); }
);
if (f != students.end())
f->display(true);
else
std::cout << "Name not found in List" << std::endl;
}
break;
}
case 5:
{
std::cout << "Enter the index of the Student to Delete: " << std::endl;
int idx = read_number();
if ((idx < 0) || (idx >= students.size()))
std::cout << "Index not found in List" << std::endl;
else
students.erase(std::next(students.begin(), idx));
break;
}
}
}
std::system("pause");
return 0;
}