Desktop Programming > C/C++ & Visual C++

class Vector ... and Stacks and Queues ...

<< < (2/2)

David:
Finally ... as a template ...


--- Code: ---// MyArray3.h //


#ifndef MYARRAY_H
#define MYARRAY_H

#include <iostream>
using std::cerr;


// 3rdly as a template ...
template < typename T >
class MyArray
{
public:
    // ctors...
   
    // default ctor ...
    MyArray() : len(0), cap(0), ary(0) {}
    //with size passed in
    MyArray( size_t size ) : len(size), cap(size), ary( new T [len] )
    {
        for( size_t i = 0; i < len; ++i ) ary[i] = T();
    }
    // with ary (beg, end) passed in ...
    MyArray( const T* beg, const T* end )
    {
        len = cap = end - beg;
        ary = new T[len];
        for( size_t i =  0; i < len; ++i ) ary[i] = beg[i];
    }
    // copy ctor...
    MyArray ( const MyArray< T >& v ) // copy constructor ...
    {
        cap = v.cap;
        len = v.len;
        ary = new T[cap];
        for( size_t i = 0; i < len; ++i ) ary[i] = v.ary[i];
    }
    // overloaded operateo = ...
    MyArray< T >& operator = ( const MyArray< T >& v ) // copy constructor ...
    {
        if( this != &v )
        {
            delete [] ary;
           
            cap = v.cap;
            len = v.len;
            ary = new T[cap];
            for( size_t i = 0; i < len; ++i ) ary[i] = v.ary[i];
        }
        return *this;
    }

    // clear ...
    void clear()
    {
        if( ary )
        {
            delete [] ary;
            cap = 0;
            len = 0;
            ary = 0;
        }
    }
    // destructor ..
    ~MyArray() { clear(); }
   
   
    // reserve ...
    void reserve( size_t newCap )
    {
        if( newCap > cap )
        {
            cap = newCap;
            T* tmp = new T[ cap ];
            for( size_t i = 0; i < len; ++i ) tmp[i] = ary[i];
            delete [] ary;
            ary = tmp; // update the base address of ary
        }
    }
    // resize ...
    void resize( size_t newSize )
    {
        if( newSize > len )
        {
            reserve( newSize );
            for( size_t i = cap-1; i >= len; --i ) ary[i] = T();
            len = newSize;
        }
        else if( newSize < len )
        {
            for( size_t i = len-1; i >= newSize; --i ) ary[i] = T();
            len = newSize;
        }
    }
   
   
    // push_back ...
    void push_back( const T& val )
    {
        if( len == cap ) enlarge();
        /* now add in new element ... */
        ary[len] = val;
        ++ len;
    }
   
    // overloaded operator [] ...
    T& operator [] ( size_t i ) { return ary[i]; } // allow element to be updated
    const T& operator [] ( size_t i ) const { return ary[i]; } // 'read only'
   
    size_t size() const { return len; }
    size_t capacity() const { return cap; }
   
    const T& back() const
    {
        if( len ) return ary[len-1];
        // else ...
        cerr << "\nERROR! MyArray is empty ... return value of 0 is NOT valid.\n";
        return errVal;;
    }
    T& back()
    {
        if( len ) return ary[len-1];
        // else ...
        cerr << "\nERROR! MyArray is empty ... return value of 0 is NOT valid.\n";
        return errVal;;
    }
    void pop_back() { if( len ) --len;  }

    bool empty() const { return len == 0; }
   
private:
   size_t len;
   size_t cap;
   T* ary;
   
   static T errVal;
   
    // enlarge
    void enlarge()
    {
        if( cap ) cap += cap; // double capacity ...
        else cap = 2; // set initial capacity
        T* tmp = new T[ cap ];
        for( size_t i = 0; i < len; ++i ) tmp[i] = ary[i];
        //for( int i = cap-1; i >= len; --i ) tmp[i] = T();
        delete [] ary;
        ary = tmp; // update the base address of ary
    }

} ;


// initail here ... //
template< typename T >
T MyArray< T >::errVal = T();

#endif
--- End code ---


And a cheap little test file ...


--- Code: ---// test_MyIntArray3.h.cpp //  // 2016-02-28 //


#include "MyIntArray3.h"

#include <string>



int main()
{
    using namespace std;

    const int nums[]= { 5, 4, 3, 2, 1 };
    const int size = sizeof nums / sizeof(int);

    MyArray < int > v( nums, nums+size );
    MyArray < int > cpy( v ), a;
    a = cpy;
   
    for( size_t i = 0; i < v.size(); ++ i ) cout << v[i] << ' ';
    cout << '\n';
    for( size_t i = 0; i < cpy.size(); ++ i ) cout << cpy[i] << ' ';
    cout << '\n';
    for( size_t i = 0; i < a.size(); ++ i ) cout << a[i] << ' ';
    cout << "\n\n";
   
    while( !a.empty() )
    {
        cout << a.back() << ' ';
        a.pop_back();
    }
   
   
    cout << "\n\n";
   
    const string strs[] = { "5", "4", "3", "2", "1" };
    const int sizeStrs = sizeof strs / sizeof(string);

    MyArray < string > vStr( strs, strs+sizeStrs );
    MyArray < string > cpyStr( vStr ), aStr;
    aStr = cpyStr;

    for( size_t i = 0; i < vStr.size(); ++ i ) cout << vStr[i] << ' ';
    cout << '\n';
    for( size_t i = 0; i < cpyStr.size(); ++ i ) cout << cpyStr[i] << ' ';
    cout << '\n';
    for( size_t i = 0; i < aStr.size(); ++ i ) cout << aStr[i] << ' ';
    cout << "\n\n";

    while( !aStr.empty() )
    {
        cout << aStr.back() << ' ';
        aStr.pop_back();
    }
   
    cout << "\nPrees 'Enter' to exit/continue ... ";
    cin.get();
}

