?
Solved

C++ - Conversion from static to dynamic arrays + pointers.

Posted on 2011-05-06
27
Medium Priority
?
573 Views
Last Modified: 2012-05-11
Hi!
Im extending a old program I've made. Im changing all the static arrays into dynamic arrays and using pointers aswell.

Program
The program is a transaction jar which functions as if three people are out on a dinner then one of the three may pay for all of them, and then someone else pays for the next time's activity, so if the dinner costs 120, then person B and C are in a 40 debt each to person A.
____________________________________________________________________________

I thought that I just should change the first (Transaction) class first and make the program work with that, and then change the rest of the program. I tried add a copy-, and a assignment constructor and a destructor. However I just got runtime errors so I feel pretty lost where I´ve failed.
I'd gladly accept some input.

TransactionJar_Dyn.cpp is the file im using with infile "pot.txt", and the program im using is Code::Blocks 10.05
T-Jar.cpp
pot.txt
TransactionJar-Dyn.cpp
0
Comment
Question by:rijku
  • 13
  • 12
  • 2
27 Comments
 
LVL 53

Accepted Solution

by:
Infinity08 earned 1000 total points
ID: 35705501
>> However I just got runtime errors

Whenever you have errors or other problems, please include the exact error messages you get (and a complete description of what's going wrong) in your question. Otherwise, it's a lot harder for us to help you.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 35705502
Why don't you just change your code to use a vector?
http://www.cplusplus.com/reference/stl/vector/

That's going to be far simpler (and safer) that doing lots of dynamic allocations all over the place and for the most part you should be able to work with a vector without changing much existing code since a vector is designed to have almost the same syntax and semantics as a normal C style array.
0
 

Author Comment

by:rijku
ID: 35711844
@evilrix  
Im supposed not to use vectors.

@Infinity08
I first get to the menu in my main where I can choose a number between 0-6. When I've entered a number, MS windows "the program have stopped working" window pops up and then in the application window i get
Process returned -1073741819 (0xC0000005)  or
Process returned 255 (OxFF)
depending on if I cancel respectively wait for the MS window to be done.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 53

Expert Comment

by:Infinity08
ID: 35711869
>> When I've entered a number

What number would that be ? Did you do anything else before entering that number ? Can you post the complete output of your code ?

Btw, I notice that you've never initialized the choice variable, so depending on the conditions, it might have the value 0, which would cause the while loop to be skipped entirely.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 35712427
>> Im supposed not to use vectors.

Hmmm, your comment "Im extending a old program I've made" would imply there are no restrictions on how you do this but that statement would imply this is possibly an assignment. Please clarify so that the experts can gauge their responses accordingly.

http://www.experts-exchange.com/help.jsp?hi=21

Other than that I'm going to leave you in Infinity08 expert hands as too many experts just make life confusing :)
0
 

Author Comment

by:rijku
ID: 35712834
@evilrix yeah sorry about that. yes it's an assignment so I dont want anyone to make a program for me but i would appreciate guidance or something like it.

@Infinity08 After I run the application, the first thing i do is enter a number, the menu shows itself automatically before that. I tried to input different (ranging from 0-6) numbers and the result is
Process returned -1073741819 (0xC0000005) or Process returned 255 (OxFF)
for every input as the screencast shows. Not just for 2 but for all numbers. I haven't seen why it returns differently from time to time.
I tried to initialize "choice" with negative and positive numbers but I didn't see any difference in doing so. However should I keep "choice" initialized? Is it preferable?

The methods I added in "TransactionJar_Dyn.cpp" is the copy constructor, assignment constructor and changed the destructor in the transaction class. All apart that is that i've changed the string friends[MAX_FRIENDS]; into string *friends; in the transaction class.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

const int MAX_PERSONS = 10;
const int MAX_TRANSACTIONS = 30;
const int MAX_FRIENDS = 10;

class Transaction
{
    private:
    string date;
    string type;
    string name;
    double amount;
    int num_friends;
    string *friends; // OLD: string friends[MAX_FRIENDS];

    public:
    Transaction();

    Transaction(int nSize,int v);

    ~Transaction();

    Transaction(const Transaction &t);

    string get_name();
    double get_amount();
    int get_num_friends();
    bool existFriend(string theeName);
    bool readATrans(istream &is);
    void writeATrans(ostream &os);
};

class Person
{
    private:
    string name;
    double paid_others;
    double debt;

    public:
    Person();
    Person(string n, double b, double s);
    double get_paid();
    double get_debt();
    void printOut_P();
};

class PersonList
{
    private:
    int num_persons;
    Person pers[MAX_PERSONS];

    public:
    PersonList();
    ~PersonList();
    void addAnotherP(Person pny);
    void printOutAndFix();
    double sumDebt();
    double sumPaid();
};

class TransactionsList
{
    private:
    Transaction trans[MAX_TRANSACTIONS];
    int numTrans;

    public:
    TransactionsList();
    ~TransactionsList();
    void loadin(istream &is);
    void printout_TL(ostream &os);
    void addMore_TL(Transaction &t);
    double totalcost();
    double havePaid(string theeName);
    double theDebt(string theeName);
    PersonList FixPersons();

    int showAddMore_TL();
};

/* ------------------- *
 * --- TRANSACTION --- *
 * ------------------- */
Transaction::Transaction()
:date(), type(), name(), amount(), num_friends(), friends()
{
}

Transaction::Transaction(int nSize, int v)
:date(), type(), name(), amount(), num_friends(), friends()
{
    if (num_friends > 0)
    {
        friends = new string[num_friends];
        for (int i = 0; i < num_friends; i++)
            friends[i] = v;
    }

    else
    {
        friends = 0;
    }
}

Transaction::Transaction(const Transaction &t)
:date(), type(), name(), amount(), num_friends(), friends()
{
    if (num_friends > 0)
    {
        friends = new string[num_friends];
        for (int i = 0; i < num_friends; i++)
            friends[i] = t.friends[i];
    }

    else
    friends = 0;
}

Transaction::~Transaction()
{
    delete [] friends;
}

string Transaction::get_name()
{
    return name;
}

double Transaction::get_amount()
{
    return amount;
}

int Transaction::get_num_friends()
{
    return num_friends;
}

bool Transaction::existFriend(string theeName)
{
    for (int i = 0; i < num_friends; i++)
    {
        if (theeName == friends[i])
        {
            return true;
        }
    }
    return false;
}

bool Transaction::readATrans(istream &is)
{
    is >> date >> type >> name >> amount >> num_friends;

    for (int i = 0; i < num_friends; i++)
    {
        is >> friends[i];
    }

    return is;
}

void Transaction::writeATrans(ostream &os)
{
    os << date << "\t" << type << "\t" << name << "\t" << amount << "\t" << num_friends << "\t";

    for (int i = 0; i < num_friends; i++)
    {
        os << friends[i] << " ";
    }

    os << endl;
}

/* ------------------------ *
 * --- TRANSACTIONSLIST --- *
 * ------------------------ */

TransactionsList::TransactionsList()
:numTrans()
{
    numTrans = 0;
}

TransactionsList::~TransactionsList()
{
}

void TransactionsList::loadin(istream &is)
{
    Transaction t;

    while (t.readATrans(is))
    {
        addMore_TL(t);
    }
}

void TransactionsList::printout_TL(ostream &os)
{
    for (int i = 0; i < numTrans; i++)
    {
        trans[i].writeATrans(os);
    }
}

void TransactionsList::addMore_TL(Transaction &t)
{
    trans[numTrans] = t;
    numTrans++;
}

int TransactionsList::showAddMore_TL()
{
    return numTrans;
}

double TransactionsList::totalcost()
{
    double expense = 0.0;

    for (int i = 0; i < numTrans; i++)
    {
        expense += trans[i].get_amount();
    }

    return expense;
}

double TransactionsList::havePaid(string theeName)
{
    double paid = 0.0;

    for (int i = 0; i < numTrans; i++)
    {
        if (theeName == trans[i].get_name())
        {
            paid += (trans[i].get_amount()) - ((trans[i].get_amount()) / (trans[i].get_num_friends()+1)); // /(trans[i].get_num_friends()+1);
        }
    }

    return paid;
}

double TransactionsList::theDebt(string theeName)
{
    double debt = 0.0;

    for (int i = 0; i < numTrans; i++)
    {
        if (trans[i].existFriend(theeName))
        {
            debt += (trans[i].get_amount())/(trans[i].get_num_friends()+1);
        }
    }

    return debt;
}

PersonList TransactionsList::FixPersons()
{
    PersonList pl = PersonList();
    string s_arr[MAX_PERSONS];
    int num_pers = 0;
    string name = "";

    for (int i = 0; i < numTrans; i++)
    {
        Transaction t = trans[i];

        name = t.get_name();
        bool nameExist = false;

        for ( int k = 0; k < num_pers; k++)
        {
            if (s_arr[k] == name)
            {
                nameExist = true;
            }
        }

        if(!nameExist)
        {
            s_arr[num_pers] = name;
            num_pers++;
        }
    }

    for(int i = 0; i < num_pers; i++)
    {
        name = s_arr[i];
        Person p = Person(name, havePaid(name), theDebt(name));
        pl.addAnotherP(p);
    }

    return pl;
}

/* -------------- *
 * --- PERSON --- *
 * -------------- */

Person::Person ()
:name(), paid_others(), debt()
{
}

Person::Person (string n, double b, double s)
:name(), paid_others(), debt()
{
    name = n;
    paid_others = b;
    debt = s;
}

double Person::get_paid()
{
    return paid_others;
}

double Person::get_debt()
{
    return debt;
}

void Person::printOut_P()
{
    cout << name << "\tPaid others: " << paid_others << "\tdebt: " << debt << endl;

    if (debt > paid_others)
    {
        cout << "Pot takes " << debt - paid_others << endl;
    }

    if (debt < paid_others)
    {
        cout << "Pot gives " << paid_others - debt << endl;
    }

    if (debt == paid_others)
    {
        cout << "Pot is happy! " << endl;
    }
}

/* ------------------ *
 * --- PERSONLIST --- *
 * ------------------ */

PersonList::PersonList()
:num_persons()
{
    num_persons = 0;
}

PersonList::~PersonList()
{
}

void PersonList::addAnotherP(Person pny)
{
    pers[num_persons] = pny;
    num_persons++;
}

void PersonList::printOutAndFix()
{
    for (int i = 0; i < num_persons; i++)
    {
        pers[i].printOut_P();
    }
}

double PersonList::sumDebt()
{
    double sd = 0.0;

    for ( int i = 0; i < num_persons; i++)
    {
        sd += pers[i].get_debt();
    }

    return sd;
}

double PersonList::sumPaid()
{
    double sp = 0.0;

    for ( int i = 0; i < num_persons; i++)
    {
        sp += pers[i].get_paid();
    }

    return sp;
}

/* ------------ *
 * --- MAIN --- *
 * ------------ */

int main()
{
    Transaction t;
    TransactionsList tl;
    Person p;
    PersonList pl;

    int choice = -1;
    string theeName;

    ifstream is("pot.txt");
    ofstream os("rewrite.txt");

    while (choice != 0)
    {
        cout << "What do you wanna do? Make your choice in the menu" << endl;
        cout << "0. Exit. All transactions will be saved to a file. " << endl;
        cout << "1. Write a transaction from the keyboard " << endl;
        cout << "2. Print out information from all transactions " << endl;
        cout << "3. Calculate the total cost. " << endl;
        cout << "4. How much is a specified person's debt? " << endl;
        cout << "5. How much have a person paid for others? " << endl;
        cout << "6. List all persons and fix. " << endl;
        cin >> choice;
        cout << endl;

        tl.loadin(is);

        switch(choice)
        {
            case 0:
            {
                tl.printout_TL(os);
                break;
            }

            case 1:
            {
                cout << "Please insert with space between " << endl << "[YYMMDD, type, name, numOfFriends, nameOffriends] " << endl;
                t.readATrans(cin);
                tl.addMore_TL(t);
                break;
            }

            case 2:
            {
                cout << "Num. of trans. = " << tl.showAddMore_TL() << endl;
                tl.printout_TL(cout);
                cout << endl;
                break;
            }

            case 3:
            {
                cout << "The total expenses are " << tl.totalcost() << endl << endl;
                break;
            }

            case 4:
            {
                cout << "Specify a name: " << endl;
                cin >> theeName;
                cout << theeName << "'s debt is " << tl.theDebt(theeName) << endl << endl;
                break;
            }

            case 5:
            {
                cout << "Specify a name: " << endl;
                cin >> theeName;
                cout << theeName << " has paid " << tl.havePaid(theeName) << endl << endl;
                break;
            }

            case 6:
            {
                pl = tl.FixPersons();
                pl.printOutAndFix();
                cout << endl;
                break;
            }

            default:
            {
                cout << "Please try again (0-6) " << endl;
            }
        }
    }

    return 0;
}

Open in new window

rijku-457114.flv
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 35712893
>> I tried to input different (ranging from 0-6) numbers and the result is
Process returned -1073741819 (0xC0000005) or Process returned 255 (OxFF)

In your Transaction class, you have this data member :

>>     string *friends; // OLD: string friends[MAX_FRIENDS];

but you don't allocate memory for this pointer before you call the readATrans method. And this method tries to access the memory that the pointer points to :

>>         is >> friends[ i ];

but since you haven't allocated memory for it yet, it fails.

You need to make sure that you allocate enough memory for the friends array, before you try to use it.



>> However should I keep "choice" initialized? Is it preferable?

Yes, it's a good habit to initialize your variables, since uninitialized variables can have any contents. And this often leads to unexpected behavior.
0
 

Author Comment

by:rijku
ID: 35715275
I see, but shouldn't it allocate memory in Transaction::Transaction(const Transaction &t) with
friends = new string[num_friends];    ?
Or should I add a method in style with "void Transaction::assign(const Transaction &t) which includes delete[], new[], and a for-loop to copy all the elements regarding the friends array? Otherwise, I am not sure of how to allocate sufficient memory.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 35715402
>> I see, but shouldn't it allocate memory in Transaction::Transaction(const Transaction &t) with

That's the copy constructor. But you're not using the copy constructor to construct the Transaction object. You're using the default constructor :

>>     Transaction t;

(in the TransactionsList::loadin method)
0
 

Author Comment

by:rijku
ID: 35715870
So I must change Transaction t; so it uses the copy constructor instead of the default-? I tried to figure it out with the help of http://en.wikipedia.org/wiki/Copy_constructor. But I didn't really get clear how to define it. To me, it would be something like this:
Transaction t = Transaction(); or like Transaction t; Transaction t2; t2 = t;
But It feels like there are some more to it.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 35716088
>> So I must change Transaction t; so it uses the copy constructor instead of the default-?

A copy constructor makes a copy of an existing object. Do you have an existing Transaction object to copy ?

Do you know how many items you'll put in the friends array ? Is there a maximum ? Do you either have a constructor that constructs a Transaction object from scratch, and makes sure to have enough room for the necessary amount of friends . Or can you alternatively make sure to do the necessary allocation otherwise ?
0
 

Author Comment

by:rijku
ID: 35730076
Hmm, well I got a file as ifstream which are being used in the loadin method?

I have no restrictions of minimum nor maximum values in the application.
I am a bit of unsure of this constructors still that you´re talking about. But what I believed and would prefer is that the constructor is in charge for all of the necessary allocation and I guess that's what I atleast have tried with.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 35732796
Then make sure that you let the constructor allocate the appropriate amount of memory.

Right now, you have 3 constructors :

1) the default constructor that allocates no memory
2) a constructor that takes a size as parameter, but doesn't use it (it was probably intended to allocate the given amount of memory)
3) a copy constructor
0
 

