I'm working on exception handling. Here is my code, I need some help..

Requirements:
=> If the user push a value to stack when stack is full,it must throw an exception of type "cInvalidPush".
=> If the user pop a value from stack when stack is empty , it must throw an exception of type "cInvalidPop" .
=> The class "cInvalidPush" is inherited from the class "cInvalidStack" .
=> The class "cInvalidPop"is inherited from the class "cInvalidStack" .
=> In the exception classes mentioned above, their objects must be able to store error message in them.
=> Create an object of CStack in main and show how you would catch the exceptions if any of above occurs.

class that holds the prototype of all functions:

#include<iostream>
    #include<stdexcept>
    using namespace std;

    class CStack //holds the prototype of functions
    {
        private:
            int size; //holds size of stack
            int top; //contains the index value of array from where the value will be pushed and poped
            int *ptr_stk; //points to an array of integer
            int isFull() const; //returns 1 if stack is empty otherwise 0
            int isEmpty() const; //returns 1 if stack is full otherwise 0
        public:
        CStack(int=10); //default size for the stack is 10
        ~CStack();
        void push(const int); //push the value in array of integers pointed by int *ptr_stk
        int pop();  //pop the value array of integers pointed by int *ptr_stk from the top of stack
    }; //end class CStack

and now here is the defintion of all prototypes:

int CStack::isEmpty() const
    {
        if(top==0)
         return 1;
        else
        return 0;
    }

    int CStack ::isFull() const
    {
        if (top==size)
         return 1;
        else
         return 0; 
    }

    CStack::CStack(int stackSize)
    {
        size=stackSize;
        ptr_stk=new int[size]; //allocates the pointer-based space

        for(int i=1;i<=size;i++)
         ptr_stk[i]=0;
    }

    void CStack::~CStack()
    {
        delete [] ptr_stk; //de-allocates the space
    }

    void CStack::push(const int val)
    {
        int decision1;
        decision1=isFull();
        if(decision1==1)
         throw cInvalidPush;
        else
         for(int j=1;j<=top;j++)
         {
            ptr_stk[i]=val;
         }
    }

    void CStack::pop()
    {
        int decision2;
        decision2=isEmpty();
        if(decision2==1)
         throw cInvalidPop;
        else
         delete [] ptr_stk;
    }

I made two classes for exception:

class cInvalidPush:public cInvalidStack //exception if stack is full
    {
        public:
            cInvalidPush():cInvalidStack("Stack if full.")
            {
            }
    }; //end class 

    class cInvalidPop:public cInvalidStack //exception if stack is empty
    {
        public:
            cInvalidPop():cInvalidStack("Stack is empty.")
            {
            }
    }; //end class

but i don't know what to write in class cInvalidStack? it was mentioned in the question that these two classes are inherited from class cInvalidStack...
My second question is can anyone tell me what to write in it's main() ?
because I'm throwing two exceptions in my program. Rather one of them occurs at a time. So how to handle two exceptions in one catch? and how to make its TRY block?
Oh, i tried and here it is:

int main()
    {
        CStack obj; //instantiating object
        int value;
        while(cin>>value)
        {
            try
            {
            cout<<"enter the value in stack: "<<endl;
            obj.push(value);
            }
            catch
            {
                /*no idea?
                */
            }
        }

        return 0;
    }

Can anyone complete it please? and one other thing how to handle the data member top ?

Recommended Answers

All 23 Replies

Yes, I could help you, but I will not.

very well then. thank you.

Since you have supplied the most part of the code ... you might like to see this little further 'edit' that might help you to continue ...

Edit: use a C++ 11 or greater compiler

// CStack.h //


#include <iostream>
#include <string>
#include <stdexcept>

// using namespace std;

class cInvalidStack : public std::exception
{
protected:
    std::string msg;
public:
    cInvalidStack( const std::string& msg = "" ) : msg(msg) {}
    virtual std::string& what() = 0;
} ;



class cInvalidPush : public cInvalidStack //exception if stack is full
{
public:
    cInvalidPush() : cInvalidStack( "Stack is full." ) {}
    std::string& what() { return msg; }

} ; //end class

class cInvalidPop: public cInvalidStack //exception if stack is empty
{
public:
    cInvalidPop():cInvalidStack( "Stack is empty." ) {}
    std::string& what() { return msg; }

} ; //end class




class CStack // holds the prototype of functions //
{
private:
    int* ptr_stk; //points to an array of integer
    int top; //contains the index value of array from where the value will be pushed and poped
    int max_size;
public:
    CStack (const int stackSize = 10 ); //default size for the stack is 10
    ~CStack();