--- End code ---

David:
Now to some simple stacks demo'd ...



--- Code: ---// Stack.h //  // 2016-02-29 //

#ifndef dwSTACK_H
#define dwSTACK_H

#include <iostream>
#include <vector>

// default container for *THIS CUSTOM* stack here is std:: vector< T > //
template < typename T, class Container = std::vector < T > >
class Stack
{
public:
    void push( const T& val ) { stk.push_back( val ); }
   
    /////////  NOTE! *NO* bounds checking is done here /////
    const T& top() const { return stk.back(); }
    T& top() { return stk.back(); }
    void pop() { stk.pop_back(); }
    ////////////////////////////////////////////////////////
   
    size_t size() const { return stk.size(); }
    bool empty() const { return stk.empty(); }

private:
    Container stk;
} ;

#endif
--- End code ---


And a little test progrom ...



--- Code: ---// test_Stack.h.cpp //  // 2016-02-29  //


#include "Stack.h"

#include <iostream> // included above //
#include <string>
#include <list>
#include <deque> // a double ended queue //



int main()
{
    using namespace std;

    const string names[] = { "Andy", "Bill", "Jill", "Lucy", "Marie", "Sam", "Sharon", "Zoe" };
    const int num_names = sizeof names / sizeof *names;

    Stack < string > vNames; // by default, container inside *THIS CUSTOM* Stack wrapper class is a vector //
   
    for( int i = 0; i < num_names; ++ i ) vNames.push( names[i] );

    cout << "Testing pop vNames: \n";
    while( !vNames.empty() )
    {
        cout << vNames.top() << ' ';
        vNames.pop();
    }
   
    // Note C++ list is a double_link linked list ...
    // so has push_back and pop_back and back methods all implemented ok //
    Stack < string, list< string > > lstNames; // here, using a list container inside the class Stack //

    for( int i = 0; i < num_names; ++ i ) lstNames.push( names[i] );

    cout << "\n\nTesting pop lstNames: \n";
    while( !lstNames.empty() )
    {
        cout << lstNames.top() << ' ';
        lstNames.pop();
    }
   
   
    Stack < string, deque< string > > deqNames; // here, using a deque container inside the class Stack //

    for( int i = 0; i < num_names; ++ i ) deqNames.push( names[i] );

    cout << "\n\nTesting pop deqNames: \n";
    while( !deqNames.empty() )
    {
        cout << deqNames.top() << ' ';
        deqNames.pop();
    }
   
    cout << "\n\nPress 'Enter' to continue/exit ... " << flush;
    cin.get();
}

--- End code ---

David:
Now to Queues ...



--- Code: ---// Queue.h //  // 2016-02-29 //

#ifndef dwQUEUE_H
#define dwQUEUE  _H

#include <iostream>
#include <list>

// default container for stack here is std::list < T > //
template < typename T, typename Container = std::list < T > >
class Queue
{
public:
    void push_back( const T& obj ) { que.push_back( obj ); }
   
    /////////  NOTE! *NO* bounds checking is done here /////
    const T& back() const { return que.back(); }
    T& back() { return que.back(); }
   
    const T& front() const { return que.front(); }
    T& front() { return que.front(); }
   
    void pop_front() { que.pop_front(); }
    ////////////////////////////////////////////////////////
   
    size_t size() const { return que.size(); }
    bool empty() const { return que.empty(); }

private:
    Container que;
} ;

#endif
--- End code ---


And a little test program ...



--- Code: ---// test_Queue.h.cpp //  // 2016-02-13  //


#include "Queue.h"

#include <iostream> // included above //
#include <string>
#include <deque> // a double ended queue //



int main()
{
    using namespace std;

    const string names[] = { "Andy", "Bill", "Jill", "Lucy", "Marie", "Sam", "Sharon", "Zoe" };
    const int num_names = sizeof names / sizeof *names;

   
    // Note C++ list is a double_link linked list ...
    // so has push_back and pop_back and back methods all implemented ok //
    Queue < string > lstNames; // here, using default list container inside the class Queue //

    for( int i = 0; i < num_names; ++ i ) lstNames.push_back( names[i] );

    cout << "\n\nTesting pop_front lstNames: \n";
    while( !lstNames.empty() )
    {
        cout << lstNames.front() << ' ';
        lstNames.pop_front();
    }
   
   
    // here, using a deque container inside the class Queue //
   
    Queue < string, deque< string > > deqNames;

    for( int i = 0; i < num_names; ++ i ) deqNames.push_back( names[i] );

    cout << "\n\nTesting pop_front deqNames: \n";
    while( !deqNames.empty() )
    {
        cout << deqNames.front() << ' ';
        deqNames.pop_front();
    }
   
    cout << "\n\nPress 'Enter' to continue/exit ... " << flush;
    cin.get();
}

--- End code ---


Navigation

[0] Message Index

[*] Previous page

Go to full version