Author Comment

by:rijku
ID: 35748397
I have been thinking about how to use the parameters in the assignment constructor, I've tried to declare the size parameter in the initialization list, but, I don't know where to go from there, like how I should do to allocate sufficient memory with the parameter size and get it to a sufficient size.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 35748545
>> I've tried to declare the size parameter in the initialization list,

In the initialization list, you have this :

>> num_friends()

If you want to set num_friends to the nSize value passed as parameter to the constructor, you should use :

        num_friends(nSize)

instead.
0
 

Author Comment

by:rijku
ID: 35748793
Oh, sorry I missed linking code, anyway, I mean I've done what you described just now.
And don't know what I should be doing next, If there's something missing in relation to the constructors? Because the error is still here.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 35748822
Well, once you have initialized the member variables correctly, can you then ensure that enough memory is allocated for the friends array ?
0
 

Author Comment

by:rijku
ID: 35749005
Well, I feel unsure about this, but,  in the assignment operator I thought that I changed the size of the array to nSize and then allocated sufficient memory and then changed all elements to v.
And no, I can't ensure that while I feel unsure about this stuff still.
0
 

Author Comment

by:rijku
ID: 35764569
Now I've changed and added "0" to friends in the member initialization list in the default constructor, and I added: delete [] kompisar; kompisar = new string[ant_kompisar]; to the readATrans function.
I've also added a function for the "deep copy", and used it in the loadin function.
void Transaction::assign(const Transaction &t)
{
    // assign: actual object = t.

    num_friends = t.num_friends;

    if (num_friends > 0)
    {
        delete [] friends; // Release memory.
        friends = new string[ant_num_friends]; // Allocate new memory.

        for (int i = 0; i < num_friends; i++)
        {
            friends[i] = t.friends[i]; // Copy elements.
        }
    }
    else
    friends = 0; // NULL.
}