    void push( const int ); //push the value in array of integers pointed by int *ptr_stk
    int pop();  //pop the value array of integers pointed by int *ptr_stk from the top of stack

    int isFull() const; //returns 1 if stack is empty otherwise 0
    int isEmpty() const; //returns 1 if stack is full otherwise 0
    int size() const { return top; } // returns  size of stack
} ; //end class CStack


CStack::CStack( int stackSize ) : top(0), max_size(stackSize)
{
    ptr_stk = new int[max_size]; //allocates the pointer-based space
    for( int i = 0; i < max_size; ++ i ) ptr_stk[i] = 0;
}
CStack::~CStack()
{
    delete [] ptr_stk; //de-allocates the space
    ptr_stk = 0;
    top = 0;
    max_size = 0;
}

void CStack::push( const int val )
{
    if( ! isFull() ) ptr_stk[top++] = val;
    else throw cInvalidPush();
}
int CStack::pop()
{
    if( ! isEmpty() ) return ptr_stk[--top];
    else throw cInvalidPop();
}

int CStack ::isFull() const
{
    if( top == max_size ) return 1;
    else return 0;
}
int CStack::isEmpty() const
{
    if( top == 0 ) return 1;
    else return 0;
}

And now a little test program, edited from yours ...

// test_CStack.cpp //

/*
Requirements:
    => If the user push a value to stack when stack is full,
       it must throw an exception of type "cInvalidPush".
    => If the user pop a value from stack when stack is empty,
       it must throw an exception of type "cInvalidPop" .
    => The class "cInvalidPush" is inherited from the class "cInvalidStack" .
    => The class "cInvalidPop"is inherited from the class "cInvalidStack" .
    => In the exception classes mentioned above, their objects must be able to store error message in them.
    => Create an object of CStack in main and show how you would catch the exceptions if any of above occurs.

    ... but i don't know what to write in class cInvalidStack?
    it was mentioned in the question that these two classes are inherited from class cInvalidStack...

    My second question is can anyone tell me what to write in it's main() ?
    because I'm throwing two exceptions in my program.
    Rather one of them occurs at a time.
    So how to handle two exceptions in one catch?
    and how to make its TRY block?

    Oh, i tried and here it is:
*/

#include "CStack.h"

int main()
{
    CStack obj(3); // use small stack for testing //

    std::cout << "Enter a value to push on stack: " << std::flush;
    int value;
    while( std::cin >> value )
    {
        try
        {
            obj.push(value);
            std::cout << "obj.size() = " << obj.size() << '\n';
        }
        catch( cInvalidStack& ex )
        {
            std::cout << ex.what() << '\n';
            std::cout << "obj.size() = " << obj.size() << '\n';
        }
        std::cout << "Enter a value to push on stack (q to quit): " << std::flush;
    }
    std::cin.clear();
    std::cin.sync();

    while( ! obj.isEmpty() )
    {
        std::cout << "obj.pop() = " << obj.pop() << '\n';
        std::cout << "obj.size() = " << obj.size() << '\n';
    }


    try
    {
        std::cout << "obj.pop() = " << obj.pop() << '\n';
    }
    catch( cInvalidStack& ex )
    {
        std::cout << ex.what() << '\n';
    }


    std::cout << "\nPress 'Enter' to continue/exit ... " << std::flush;
    std::cin.get();

}

Thank you so much David ,You made it simple for me :)
One question regarding your code is that What if I write only cout instead of std::cout and all other streams?

What if I write only cout instead of std::cout and all other streams?

You already know the answer to this. Seriously, it's time to start thinking for yourself.

And I'm using Dev-c++ as a beginner ...I don't know how to use c++ 11...

Yeah moschops I'll try it finding myself :)

I'm using Dev-Cpp 5.11 TDM-GCC 4.9.2.
What do you think about this?

I'm using Dev-Cpp 5.11 TDM-GCC 4.9.2.
What do you think about this?

That's the latest Orwell build, so that should be fine.

Yeah I saw that .Thank you :)

David!
My Dev-C++ compiler is still giving two errors as follows:

[Error] looser throw specifier for 'virtual cInvalidStack::~cInvalidStack()'
[Error] overriding 'virtual std::exception::~exception() throw ()'

Agh! I'm stuck in this code.

With your Dev compiler ...

1) make sure you HAVE pre-set ... to compile as C++ 11

2) make sure the pointer width is 64 bit

3) make sure to compile with 64 bit release

Other settings than the above seem to be problematic with your Dev compiler

3rd setting is Ok. I'm compiling my every code with 64 bit release.
But from where to check the other two?
Can you guide me?

re. 2)
tools
compiler options
settings
code generation
compile width ... pointer width ... select 64 bit

