A6423
A6423

Reputation: 29

What is causing the abort method to be called when I try to compile and run my "main.cpp" file in c++?

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");
    }
} 

Upvotes: 0

Views: 1064

Answers (1)

h0r53
h0r53

Reputation: 3229

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.

Upvotes: 1

Related Questions