Open in new window

0
 
LVL 53

Expert Comment

by:Infinity08
ID: 35787103
>> No answer in quite some days now, and have come long way with new code

You didn't ask a question in quite some days, so I assumed you were just working on things.

In any case, the original question was about the crash that you experienced, and the reason for that was pointed out. If you haven't been able to resolve it with the advice given here, I'd be happy to assist you further.
0
 

Author Comment

by:rijku
ID: 35788546
Sorry If I was unclear! However I've been working on stuff, and added a new method called assign, which should work as "deep copy".

However I still get this error 0xC0000005 - access violation, and I don't really understand how I could prevent it, how I should change my code so it doesn't do that.

New code:


#include <fstream>
#include <iostream>
#include <string>
using namespace std;

const int MAX_PERSONS = 10;
const int MAX_TRANSACTIONS = 30;
const int MAX_FRIENDS = 10;

class Transaction
{
    private:
    string date;
    string type;
    string name;
    double amount;
    int num_friends;
    string *friends; // OLD: string friends[MAX_FRIENDS];

    public:
    Transaction();

    Transaction(int nSize,int v);

    ~Transaction();

    Transaction(const Transaction &t);

    void assign(const Transaction &t);

    string get_name();
    double get_amount();
    int get_num_friends();
    bool existFriend(string theeName);
    bool readATrans(istream &is);
    void writeATrans(ostream &os);
};