re. 1)
tools
compiler options
settings
code generation
language standard ... select either C++ 11 option

And while your setting up your compiler turn on warnings (click on):
tools
compiler options
settings
code generation
warnings
select ... these 3 ... -Wall, -Wextra, -pedantic

Since I have not heard further ... I presume you have 'the example' working ok?

Here is a little upgrade to demo the ease of editing that code to a 'template'.

// CStack.h //  // 2015-08-03 //


// use a C++ 11 (or newer) compiler //

#include <iostream>
#include <string>
#include <stdexcept>

// using namespace std;

class cInvalidStack : public std::exception
{
protected:
    std::string msg;
public:
    cInvalidStack( const std::string& msg = "" ) : msg(msg) {}
    virtual std::string& what() = 0;
} ;



class cInvalidPush : public cInvalidStack // throw if stack is full
{
public:
    cInvalidPush() : cInvalidStack( "Stack is full." ) {}
    std::string& what() { return msg; }
} ; 

class cInvalidPop: public cInvalidStack // throw if stack is empty
{
public:
    cInvalidPop():cInvalidStack( "Stack is empty." ) {}
    std::string& what() { return msg; }
} ;



template< typename T >
class CStack 
{
public:
    CStack (const size_t stackSize = 10 ); 
    ~CStack();

    // copy ctor...
    CStack( const CStack& cstk )
    {
        top = cstk.top;
        max_size = cstk.max_size;
        ptr_stk = new T[max_size];
        for( size_t i = 0; i < top; ++ i ) ptr_stk[i] = cstk.ptr_stk[i];
        for( size_t i = top; i < max_size; ++ i ) ptr_stk[i] = T();
    }
    // overloaded operator ==
    CStack& operator == ( const CStack& cstk )
    {
        if( this != &cstk )
        {
            delete ptr_stk;

            top = cstk.top;
            max_size = cstk.max_size;
            ptr_stk = new T[max_size];
            for( size_t i = 0; i < top; ++ i ) ptr_stk[i] = cstk.ptr_stk[i];
            for( size_t i = top; i < max_size; ++ i ) ptr_stk[i] = T();
        }
        return *this;
    }

    bool exists( const T& val ) const
    {
        for( size_t i = 0; i < top; ++ i )
        {
            if( ptr_stk[i] == val ) return true;
        }
        return false;
    }

    void push( const T& ); 
    T pop();

    bool isFull() const; 
    bool isEmpty() const; 
    size_t size() const { return top; } 
    size_t capacity() const { return max_size; }
private:
    T* ptr_stk;
    size_t top;
    size_t max_size;
} ;


template< typename T >
CStack< T >::CStack( size_t stackSize ) : top(0), max_size(stackSize)
{
    ptr_stk = new T[max_size];
    for( size_t i = 0; i < max_size; ++ i ) ptr_stk[i] = T();
}
template< typename T >
CStack< T >::~CStack()
{
    delete [] ptr_stk;
    ptr_stk = 0;
    top = 0;
    max_size = 0;
}
template< typename T >
void CStack< T >::push( const T& val )
{
    if( ! isFull() ) ptr_stk[top++] = val;
    else throw cInvalidPush();
}
template< typename T >
T CStack< T >::pop()
{
    if( ! isEmpty() ) return ptr_stk[--top];
    else throw cInvalidPop();
}
template< typename T >
bool CStack< T >::isFull() const
{
    return ( top == max_size ) ;
}
template< typename T >
bool CStack< T >::isEmpty() const
{
    return ( top == 0 ) ;
}

And a little test program that uses an user defined object ..,
(class Student)

// test_CStack.cpp //  / 2015-08-03 //


// use a C++ 11 (or newer) compiler //

#include <cctype> // re. std::isdigit, std::tolower
#include "CStack.h"


struct Student
{
public:
    // ctors ...
    Student( int id=0, const std::string& name="" ) : id(id), name(name) {}
    //int get_id() const { return id; }

    // re. taking in only unique id's...
    // used with call to exists ... in class CStack //
    bool operator == ( const Student& stud )
    {
        return (id == stud.id);
    }
private:
    int id;
    std::string name;

    // re. output of Student objects //
    friend std::ostream& operator << ( std::ostream& os, const Student& st )
    {
        return os << st.id << ", " << st.name;
    }
    friend bool takeIn( const CStack< Student >& stk, Student& st );
} ;

bool isOkAsInt( const std::string& str )
{
    if( str.size() == 0 ) return 0;
    for( auto e : str )
    {
        if( ! std::isdigit(e) ) return false;
    }
    // if reach here ...
    return true;
}

