Thread: Calculator + LinkedList

  1. #1
    Registered User
    Join Date
    Apr 2005
    Posts
    18

    Unhappy Calculator + LinkedList

    Hi
    can you please help me and tell me where is the error
    the code compile but it crash i don't know what is wrong
    here is my code 9 files

    1-calcCommand.h
    Code:
     #ifndef CALCCOMMANDH
    #define CALCCOMMANDH
    
    #include <string>
    using std::string;
    
    /**
    This class implements a CalcCommand. A CalcCommand object can be used to store
    an operation that was done on a calculator. CalcCommand objects can be linked
    togheter in a LinkedList by means of their getNext () and setNext () methods.
    This class is fully implemented and can be used as is.
    
    @author Tom Artoos.
    */
    
    class CalcCommand
    {
        private:
    		//MyRef string doesn't support white space??!!! 
            string fOperand;            //125...etc
            string fOperation;          // +,-,*,..etc
            string fDescription;        // messege
            CalcCommand* fNext;
            
        public:
            CalcCommand ();
            CalcCommand (string operand, string operation, string description);
            CalcCommand (const CalcCommand& cmd); //MyRef;copy constructor
            
            string getOperand () const;
            string getOperation () const;
            string getDescription () const;
            string toString ();// ???
    
            //MyRef:the seter will pass the argument by refrence
            void setOperand (const string& operand);
            void setOperation (const string& operation);
            void setDescription (const string& description);
            
            // Members that allow CalcCommands to be in a LinkedList
    		//MyRef: they are the seter and the geter of "fNext"
            CalcCommand* getNext () const;
            void setNext (CalcCommand* next);
    };
    #endif
    2-linkedlist.h
    Code:
    #ifndef LINKEDLISTH
    #define LINKEDLISTH
    
    #include "calccommand.h"
    
    /**
    Implement this LinkedList as a list of CalcCommands. Provide the necessary
    constructor, destructor, etc... The List has three methods:
    
    void push (CalcCommand* cmd): adds a dynamically allocated CalcCommand object
        to the end of the list.
    CalcCommand getFirst (): returns a reference to the first CalcCommand object
        in the list.
    void clear (): removes all CalcCommand objects from the list and frees their
        memory
    bool isEmpty (): returns true when the list is empty
    
    The methods in the list should be sufficient for the application at hand. A
    typical code snippet that retrieves all elements in the list looks like this:
        
        if (!list -> isEmpty ())
        {
            CalcCommand* iter = list -> getFirst ();
            while (iter != 0)
            {
                cout << iter -> toString ();
                iter = iter -> getNext ();
            }
        }
    
    @author Tom Artoos
    */
    
    class LinkedList
    {
        private:
            CalcCommand* fFirst;
            
        public:
            LinkedList ();
            LinkedList (LinkedList& list);
            ~LinkedList ();
            LinkedList& operator= (LinkedList& list);
            
            void push_back (CalcCommand* data);
            void clear ();
            
            CalcCommand* getFirst () const;
            bool isEmpty () const;
    };
    #endif
    3 - calculator.h

    Code:
    #ifndef CALCULATORH
    #define CALCULATORH
    #include "utils.h"
    #include "linkedlist.h"
    #include <string>
    using std::string;
    
    /**
    This class represents a basic calculator. It contains a number of methods that
    represent the supported operations (add, subtract, etc...). Each of these 
    operations take one operand and they all work on the internally stored subresult
    the following is an example:
        
        calc -> add ("125");
        
        1. convert string 125 to double
        2. take fSubResult and do fSubResult += 125
        3. log the operation with the logCommand method
            - operation = +
            - operand = 125
            - description = free to choose
        4. if all went well return true, else return false
        5. log an error when the operation failed (logCommand)
            - operation = ERROR
            - operand = operand that was given
            - description = error description
    
    The following are special methods:
        
        reset: reset the internal subresult to 0 and clear the command history
        getResult: return the current subresult
        getHistory: returns a pointer to the internal command history list
        logCommand: adds a CalcCommand object to the internal command history list
        
    @author Tom Artoos
    */
    
    class Calculator
    {
        private:
            LinkedList* fCommandHistory;
            double fSubResult;
            
        protected:
            void logCommand (string operation, string operand, string description);
        
        public:
            Calculator ();
            ~Calculator ();
            
            bool add (const string& operand);
            bool subtract (const string& operand);
            bool divide (const string& operand);
            bool multiply (const string& operand);
            bool sqrtC (const string& operand);
            bool powC (const string& operand);
            void reset ();
            
    		void setStart(const string subResult);
            string getResult ();
            LinkedList* getCommandHistory () const;
    };
    #endif
    4 - utils.h // help functions

    Code:
    #ifndef UTILSH
    #define UTILSH
    
    #include <string>
    #include <sstream>
    #include <cstdlib>
    #include <cctype>
    using namespace std;
    
    bool isValidDouble (string data);
    double stringToDouble (string data);
    string doubleToString (double data);
    
    #endif
    5 - calccommand.cpp

    Code:
    #include "calccommand.h"
    #include <cstdio>
    #include <string>
    
    CalcCommand::CalcCommand ()//waseem;default constructor 
    {fNext = 0;}
    
    CalcCommand::CalcCommand (string operand, string operation, string description)
    {
        fOperand = operand;
        fOperation = operation;
        fDescription = description;
        fNext = 0; // set the pointer to 0
    }
    
    CalcCommand::CalcCommand (const CalcCommand& cmd)//copy constructor
    {
    	fNext = 0;
        fOperand = cmd.getOperand ();
        fOperation = cmd.getOperation ();
        fDescription = cmd.getDescription ();
        fNext = cmd.getNext ();
    }
    
    string CalcCommand::getOperand () const
    {
        return fOperand;
    }
    
    string CalcCommand::getOperation () const
    {
        return fOperation;
    }
    
    string CalcCommand::getDescription () const
    {
        return fDescription;
    }
    
    
    string CalcCommand::toString ()
    {
        int bufsize = fOperation.size() + fOperand.size() + fDescription.size() + 3;
        char* buffer = new char [bufsize];
        sprintf (buffer, "%s\t%s\t%s\n", fOperation.c_str(), fOperand.c_str(), 
            fDescription.c_str()); //myref C_str() will return the string that passed into it
        string str (buffer);
        delete buffer;
        return str;
    }
    
    void CalcCommand::setOperand (const string& operand)
    {
        fOperand = operand;
    }
    
    void CalcCommand::setOperation (const string& operation)
    {
        fOperation = operation;
    }
    
    void CalcCommand::setDescription (const string& description)
    {
        fDescription = description;
    }
    
    void CalcCommand::setNext (CalcCommand* next)
    {
        fNext = next;
    }
    
    CalcCommand* CalcCommand::getNext () const
    {
        return fNext;
    }
    6 - linkedlist.cpp

    Code:
    #include "linkedlist.h"
    
    LinkedList::LinkedList ():fFirst(0){} // default constructor 
    LinkedList::~LinkedList (){clear ();} // destructor
    
    //copy constructor
    LinkedList::LinkedList (LinkedList& list)
    {
        CalcCommand* end = 0;
    	CalcCommand* temp = list.fFirst;
    	/**
    	list.fFirst still not assigned to any value ...
    	list.fFirst i think it's one number 
    	CalcComand * end or *temp is pointing to one number also */
    	while (temp) 
        {
    		//in the example "CalcCommand* el = new CalcCommand (temp)" this didn't work here
    		CalcCommand* el = new CalcCommand (*temp); 
    		
    		el -> setNext (0); 
    		if (!fFirst) fFirst = el; // if there is no item in the list
    		// el will poit to the first node
    		else end -> setNext(el);
    		end = el;
    		temp = temp -> getNext();
        }  
    }
    
    //Assignment operator 
    LinkedList& LinkedList::operator= (LinkedList& list)
    {
        clear ();
    	
    	CalcCommand* end = 0;
    	CalcCommand* temp = list.fFirst;
    	while (temp) 
        {
    		CalcCommand* el = new CalcCommand (*temp);
    		
    		el -> setNext (0);
    		if (!fFirst) fFirst = el;
    		else end -> setNext(el);
    		end = el;
    		temp = temp -> getNext();
    	}
    	return *this;
    } 
    
    //Returns the first element
    CalcCommand* LinkedList::getFirst () const {return fFirst;}
    
    //Pushes an element in the back of the list.
    void LinkedList::push_back (CalcCommand* data)
    {
    	
    	CalcCommand* temp = fFirst;
        while (temp -> getNext () != 0)
        {
            temp = temp -> getNext ();
        }
        
    	temp -> setNext (data);//this will add data to the end of the list
    	data -> setNext (0); //and this will set the one after the end of the list to NULL
    }
    
    void LinkedList::clear ()
    {
    	CalcCommand* temp = 0;
    	while (fFirst) 
        {
    		temp = fFirst;
    		fFirst = fFirst -> getNext();
    		delete temp;
    	}
    	fFirst = 0;
    }
    
    bool LinkedList::isEmpty () const
    {
    	if (!fFirst) return true;
    	else return false;
    }
    7- calculator.cpp

    Code:
    #include "calculator.h"
    #include <math.h>
    #include <iostream>
    using namespace std;
    
    Calculator:: Calculator ():fCommandHistory(0) , fSubResult(0){} //DEFAULT CONSTRUCTOR
    Calculator::~Calculator (){reset ();} //Calculator Destructor
    
    // How can i use this (LinkedList* fCommandHistory) ?
    // i can't call the seter functions of CalcComand "they are public"??
    
    //log command mesthod 
    void Calculator::logCommand (string operation, string operand, string description)
    {
    	fCommandHistory->push_back(new CalcCommand (operand,operation,description));
    }
    
    //Calculation Methods
    bool Calculator::add (const string& operand)
    {
    	if (isValidDouble (operand))
    	{
    		fSubResult += stringToDouble (operand);
    		logCommand ("+",operand,"Add ");
    		return true;
    	}
    	else logCommand ("Adding number",operand,"Faild"); 
    	return false;
    }
    
    bool Calculator::subtract (const string& operand)
    {
    	if (isValidDouble (operand))
    	{
    		fSubResult -= stringToDouble (operand);
    		logCommand ("-",operand,"subtract");
    		return true;
    	}
    	else logCommand ("Subtraction number",operand,"faild"); 
    	return false;
    }
    
    bool Calculator::divide (const string& operand)
    {
    	if (isValidDouble (operand))
    	{
    		fSubResult /= stringToDouble (operand);
    		logCommand ("/",operand,"divide");
    		return true;
    	}
    	else logCommand ("dividing number",operand,"Faild"); 
    	return false;
    }
    
    bool Calculator::multiply (const string& operand)
    {
    	if (isValidDouble (operand))
    	{
    		fSubResult *= stringToDouble (operand);
    		logCommand ("*",operand,"multiply");
    		return true;
    	}
    	else logCommand ("multiplay number",operand,"Faild"); 
    	return false;
    }
    bool Calculator::sqrtC (const string& operand)
    {
    	if (isValidDouble (operand))
    	{
    		fSubResult =sqrt( stringToDouble (operand));
    		logCommand ("sqrt",operand,"sqrt");
    		return true;
    	}
    	else  logCommand ("sqrt",operand,"Faild");
    	return false;
    }
    bool Calculator::powC (const string& operand)
    {
    	if (isValidDouble (operand))
    	{
    		fSubResult = pow(fSubResult,stringToDouble (operand));
    		logCommand ("+",operand,"pow");
    		return true;
    	}
    	else logCommand ("pow",operand,"Faild"); 
    	return false;
    }
    
    void Calculator::setStart(const string subResult)
    {
    	if (isValidDouble (subResult))
    	{
    		fSubResult = stringToDouble (subResult);
    	}
    	else cout<<"error input , input wil be set to 0"<<endl; 
    	fSubResult=0;
    }
    
    LinkedList* Calculator:: getCommandHistory () const {return fCommandHistory;}
    
    string Calculator::getResult () 
    {
    	return doubleToString (fSubResult);
    	reset ();
    }
    
    void Calculator::reset ()
    {
    	fSubResult = 0;
    	fCommandHistory= 0;
    }
    8 - utils.cpp

    Code:
    #include "utils.h"
    
    /**
    This method runs a simple check on the string data to verify that it is a valid
    double number.
    */
    
    bool isValidDouble (string data)
    {
        bool decpointcnt = 0;
        for (int i = 0; i < data.size(); i++)
        {
            if (isdigit(data[i]) == 0)
            {
                // if the char is no digit...
                if (data[i] != '.' && data[i] != '-') return false; // '.' the point od decimal
                else if (data[i] == '-' && i != 0) return false;//'-' for min numbers
                else if (data[i] == '.' && decpointcnt > 0) return false; //'.' can be only once
                
                if (data[i] == '.' && decpointcnt == 0) ++decpointcnt;
            }
        }
                        
        return true;
    }
    
    /**
    Converts a string into a double value. This function only produces reliable
    results if data contains a valid double number. Use isValidDouble to verify
    this.
    */
    double stringToDouble (string data)
    {
        return atof (data.c_str());  /*MyRef atof is a function included in <cstdlib> 
           & it take a parameter whitch is a pointer to string and it returns double **/ 
    }
    
    /**
    Converts any double number into a string.
    */
    string doubleToString (double data)
    {
        stringstream stream;
        stream << data;
        string result;
        stream>>result;
        stream.clear ();
        return result;
    }
    9 - main.cpp

    Code:
    #include <iostream>
    #include <stdlib.h>
    #include "Calculator.h"
    using std::string;
    
    using namespace std;
    
    int main ()
    {
    	string operand ;
    	string start   ;
    	char operation ='?';
    	bool finish = true ;
    	Calculator cal;
    
    	cout<<"\t\t\tCalculator\n"<<endl;
    
    	cout<<"\tEnter White space Between numbers and Operations!!\n"<<endl;
    
    	cout<<" \t --------------------------------------  "<<endl;
    	cout<<" \t| [+] Add number  [-] Substruct Number |"<<endl;
    	cout<<" \t|[*] Multiply    [/] Divide           |"<<endl;
    	cout<<" \t| [§] Sqrt        [^] Power            |"<<endl;
    	cout<<" \t| [=] Show result                      |"<<endl;
    	cout<<" \t -------------------------------------- "<<endl;
    	cout<<"\n\nYour Calulation = ";
    
    	
    	cin>>start;
    	cal.setStart(start);
    	
    	do
    	{
    		finish = true;
    		cin>>operation;
    		switch (operation)
    		{
    			case '+' :	
    						cin>>operand;
    						cal.add(operand);
    						break;
    			case '-':	
    						cin>>operand;
    						cal.subtract(operand);
    						break;
    			case '*' :
    						cin>>operand;
    						cal.multiply(operand);
    						break;
    			case '/' :	
    						cin>>operand;
    						cal.divide(operand);
    						break;
    			case '§' : 
    						cin>>operand;
    						cal.sqrtC(operand);
    						break;
    			case '^' :
    						cin>>operand;
    						cal.powC(operand);
    						break;
    			case '=' :
    						finish =false;
    						cout<<"Result = "<<cal.getResult();
    						break;
    			default :
    						finish =false;
    						cout<<"Unknow input"<<endl;
    		}
    	}while (finish = true);
    
    	
    
    	return 0;
    }

    and please tell me how can i print the hole linked list befor i delete it
    thanks for your help

  2. #2
    People Love Me
    Join Date
    Jan 2003
    Posts
    412
    Quote Originally Posted by maro009
    Hi
    can you please help me and tell me where is the error
    the code compile but it crash i don't know what is wrong
    here is my code 9 files and please tell me how can i print the hole linked list befor i delete it
    thanks for your help
    You gotta be freaking kidding me.

    Ever heard of kinda narrowing it down and telling us what the compiler error is, and showing us the most significant lines of code?

  3. #3
    essence of digital xddxogm3's Avatar
    Join Date
    Sep 2003
    Posts
    589
    i didn't look at your full code, but to print the linked list, all you have to do is cycle through the list and print the data at each location.
    "Hence to fight and conquer in all your battles is not supreme excellence;
    supreme excellence consists in breaking the enemy's resistance without fighting."
    Art of War Sun Tzu

  4. #4
    Registered User
    Join Date
    Apr 2005
    Posts
    18
    Quote Originally Posted by Krak
    You gotta be freaking kidding me.

    Ever heard of kinda narrowing it down and telling us what the compiler error is, and showing us the most significant lines of code?
    as i told you it compile and the compiler doesn't give any error but it crash
    i try to debug but i couldn't find it also but i think the eroor is in linkelist.cpp "push_back" function
    is that what you mean?

    You gotta be freaking kidding me.
    i'm beginner in c++

  5. #5
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    zip up your project and ill take a look, im not trawling thru that lot except with a debugger in an ide.
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

  6. #6
    Registered User
    Join Date
    Apr 2005
    Posts
    18
    it seems that i can't upload zip files , i rename it to txt file.
    just rename the file to calculator.zip
    thanks

  7. #7
    Let's do some coding! Welshy's Avatar
    Join Date
    Mar 2005
    Location
    Staffordshire University, UK
    Posts
    168
    I wouldnt really call that beginners work, especially if your using linked lists

  8. #8
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    Just for the future: try to code smaller parts of the program, compile and test it. If it crashes you know what part of the code you added so you check that part of the code. Repeat until the program is finished. This way you dont have 9 files to go through to find a runtime error, you might have a function instead.
    STL Util a small headers-only library with various utility functions. Mainly for fun but feedback is welcome.

  9. #9
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    Ffirst when first used is a null pointer. perhaps you should add a sentinel node to the front of your list to act as the head node so your list is always at least 1 node long.
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

  10. #10
    Registered User
    Join Date
    Apr 2005
    Posts
    18
    Quote Originally Posted by Shakti
    Just for the future: try to code smaller parts of the program, compile and test it. If it crashes you know what part of the code you added so you check that part of the code. Repeat until the program is finished. This way you dont have 9 files to go through to find a runtime error, you might have a function instead.
    yes i did this already and i know that the problem is in linkedlist.cpp " not sure"
    in this function :
    Code:
    void LinkedList::push_back (CalcCommand* data)
    {
    	
    	CalcCommand* temp = fFirst;
        while (temp -> getNext () != 0)
        {
            temp = temp -> getNext ();
        }
        
    	temp -> setNext (data);//this will add data to the end of the list
    	data -> setNext (0); //and this will set the one after the end of the list to NULL
    }

  11. #11
    Registered User
    Join Date
    Jun 2004
    Posts
    722
    Quote Originally Posted by maro009
    yes i did this already and i know that the problem is in linkedlist.cpp " not sure"
    in this function :
    Code:
    void LinkedList::push_back (CalcCommand* data)
    {
    	
    	CalcCommand* temp = fFirst;
        while (temp -> getNext () != 0) // if temp == null, then boom
        {
            temp = temp -> getNext ();
        }
        
    	temp -> setNext (data);//this will add data to the end of the list
    	data -> setNext (0); //and this will set the one after the end of the list to NULL
    }
    What happens when temp is null before the cicle ?!? Can fFirst be null when there are no commands ?? I don't know, haven't look at the rest of the code.

  12. #12
    Registered User
    Join Date
    Apr 2005
    Posts
    18
    Quote Originally Posted by Stoned_Coder
    Ffirst when first used is a null pointer. perhaps you should add a sentinel node to the front of your list to act as the head node so your list is always at least 1 node long.
    can you explain with code please ?

  13. #13
    Registered User
    Join Date
    Apr 2005
    Posts
    18
    i found one error
    i set the pointer fNext to NULL
    when i try to test if fNext is NULL in while loop using getnext function , this will call get function and return NULL
    here is the code
    Code:
    void LinkedList::push_back (CalcCommand* data)
    {
    	
    	CalcCommand* temp = fFirst;
        while (temp -> getNext () != 0) // get next will return fNext = NULL
        {
            temp = temp -> getNext ();
        }
        
    	temp -> setNext (data);//this will add data to the end of the list
    	data -> setNext (0); //and this will set the one after the end of the list to NULL
    }

  14. #14
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    read xeraths comment. it says it all. You use a list thats not there. fFirts is NULL on first use so temp is also NULL. This is your problem.
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

  15. #15
    Registered User
    Join Date
    Jun 2004
    Posts
    722
    Code:
    void LinkedList::push_back (CalcCommand* data){
    	CalcCommand* temp = fFirst;
    	if(temp == NULL){
    		// you complete
    	}else{
    		while (temp -> getNext () != 0){
    			temp = temp -> getNext ();
    		}
    		temp -> setNext (data);
    		data -> setNext (0);
    	}
    }

Popular pages Recent additions subscribe to a feed