class Person
{
    private:
    string name;
    double paid_others;
    double debt;

    public:
    Person();
    Person(string n, double b, double s);
    double get_paid();
    double get_debt();
    void printOut_P();
};

class PersonList
{
    private:
    int num_persons;
    Person pers[MAX_PERSONS];

    public:
    PersonList();
    ~PersonList();
    void addAnotherP(Person pny);
    void printOutAndFix();
    double sumDebt();
    double sumPaid();
};

class TransactionsList
{
    private:
    Transaction trans[MAX_TRANSACTIONS];
    int numTrans;

    public:
    TransactionsList();
    ~TransactionsList();
    void loadin(istream &is);
    void printout_TL(ostream &os);
    void addMore_TL(Transaction &t);
    double totalcost();
    double havePaid(string theeName);
    double theDebt(string theeName);
    PersonList FixPersons();

    int showAddMore_TL();
};

/* ------------------- *
 * --- TRANSACTION --- *
 * ------------------- */
Transaction::Transaction()
:date(), type(), name(), amount(), num_friends(), friends(0)
{
}

Transaction::Transaction(int nSize, int v)
:date(), type(), name(), amount(), num_friends(nSize), friends()
{
    if (num_friends > 0)
    {
        friends = new string[num_friends]; // allocate memory.
        for (int i = 0; i < num_friends; i++)
            friends[i] = v;
    }

    else
    {
        friends = 0; // NULL-pointer.
    }
}