// re. input (from keyboard with prompts)  of Student objects //
bool takeIn( const CStack< Student >& stk, Student& st )
{
    std::string tmp;
    for( ; ;  )
    {
        for( ; ; )
        {
            std::cout << "Enter id: " << std::flush;
            getline( std::cin, tmp );
            if( isOkAsInt(tmp) ) break;
            std::cout << "INVALID input ... ONLY integers are VALID input here.\n";
        }
        try
        { st.id = std::stoi( tmp ); }
        catch( std::out_of_range& ex )
        {
            std::cout << ex.what() << " OUT OF VALID RANGE!\n";
            continue;
        }

        if( st.id == 0 )
            return false;

        if( stk.exists( st ) )
        {
            std::cout << "That id, '" << st.id
                      << "', already exists!\n";
            continue;
        }

        std::cout << "Enter name: " << std::flush;
        getline( std::cin, st.name );

        std::cout << "You entered '"
                  << st << "', Ok to accept (y/n) ? " << std::flush;
        getline( std::cin, tmp );
        if( tmp.size() && std::tolower( tmp[0] ) == 'y' )
            break;

        std::cout << "Try again!\n";
    }
    return true;
}



int main()
{
    CStack< Student >stk(3); // use small stack for testing //

    std::cout << "Enter Student data to push on stack (id = 0 to quit):\n";
    Student stud;
    while( takeIn( stk, stud ) ) // permit ONLY unique id's //
    {
        try
        {
            stk.push(stud);
        }
        catch( cInvalidStack& ex )
        {
            std::cout << ex.what() << ".. so NOthing added!"
                      << "\n(Recall: Enter id = 0 to quit.)\n";
        }
        std::cout << "stk.size() = " << stk.size() << '\n';
    }

    while( ! stk.isEmpty() )
    {
        std::cout << "stk.pop() = " << stk.pop() << '\n';
        std::cout << "stk.size() = " << stk.size() << '\n';
    }

    std::cout << "\nTesting pop if stack already empty ...\n";
    try
    {
        std::cout << "stk.pop() = " << stk.pop() << '\n';
    }
    catch( cInvalidStack& ex )
    {
        std::cout << ex.what() << ".. so can NOT pop anything!\n";
    }


    std::cout << "\nPress 'Enter' to continue/exit ... " << std::flush;
    std::cin.get();

}

Whoa David ...I've done those three settings you told me and my code is executing :P
Okay and the second code you provided me by using template, seems a bit difficult ... But I'll take a look at that.. Thank you :)

One question ,If you explain the term C++ 11 which I set in my compiler?
What is it's purpose?

Actually this question was in my paper so I just have to use the stated data members and member functions in the code. So the template code(the other code you provided) is for my practice. :)

Your Dev IDE settings ...
permit your code to be compiled using one of these standards ...

ISO C90  <--- this is what I normally choose when compiling C student code
ISO C99 
ISO C++     <--- this ... or if needed then ...
ISO C++ 11  <--- this ... is what I normally choose for C++ student code
GNU C90
GNU C99
GNU C++
GNU C++ 11

One question ... explain the term C++ 11 which I set in my compiler ... it's purpose?

If you use features in your code that are NOT available in a 'lower standard',
then that code will NOT compile ...
until ...
you turn on the ability to compile that code that uses those 'higher' features.

For example,
if you used [ ] with a 'lambda function' in some C++ code and used the ISO C++ compiler setting ...
it would NOT compile ...
until you reset the compile setting to one of the C++ 11 compile settings

I think a more basic explanation may be called for...

Like most languages still in use, C++ is still evolving over time, and the official standards for the language is updated by the International Standards Organization (ISO) and the American National Standards Institute (ANSI) at irregular intervals as the development committees set the changes into the rules. The different versions of the language - which generally are backwards compatible with older code, but add new features and clarify the details of older rules - are given by the name of the agency that released it, the name of the language, and the year it was released. For example, ANSI C 89 was the first 'official' standard for C, released by ANSI in 1989. The current standard most C++ compilers support (at least partly) is ISO C++ 11; since ANSI accepts the ISO standards for most programming languages as the same as their own, the 'ISO' part is usually dropped, so it is called C++11. There is a newer update, C++14, but it is a minor update for the most part (mostly clarifications of problematic parts of C++11) and most C++ compiler developers haven't gotten to working on supporting it yet.

You'll also note that most C++ compilers are also C compilers, so you want to make sure that you are compiling for C++ for this class, not C.

Got it :)

Thanks to both of you..!

Funny!
Most of the people don't figure out that it is funny to even think about things like that.
YO man should figureout the spce in memory that is available and then push if you have space, otherwise you have array that is simulating stack and that is, well ...

Have fun!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.