Hi, I'm trying to update an objects information within my linked list but for some reason after attempting to alter the data no changes appear to have taken place. As far as I am aware I'm not updating a copy of the object because I am finding the relevant object (and this does work) and then creating a pointer to the address of the found object and then updating it's contents. The exact same code works if I use a vector but not when I use my own linked list (which I need to implement because this is for an imporatant assignment).

bool Bank::withdraw(double amount, int index)
{
	Account *a = &theAccounts.at(index);
	if(a->getBalance() >= amount)
	{
		a->withdraw(amount);//problem is here
		return true;
	}
	else
		return false;
}

Above is the code that should be withdrawing money from an account but when I check the data after this method is called it displays it's original value (before withdrawal). Debugging showed me that the calculations etc. were all performed which is why I feel that somehow I am still only updating a copy.

I've attached my linked list files and also the bank files. Any help is greatly appreciated, I have an assignment deadline very soon :s

Attachments
#include "Bank.h"

void Bank::Init()
{
	numCustomers = 0;
	numAccounts = 0;
	numMortgages = 0;
}

void Bank::addCustomer(Customer *newCustomer)
{
	numCustomers++;
	theCustomers.push_back(newCustomer);
}

void Bank::displayAllCustomers()
{
	int i;
	for (i = 0; i < theCustomers.size(); ++i)
	{
		theCustomers.at(i).toString();
	}
}

int Bank::customerSearch(unsigned int custNum)
{
	int i;
	for(i = 0; i < theCustomers.size(); ++i)
	{
		Customer c = theCustomers.at(i);
		if(c.getCustNum() == custNum)
		{
			return i;
		}
	}
	return -1;
}

void Bank::removeCustomer(unsigned int custNum)
{
	int index;
	//Firstly find the accounts associated with the customer and erase them
	eraseCustAccounts(custNum);
	//Secondly, delete the customer object itself
	index = customerSearch(custNum);
	if(index != -1)
	{
		theCustomers.erase(index);
		numCustomers--;
	}
	else
	{
		cout << "Could not find customer searched for" << endl;
	}
}

Customer Bank::assignCustomer(int index)
{
	Customer c = theCustomers.at(index);
	return c;
}

void Bank::addAccount(Account *newAccount)
{
	numAccounts++;
	theAccounts.push_back(newAccount);
}

void Bank::displayCustAccounts(unsigned int custNum)
{
	int i;
	for(i = 0; i < theAccounts.size(); ++i)
	{
		if(theAccounts.at(i).getAccHolderNum() == custNum)
		{
			cout << "\n" << endl;
			cout << "Account Type: " << theAccounts.at(i).getType() << endl;
			cout << "Account Number: " << theAccounts.at(i).getAccountNum() << endl;
			cout << "Balance: " << theAccounts.at(i).getBalance() << endl;
			cout << "\n" << endl;
		}
	}
}

void Bank::eraseCustAccounts(unsigned int custNum)
{
	int i;
	for(i = 0; i < theAccounts.size(); ++i)
	{
		if(theAccounts.at(i).getAccHolderNum() == custNum)
		{
			removeAccount(i);
		}
	}
}

void Bank::removeAccount(int index)
{
	theAccounts.erase(index);
	numAccounts--;
}

int Bank::getAccountIndex(unsigned int accNum)
{
	int i;
	for(i = 0; i < theAccounts.size(); ++i)
	{
		Account a = theAccounts.at(i);
		if(a.getAccountNum() == accNum)
		{
			return i;
		}
	}
	return -1;
}

bool Bank::withdraw(double amount, int index)
{
	Account *a = &theAccounts.at(index);
	if(a->getBalance() >= amount)
	{
		a->withdraw(amount);
		return true;
	}
	else
		return false;
}

bool Bank::deposit(double amount, int index)
{
	Account *a = &theAccounts.at(index);
	if(amount > 0)
	{
		a->deposit(amount);
		return true;
	}
	else
		return false;
}

void Bank::addMortgage(Mortgage *newMortgage)
{
	numMortgages++;
	theMortgages.push_back(newMortgage);
}
#ifndef _BANK_H_
#define _BANK_H_

#include "Customer.h"
#include "Account.h"
#include "Mortgage.h"
#include "myList.h"
#include "myList.cpp"

using namespace std;

class Bank{
	int numCustomers;
	int numAccounts;
	int numMortgages;

	List<Customer> theCustomers;
	List<Account> theAccounts;
	List<Mortgage> theMortgages;

public:
	//General functions
	void Init();
	void displayAllCustomers();

	//Manipulation of Customers
	void addCustomer(Customer  *c);
	int customerSearch(unsigned int custNum);
	void removeCustomer(unsigned int custNum);
	Customer assignCustomer(int index);

	//Manipulation of Accounts
	void addAccount(Account *a);
	void displayCustAccounts(unsigned int custNum);
	void eraseCustAccounts(unsigned int custNum);
	void removeAccount(int index);
	int getAccountIndex(unsigned int accNum);
	bool withdraw(double amount, int index);
	bool deposit(double amount, int index);