Transaction::Transaction(const Transaction &t)
:date(t.date), type(t.type), name(t.name), amount(t.amount), num_friends(t.num_friends), friends(t.friends)
{
    if (num_friends > 0)
    {
        friends = new string[num_friends]; // allocate new memory.
        for (int i = 0; i < num_friends; i++)
            friends[i] = t.friends[i]; // copy the elements.
    }

    else
    friends = 0; // NULL.
}

Transaction::~Transaction()
{
    delete [] friends;
}

string Transaction::get_name()
{
    return name;
}

double Transaction::get_amount()
{
    return amount;
}

int Transaction::get_num_friends()
{
    return num_friends;
}

bool Transaction::existFriend(string theeName)
{
    for (int i = 0; i < num_friends; i++)
    {
        if (theeName == friends[i])
        {
            return true;
        }
    }
    return false;
}

bool Transaction::readATrans(istream &is)
{
    delete [] friends;
    friends = new string[num_friends];

    is >> date >> type >> name >> amount >> num_friends;

    for (int i = 0; i < num_friends; i++)
    {
        is >> friends[i];
    }

    return is;
}

void Transaction::writeATrans(ostream &os)
{
    os << date << "\t" << type << "\t" << name << "\t" << amount << "\t" << num_friends << "\t";

    for (int i = 0; i < num_friends; i++)
    {
        os << friends[i] << " ";
    }

    os << endl;
}

