Thread: OOP gone WILD!!!

  1. #1
    Kiss the monkey. CodeMonkey's Avatar
    Join Date
    Sep 2001
    Posts
    937

    OOP gone WILD!!!

    Here is yet another example of my overbearing tendency to tackle new projects without enough planning. This is my constantly-in-development money managing program. I recently tried to implement a logging system (line saved in file for ever deposit/withdrawl) with what I though was great success until... It happened. I don't know what went wrong, but as you will see in the code, there comes an error in this fashion: main() -> CommandSwitch() -> loadfile() -> ReadInAccounts() ->(in the log case) SaveAccount() -> ACCNT::~ACCNT() -> array<string>::~array<string>() -> basic_string::vector deleting destructor -> operator delete(void*) -> free(void*) -> UNHANDLED EXCEPTION ERROR: CRASH.

    This object is the culprit: array<string> log;

    I know this must have something to do with deleting unallocated data, or acessing deleted data or SOMETHING. I just can't find where. Any line followed by '//DEBUG' in my code is just for debugging purposes.

    Any ideas are appreciated. HERE'S A CODE DUMP. I excluded most of the code as to save anybody who's willing to read any. The problemed parts are bolded: (problemed, according to MSVC++ 6 debugger)

    Code:
    
    ACCNT::~ACCNT()
    {
    }
    
    
    int ACCNT::operator =(ACCNT other)
    {
    	withdraw(-1,NULL,true);
    	deposit(other.GetBalance(),NULL,true);
    	label(other.GetName());
    	SetIDNumber(other.GetIDNumber());
    	SetAccountNum(other.GetAccountNum());
    	if(other.GetNumLogEntries() == 0)
    		Log.purge();
    	else
    	{
    		cout << other.GetLog()[0] << endl; //DEBUG
    		//Log = other.GetLog();
    	}
    	
    	return 1;
    }
    
    array<string> & ACCNT::GetLog()
    {
    	return Log;
    }
    
    
    
    BANK::BANK()
    {
    	AccountPointer = 0;
    
    	full = false;
    
    	edited = false;
    
    	NumOfAccounts = 0;
    	
    	for(int x = 0; x < MAX_NUM_ACCOUNTS; x++)
    	{
    		AccountsMap[x] = 0;
    	}
    
    }
    
    
    int BANK::SaveAccount(ACCNT InputAccount, bool UsedInCreation)
    {
    	cout << InputAccount.GetName() << endl;//DEBUG
    	if(!UsedInCreation)
    	{
    		if(!edited)
    			edited = true;
    	}
    
    	if(AccountsMap[InputAccount.GetIDNumber()] == 0)
    		return -1;
    	else if(AccountsMap[InputAccount.GetIDNumber()] == 1)
    	{
    		cout << "Inside Save account: going to use = operator" << endl;//DEBUG
    		Accounts[InputAccount.GetIDNumber()] = InputAccount;
    		cout << "Done equalizing" << endl;//DEBUG
    	}
    	else
    		return -1;
    
    	return 0;
    }
    
    int BANK::ReadInAccounts(const char* FileName,bool purgeAccounts)
    {
    	SCRIPT_POSITION read_state = ACC_NUM;
    	char buffer[1024];
    	ifstream Reader(FileName);
    	bool active = true;
    	ACCNT CurrentAccount;
    
    	if(purgeAccounts)
    		purge();
    
    	if(Reader.fail())
    		return -1;
    
    	while(active)
    	{
    		switch(read_state)
    		{
    		case ACC_NUM:
    			{
    				Reader.getline(buffer,1024);
    				if(Reader.eof())
    				{
    					active = false;
    					break;
    				}
    				if(strlen(buffer) > 2)
    				{
    					if(buffer[0] == '/' && buffer[1] == '/')
    						continue;
    				}
    				CurrentAccount = CreateAccount(atoi(buffer),0,"~null~");
    				read_state = NAME;
    			}break;
    		case NAME:
    			{
    				Reader.getline(buffer,1024);
    				if(Reader.eof())
    				{
    					active = false;
    					break;
    				}
    				if(strlen(buffer) > 2)
    				{
    					if(buffer[0] == '/' && buffer[1] == '/')
    						continue;
    				}
    				CurrentAccount.label(buffer);
    				SaveAccount(CurrentAccount,true);
    				read_state = MONEY;
    			}break;
    		case MONEY:
    			{
    				Reader.getline(buffer,1024);
    				if(Reader.eof())
    				{
    					active = false;
    					break;
    				}
    				if(strlen(buffer) > 2)
    				{
    					if(buffer[0] == '/' && buffer[1] == '/')
    						continue;
    				}
    				CurrentAccount.deposit(atof(buffer),"Creation",true);
    				SaveAccount(CurrentAccount,true);
    				read_state = LOG;
    			}break;
    		case LOG:
    			{
    				cout << "Log reader" << endl;//DEBUG
    
    				Reader.getline(buffer,1024);
    
    				cout << "Read log line" << endl;//DEBUG
    				//DEBUG
    				if(Reader.eof())
    				{
    					active = false;
    					break;
    				}
    				if(strlen(buffer) > 2)
    				{
    					if(buffer[0] == '/' && buffer[1] == '/')
    						continue;
    				}
    				if(!strcmpi(buffer,"ENDLOG"))
    				{
    					cout << "Endlog found" << endl;//DEBUG
    					read_state = ACC_NUM;
    					break;
    				}
    				else
    				{
    					cout << "Going to add entry" << endl; //DEBUG
    					CurrentAccount.AddLogEntry(buffer);
    					cout << "Added Entry\nGoing to save account." << endl;//DEBUG
    					if(CurrentAccount.GetNumLogEntries() > 0)//debug
    						cout << "Data at ReadInAccounts(): " << CurrentAccount.GetLogEntry(CurrentAccount.GetNumLogEntries() - 1) << endl;//debug
    					SaveAccount(CurrentAccount,true);
    					cout << "Account Saved" << endl;//DEBUG
    				}
    				//Log entry example:
    				//Thu Jan 16 12:44:01 1998~1045.66~WITHDRAW 45.66~1000~Ordered lots of pizza
    			}break;
    		default:
    			{
    			}break;
    		}
    	}
    	return 0;
    }
    
    void ACCNT::AddLogEntry(string entry)
    {
    	Log.resize(Log.GetSize() + 1);
    	Log[Log.GetSize() - 1] = entry;
    }
    
    string ACCNT::GetLogEntry(int index)
    { 
    	return (index > Log.GetSize() && index >= 0) ? "~ERROR~" : Log[index];
    }
    Code:
    //ARRAYCL.H - a template that allows users to pass arrays as variables//
    ///(a.k.a. CodeMonkey's custom vector)////////////////////////////////
    
    #ifndef _ARRAYCL_H
    #define _ARRAYCL_H
    
    template <class T>
    class array
    {
    public:
    	array(int input_size)
    	{
    		size = input_size;
    		Data = new T[input_size];
    	}
    
    	array()
    	{
    		size = 0;
    		Data = NULL;
    	}
    
    	void purge()
    	{
    		size = 0;
    		delete [] Data;
    	}
    
    	~array()
    	{
    		delete [] Data;
    	}
    
    	T & operator [] (int index)
    	{
    		if(index >= 0 && index <= size)
    			return Data[index];
    		else 
    			exit(1);
    	}
    
    	operator T*()
    	{
    		return Data;
    	}
    
    	const T & operator [] (int index) const
    	{
    		if(index >= 0 && index <= size)
    			return Data[index];
    		else 
    			exit(1);
    	}
    
    	const array & operator = (const array<typename T> & other)
    	{
    		if(this != &other)
    		{
    			delete [] Data;
    			size = other.GetSize();
    			Data = new T[size];
    			for(int x = 0; x < size; x++)
    				Data[x] = other[x];
    		}
    		return *this;
    	}
    
    	int GetSize() const
    	{
    		return size;
    	}
    
    	void resize(int newSize)
    	{
    		int numToCopy = newSize < size ? newSize : size; //First time I used this operator: HAH!
    
    		T * newData = new T[newSize];
    
    		for(int x = 0; x < numToCopy; x++)
    		{
    		   newData[x] = Data[x];
    		}
    		delete [] Data;           
    		size = newSize;
    		Data = newData;
    	}
    protected:
    
    	int size;
    	T* Data;
    };
    
    #endif
    Code:
    //Class that holds an array of strings and can convert string to strings, etc.
    //All done by David Goffredo (CodeMonkey), October 22, 2003
    //Requires the "array class", a custom vector template I made.
    
    #ifndef _SENTENCE_H
    #define _SENTENCE_H
    
    //#define TRUE_SENT     If you want a sentence to end at punctuation:
    //							turn off if you will be using punctuation
    //							for non-gramatical purposes (command-line, etc.)
    
    #include <string>
    #include <arraycl.h>
    
    using namespace std;
    
    struct _SentenceType
    {
    	bool exclamatory;
    	bool declarative;
    	bool interrogative;
    	bool imperitive;
    	void reset()
    	{
    		exclamatory = declarative = interrogative = imperitive = false;
    	}
    };
    
    typedef _SentenceType SentenceType;
    
    class sentence : public array<string>
    {
    public:
    	sentence(int numWords)
    	{
    		size = numWords;
    		Data = new string[numWords];
    		type.reset();
    	}
    
    	sentence()
    	{
    		size = 0;
    		Data = NULL;
    		type.reset();
    	}
    
    	sentence(string value)
    	{
    		size = 0;
    		BreakDown(value);
    		type.reset();
    	}
    
    	int BreakDown(string  s_input)
    	{
    		short int* where = new short int[s_input.length() +1];
    		short int where_place = 0;
    
    		for(int x = 0; x <= s_input.length() + 1; x++)
    		{
    			if(s_input[x] == ' ')
    			{
    				where[where_place] = x;
    				where_place++;
    			}
    			else if(s_input[x] == '\0' 
    #ifdef TRUE_SENT
    				|| s_input[x] == '.' || s_input[x] == '?' || s_input[x] == '!'
    #endif
    				)
    			{
    				where[where_place] = x;
    				where[where_place +1] = -1;
    				where_place++;
    				break;
    			}
    		}
    		resize(where_place);
    
    		if(where_place < 1)
    			Data[0] = s_input.substr(0,where[where_place]);
    		else if(where[where_place] == s_input.length() + 1)
    			where_place--;
    		else
    		{
    			Data[0] = s_input.substr(0,where[0]);
    			for(int y = 0; y < where_place - 1; y++)
    			{
    				Data[y + 1] = s_input.substr(where[y] + 1, where[y + 1] - (where[y] + 1) );
    			}
    		}
    
    		return 0;
    	}
    
    	string print(bool end_punctuation)
    	{
    		string ReturnValue;
    		for(int x = 0; x < size; x ++)
    		{
    			if(x > 0)
    				ReturnValue += " ";
    			ReturnValue += Data[x];
    		}
    		if(end_punctuation)
    		{
    			if( (type.declarative + type.imperitive + type.interrogative + type.exclamatory) > 0)
    			{
    				if( (type.declarative || type.imperitive) && type.interrogative)
    				{
    					ReturnValue += " ";
    				}
    				else if(type.exclamatory)
    				{
    					if(type.interrogative)
    					{
    						ReturnValue += "?!";
    					}
    					else
    						ReturnValue += "!";
    				}
    				else if(type.declarative || type.imperitive)
    					ReturnValue += ".";
    				else if(type.interrogative)
    					ReturnValue += "?";
    			}
    			else 
    				ReturnValue += " ";
    		}
    
    		return ReturnValue;
    	}
    
    	int numOfWords() const
    	{
    		return size;
    	}
    
    	SentenceType type;
    };
    #endif
    "If you tell the truth, you don't have to remember anything"
    -Mark Twain

  2. #2
    Kiss the monkey. CodeMonkey's Avatar
    Join Date
    Sep 2001
    Posts
    937
    This is the data file I have the program read, which is read in ReadInAccounts().

    test2.txt:
    Code:
    00001
    Main Account
    1000.00
    Wed Jan 15 2:34:55 1998~1000~DEPOSIT 45.66~1045.66~Birthday money
    Thu Jan 16 12:44:01 1998~1045.66~WITHDRAW 45.66~1000~Ordered lots of pizza
    ENDLOG
    //You can create a comment that is really long, and all will be fine.
    00002
    Fat People
    67.08
    ENDLOG
    00003
    Fatter People
    88.09
    ENDLOG
    "If you tell the truth, you don't have to remember anything"
    -Mark Twain

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. OOP flu
    By Hussain Hani in forum General Discussions
    Replies: 15
    Last Post: 06-27-2009, 02:02 AM
  2. wild pointers
    By ravi rajeev in forum C Programming
    Replies: 3
    Last Post: 04-02-2007, 05:39 AM
  3. Data Mapping and Moving Relationships
    By Mario F. in forum Tech Board
    Replies: 7
    Last Post: 12-14-2006, 10:32 AM
  4. recommendation for a good OOP book
    By Mario F. in forum C++ Programming
    Replies: 2
    Last Post: 06-15-2006, 04:28 PM
  5. OOP Theory Question
    By Zeusbwr in forum C++ Programming
    Replies: 2
    Last Post: 10-30-2005, 08:37 AM