	//Manipulation of Mortgages
	void addMortgage(Mortgage *m);
};
#endif
#include "myList.h"

template<class Type>
void List<Type>::add(Type *newData)
{
	Node<Type> *newNode = new Node<Type>(*newData);

	if(head != 0)
	{
		newNode->next = head;
		head = newNode;
		noEntries++;
	}
	else
	{
		newNode->next = head;
		head = newNode;
		tail = newNode;
		noEntries++;
	}
}

template<class Type>
void List<Type>::push_back(Type *newData)
{
	Node<Type> *newNode = new Node<Type>(*newData);

		if(head != 0)
		{
			tail->next = newNode;
			tail = newNode;
			noEntries++;
		}
		else
		{
			tail = newNode;
			head = newNode;
			noEntries++;
		}
}

//start at the head of the list
//delete items as you move along
//stop when at the end i.e. when
//the next pointer value is 0
/*template<class Type>
List<Type>::~List()
{
	while(head!=0)
	{
		Node<Type> *temp = head;
		head = head->next;
		delete temp;	//delete what temp points at!
	}
}*/


template<class Type>
Type List<Type>::at(int index)
{
	Node<Type> *temp = head;
	int i;
	for(i = 0; i < index; ++i)
	{
		temp = temp->next;
	}

	return temp->dataItem;
}

template<class Type>
int List<Type>::size()
{
	int i = 1;
	Node<Type> *temp = head;

	while(temp != tail)
	{
		temp = temp->next;
		++i;
	}
	return i;
}

template<class Type>
void List<Type>::erase(int index)
{
	Node<Type> *temp;//needs to be temp = new Node<Type>(*someData);
	temp->dataItem = at(index);
	delete temp;
	//Might actually need to use the destructor at this point in which case it would be
	//something like ~Node(temp); where that deletes all variables and references relating to temp
}
#ifndef _MYLIST_H_
#define _MYLIST_H_

#include <iostream>
using namespace std;

template<class Type>		//Forward decleration of the List class
class List;

template<class Type>
class Node{
public:
	Type dataItem;
	Node *next;
	Node(Type nodeData)
	{
		dataItem = nodeData;
		next = 0;
	}
	~Node<Type>(){}
	friend class List<Type>;
};

template<class Type>
class List{
	Node<Type> *head;
	Node<Type> *tail;
	int noEntries;

public:
	List<Type>(){head = 0; tail = 0; noEntries = 0;}
	//~List<Type>(){;}//doesn't seem to like this yet....
	Node<Type> *returnHead() const{return head;}
	Node<Type> *returnTail() const{return tail;}
	void add(Type *nodeData);
	void push_back(Type *nodeData);
	Type at(int index);
	int size();
	void erase(int index);
	int isEmpty(){return head == 0;}
	//ostreams go here
};

#endif //_MYLIST_H_

OK, well take another look at your code...
When the Bank::withdraw function is called, a pointer to the relevant account is obtained. If the account balance is >= the amount, then the withdraw function is called for the account pointed to by the account pointer.