void Transaction::assign(const Transaction &t)
{
    // Assign: actual object = t.

    num_friends = t.num_friends;

    if (num_friends > 0)
    {
        delete [] friends; // release memory.
        friends = new string[num_friends]; // Allocate memory.

        for (int i = 0; i < num_friends; i++)
        {
            friends[i] = t.friends[i]; // Copy elements.
        }
    }
    else
    friends = 0; // NULL.
}

/* ------------------------ *
 * --- TRANSACTIONSLIST --- *
 * ------------------------ */

TransactionsList::TransactionsList()
:numTrans()
{
    numTrans = 0;
}

TransactionsList::~TransactionsList()
{
}

void TransactionsList::loadin(istream &is)
{
    Transaction t;

    while (t.readATrans(is))
    {
        addMore_TL(t);
    }
}

void TransactionsList::printout_TL(ostream &os)
{
    for (int i = 0; i < numTrans; i++)
    {
        trans[i].writeATrans(os);
    }
}

void TransactionsList::addMore_TL(Transaction &t)
{
    trans[numTrans].assign(t); //trans[numTrans] = t;
    numTrans++;
}

int TransactionsList::showAddMore_TL()
{
    return numTrans;
}

double TransactionsList::totalcost()
{
    double expense = 0.0;

    for (int i = 0; i < numTrans; i++)
    {
        expense += trans[i].get_amount();
    }

    return expense;
}

double TransactionsList::havePaid(string theeName)
{
    double paid = 0.0;

    for (int i = 0; i < numTrans; i++)
    {
        if (theeName == trans[i].get_name())
        {
            paid += (trans[i].get_amount()) - ((trans[i].get_amount()) / (trans[i].get_num_friends()+1)); // /(trans[i].get_num_friends()+1);
        }
    }

    return paid;
}

double TransactionsList::theDebt(string theeName)
{
    double debt = 0.0;

    for (int i = 0; i < numTrans; i++)
    {
        if (trans[i].existFriend(theeName))
        {
            debt += (trans[i].get_amount())/(trans[i].get_num_friends()+1);
        }
    }

    return debt;
}

PersonList TransactionsList::FixPersons()
{
    PersonList pl = PersonList();
    string s_arr[MAX_PERSONS];
    int num_pers = 0;
    string name = "";

    for (int i = 0; i < numTrans; i++)
    {
        Transaction t;
        trans[i].assign(t); // t = trans[i];

        name = t.get_name();
        bool nameExist = false;

        for ( int k = 0; k < num_pers; k++)
        {
            if (s_arr[k] == name)
            {
                nameExist = true;
            }
        }

        if(!nameExist)
        {
            s_arr[num_pers] = name;
            num_pers++;
        }
    }

    for(int i = 0; i < num_pers; i++)
    {
        name = s_arr[i];
        Person p = Person(name, havePaid(name), theDebt(name));
        pl.addAnotherP(p);
    }

    return pl;
}

/* -------------- *
 * --- PERSON --- *
 * -------------- */

Person::Person ()
:name(), paid_others(), debt()
{
}

Person::Person (string n, double b, double s)
:name(), paid_others(), debt()
{
    name = n;
    paid_others = b;
    debt = s;
}

double Person::get_paid()
{
    return paid_others;
}

double Person::get_debt()
{
    return debt;
}

void Person::printOut_P()
{
    cout << name << "\tPaid others: " << paid_others << "\tdebt: " << debt << endl;

    if (debt > paid_others)
    {
        cout << "Pot takes " << debt - paid_others << endl;
    }

    if (debt < paid_others)
    {
        cout << "Pot gives " << paid_others - debt << endl;
    }

    if (debt == paid_others)
    {
        cout << "Pot is happy! " << endl;
    }
}

/* ------------------ *
 * --- PERSONLIST --- *
 * ------------------ */

PersonList::PersonList()
:num_persons()
{
    num_persons = 0;
}

PersonList::~PersonList()
{
}

void PersonList::addAnotherP(Person pny)
{
    pers[num_persons] = pny;
    num_persons++;
}

void PersonList::printOutAndFix()
{
    for (int i = 0; i < num_persons; i++)
    {
        pers[i].printOut_P();
    }
}

double PersonList::sumDebt()
{
    double sd = 0.0;

    for ( int i = 0; i < num_persons; i++)
    {
        sd += pers[i].get_debt();
    }

    return sd;
}

double PersonList::sumPaid()
{
    double sp = 0.0;

    for ( int i = 0; i < num_persons; i++)
    {
        sp += pers[i].get_paid();
    }

    return sp;
}

/* ------------ *
 * --- MAIN --- *
 * ------------ */

int main()
{
    Transaction t;
    TransactionsList tl;
    Person p;
    PersonList pl;

    int choice = -1;
    string theeName;

    ifstream is("pot.txt");
    ofstream os("rewrite.txt");

    while (choice != 0)
    {
        cout << "What do you wanna do? Make your choice in the menu" << endl;
        cout << "0. Exit. All transactions will be saved to a file. " << endl;
        cout << "1. Write a transaction from the keyboard " << endl;
        cout << "2. Print out information from all transactions " << endl;
        cout << "3. Calculate the total cost. " << endl;
        cout << "4. How much is a specified person's debt? " << endl;
        cout << "5. How much have a person paid for others? " << endl;
        cout << "6. List all persons and fix. " << endl;
        cin >> choice;
        cout << endl;

        tl.loadin(is);

        switch(choice)
        {
            case 0:
            {
                tl.printout_TL(os);
                break;
            }

            case 1:
            {
                cout << "Please insert with space between " << endl << "[YYMMDD, type, name, numOfFriends, nameOffriends] " << endl;
                t.readATrans(cin);
                tl.addMore_TL(t);
                break;
            }

            case 2:
            {
                cout << "Num. of trans. = " << tl.showAddMore_TL() << endl;
                tl.printout_TL(cout);
                cout << endl;
                break;
            }

            case 3:
            {
                cout << "The total expenses are " << tl.totalcost() << endl << endl;
                break;
            }

            case 4:
            {
                cout << "Specify a name: " << endl;
                cin >> theeName;
                cout << theeName << "'s debt is " << tl.theDebt(theeName) << endl << endl;
                break;
            }

            case 5:
            {
                cout << "Specify a name: " << endl;
                cin >> theeName;
                cout << theeName << " has paid " << tl.havePaid(theeName) << endl << endl;
                break;
            }

            case 6:
            {
                pl = tl.FixPersons();
                pl.printOutAndFix();
                cout << endl;
                break;
            }

            default:
            {
                cout << "Please try again (0-6) " << endl;
            }
        }
    }

    return 0;
}

Open in new window

0
 
LVL 53

Expert Comment

by:Infinity08
ID: 35788764
>> and I don't really understand how I could prevent it, how I should change my code so it doesn't do that.

In order to fix it, you have to first figure out where it crashes.

If you run your code in a debugger, it'll clearly point you to the line that caused the access violation. And once you know where it is, you can figure out what went wrong (again with the help of the debugger).
0
 

Author Comment

by:rijku
ID: 35789456
I finally figured out how to run the debugger and also I got this from the debugger. (Code Blocks also notifies about a "segmentation fault")
#0 00000000	0x00407050 in std::operator>><char, std::char_traits<char>, std::allocator<char> >() 
#1 00402685	Transaction::readATrans(this=0x22f600, is=@0x22fad4) 					(D:\gakusei\programming\TransactionJar_DynSecond.cpp	:181)
#2 00402CF5	TransactionsList::loadin(this=0x22f708, is=@0x22fad4) 					(D:\gakusei\programming\TransactionJar_DynSecond.cpp	:237)
#3 0040439D	main() 											(D:\gakusei\programming\TransactionJar_DynSecond.cpp	:473)

Open in new window

which considers the lines 181. in Transaction::readATrans
is >> friends[i];

Open in new window

237.in TranscationsList::loadin method.
while (t.readATrans(is))