Therefore if the accounts balance is not getting adjusted when Bank::withdraw is called then your problem is actually in the Account::withdraw function.
So there's nothing wrong with any of the code you've posted here. The problem is in Account::withdraw. Therefore the question is what does the Account::withdraw function look like? (You haven't posted it!)

Cheers for now,
Jas.

It's literally just this...

void withdraw(double amount)
	{
		balance -= amount;
	}

I'll attach the file that this is done in but I'm nearly 100% sure it's not this method because when used with a vector this did the job

Attachments
#ifndef _ACCOUNT_H_
#define _ACCOUNT_H_

#include "Customer.h"
#include "myList.h"
#include <string>

using namespace std;

class Account{
protected:
	static unsigned int nextAccountNum;
	unsigned int accountNum;
	double balance;
	double creditLimit;
	double interestRate;
	string accountType;
	Customer accHolder;

public:

////////////////////////////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////////////////
	//Account Constructors
	////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
	/*Account()
	{
		accountNum = nextAccountNum;
		nextAccountNum++;
	}*/
	Account(){;}

	Account(Customer accHolder, string accountType, double balance, double creditLimit, double interestRate)
	{
		Account::accHolder = accHolder;
		Account::accountType = accountType;
		Account::balance = balance;
		Account::creditLimit = creditLimit;
		Account::interestRate = interestRate;
		accountNum = nextAccountNum;
		nextAccountNum++;
	}

	Account(Customer accHolder, string accountType, double balance, double interestRate)
	{
		Account::accHolder = accHolder;
		Account::accountType = accountType;
		Account::interestRate = interestRate;
		Account::balance = balance;
		accountNum = nextAccountNum;
		nextAccountNum++;
	}

	Account(Customer accHolder, string accountType, double balance)
	{
		Account::accHolder = accHolder;
		Account::accountType = accountType;
		Account::balance = balance;
		accountNum = nextAccountNum;
		nextAccountNum++;
	}

////////////////////////////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////////////////
	//Account Manipulation
	////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

	//Add money to account
	void deposit(double amount)
	{
		balance += amount;
	}

	//Withdraw money from account
	void withdraw(double amount)
	{
		balance -= amount;
	}

	//Add interest to balance
	void addInterest()
	{
		balance *= (1 + interestRate/100.0);
	}

	//One time initialisation of any necessary variables
	void initialise();

////////////////////////////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////////////////
	//Get and Set methods
	////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

	void setInterestRate(double rate){interestRate = rate;}
	void setCreditLimit(double limit){creditLimit = limit;}
	//void setAccNum(int num){accountNum = num;}
	
	double getBalance(){return balance;}
	double getCreditLimit(){return creditLimit;}
	double getInterestRate(){return interestRate;}
	unsigned int getAccountNum(){return accountNum;}
	unsigned int getAccHolderNum(){return accHolder.getCustNum();}
	string getAccHolderName(){return accHolder.getName();}
	string getType(){return accountType;}

};
#endif //_ACCOUNT_H_

I've created a very simple class to test some of the functionality....

#include "Customer.h"
#include "Bank.h"

unsigned int Customer::nextCustNum = 1;
unsigned int Account::nextAccountNum = 1001;

int main()
{
	int i;
	Bank theBank;

	//Customer information
			string name;
			string address;
			Date *dob;
			int dd;
			int mm;
			int yyyy;
			string telNo;
			char sex;

			cout << "Please enter customers name: " << endl;
			cin >> name;
			cout << "Please enter customers address: " << endl;
			cin >> address;
			cout << "Please enter customers telephone number: " << endl;
			cin >> telNo;
			cout << "Please enter customers date of birth: " << endl;/*Validate this section*/
			cout << "Day (dd): " << endl;
			cin >> dd;
			cout << "Month (mm): " << endl;
			cin >> mm;
			cout << "Year(yyyy): " << endl;
			cin >> yyyy;
			cout << "Please enter customers sex: " << endl;
			cin >> sex;

			dob = new Date(dd, mm, yyyy);

	Customer *c = new Customer(name, address, telNo, dob, sex);
	theBank.addCustomer(c);

	theBank.displayAllCustomers();

	string type = "JuniorAccount";
	double balance = 100.0;
	double interestRate = 10.0;
	Account *a = new Account(*c, type, balance, interestRate);
	theBank.addAccount(a);

	Account a2 = theBank.assignAccount(0);

	cout << a2.getBalance() << endl;
	theBank.withdraw(90.0, 0);
	//a2.setBalance(10.0);
	cout << a2.getBalance() << endl;

	cin >> i;


	return 0;
}

If I use the commented out setBalance method then it does actually change the customers balance but when I use the withdraw nothing happens....As already mentioned, debugging shows the withdraw calculation being performed but then when the method returns the debugger shows the balance back to its previous value...I'm confused as to why this is happening though.

The most obvious possibility, but maybe the least likely, is that the prototype withdraw() post #3 line 1 and function call to withdraw, post #4 line 54 do not match with regard to number of parameters. I suspect however that this is a "posting/typo" error and probably not what the code actually looks like.

Actually it's not a typo or anything, they're just two seperate functions. Withdraw in 'bank' which takes an amount and an index and then withdraw in Account.h which takes the amount passed by the former withdraw method and uses this to actually deduct the amount from an accounts balance attribute

It's literally just this...

void withdraw(double amount)
	{
		balance -= amount;
	}

I'll attach the file that this is done in but I'm nearly 100% sure it's not this method because when used with a vector this did the job

Hmmm, that's odd. That looks like it should correctly update the objects balance. Have you tried using the this pointer to refer to the balance?
e.g.

this->balance -= amount;

That might just do the trick!
If that doesn't work (and I can't see why it shouldn't!), I also noticed that in your constructor you're setting the balance using:

Account::balance = balance;

So perhaps as a last resort you could try adjusting the balance like this:

Account::balance -= amount

Other than that, I can't see anything obvious there!
Cheers for now,
Jas

Still no luck...
I feel like it's something really obvious that I'm overlooking but I can't quite put my finger on it

OK, if you need a fresh pair of eyeballs to go over the code, .zip up all of the source files for your project and post it here as an attachment, I'd be more than happy to take a look at it for you!

Cheers for now,
Jas.

Edited 7 Years Ago by JasonHippy: n/a

I've managed to solve it finally :)
Even though, as far as I can see, it's still virtually doing the same as what I had programmed initially it seems to be running fine now.
Instead of storing objects using my template like '<Customer>' for example....I am now storing them as pointers like this '<Customer*>'. This did mean I had to change a lot of code to use '->' instead of '.' etc. but now its updating balances, accounts and customers fine.

I'd just like to say a massive thanks to everyone that has helped with suggestions and especially JasonHippy for showing such eagerness to help :)
Problem solved!

This question has already been answered. Start a new discussion instead.