Open in new window

and 473. in the main method.
tl.loadin(is);

Open in new window


About 181. im not really sure why it fails, all i can guess is that it bounds outside the array or that it's some problem with the memory allocation.
I guess that line 273 is the same problem as line 181.
Line 473 seems to be tracing back to line 181.
If I understand this right is line 181 where it crashes.
Am I anywhere right?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 35791366
You've indeed identified the line where it crashes.

Now, have a close look at the Transaction::readATrans function.

You allocate memory for num_friends friends :

>>     friends = new string[num_friends];

But then you read in a new value of num_friends here :

>>     is >> date >> type >> name >> amount >> num_friends;

and you use this new value for storing data in the friends array :

>>     for (int i = 0; i < num_friends; i++)


What happens if the new num_friends value is bigger than the one used for allocating memory ?
0
 

Author Comment

by:rijku
ID: 35807230
Ok, thanks I solved that! Now I can see the "num_friends" and "friends" part of the Transactions when running.
However, I have continued with the other classes now, and encountered errors when I changed the other arrays which feels confusing.
#0 00402837	Transaction::assign(this=0x0, t=@0x22fbb0) 		cpp:221)
#1 00402F29	TransactionsList::addMore_TL(this=0x22fee8, t=@0x22fbb0)cpp:285)
#2 00402E4A	TransactionsList::loadin(this=0x22fee8, is=@0x22fcac) 	cpp:271)
#3 0040473A	main() 							cpp:584)

Open in new window

Line 221 is num_friends = t.num_friends; in Transaction::assign method, which was working before I changed the other arrays.
Line 285 is trans[numTrans].assign(t); in TransactionList::addMore_TL, which I previously changed with the Transaction class. And the other lines refer to Line 285. If I understand it right, is it that it refers wrong (e.g. this=0x22fee8, t=@0x22fbb0)?
Also I feel unsecure on which constructors and methods to use, I usually go with "the rule of three" but when I tried to make a assignment as in the Transaction class, i got errors
pers = new Person[num_persons]; // allocate memory.
        for (int i = 0; i < num_persons; i++)
            pers[i] = v;

Open in new window

in the third line, so dont know if im making anything wrong or if this constructor isn't neccessary in this class. Got the same problem when I tried it with a correlative constructor in the TransactionList class. However, at the moment I only have copy constructors.
I know that you helped me solve the initial problem I asked for, but if it's okay I would like further guidance, if not, say the word
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 35807363
>> #0 00402837      Transaction::assign(this=0x0, t=@0x22fbb0)             cpp:221)

That would indicate that the object for which the assign method is not valid (this=0x0).


>>             pers[ i ] = v;

Is v the right type ? Do you have an operator= for the Person class ?
0
 

Author Comment

by:rijku
ID: 35808385
>> Is v the right type ? Do you have an operator= for the Person class ?

I made an operator= in PersonList too and used the assignments inside it in a if(this != &pl), and it did stop bothering me now, and I hope it's a working way. I only have overloading assignment operators in the Transaction class now.

I've added a operator= in the Person class and I also had Segmentation fault, but, it was solved when I added this (Including the errors mentioned in my last post.).
const Person & Person::operator= (const Person &p)
{
    if(this != &p) // protects against invalid self-assignment.
    {
    }
    return *this;
}

Open in new window

Now, the choice 2 works, but the segfault "this.0x0" remains in choice 1. However, Im a bit unsure on what I should add in the if-statements brackets . I would like something like delete[] and new there, but i get a bit confused because there's no *array in the Person class

Additionally, does PersonList::addAnotherP method need some further development?
void PersonList::addAnotherP(Person pny)
{
    //pers[num_persons].assign(pny);
    pers[num_persons] = pny;
    num_persons++;
}

Open in new window

Because addMore_TL method had the commented part instead of the second line between the brackets. I've been figuring how I in that case would be able to add a assign method, but don't get it quite right, because of, again, that the class Person don't have an *array.
Im not sure what else could be changed,but it feels pretty obvious that I missed out on some copying business.. Because the result right now with the *pers included instead of the static one is only num_friends, and friends shown in the transactions, (choice 2 or ostream file) and when I include *trans nothing is in the transactions.

At the moment I have default constructor, destructor, operator= and copy constructor in all classes except Person that only have operator= as newly added stuff.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

571 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question