Thread: Solution to Practice Problem of Chapter 25 in Jumping Into C++

  1. #1
    Registered User
    Join Date
    Apr 2017
    Posts
    11

    Solution to Practice Problem of Chapter 25 in Jumping Into C++

    Hello,

    I implemented a solution for the practice problem of Chapter 25 of the book Jumping in C++. The problem is pasted below so you can quickly see it.

    Practice problems
    1. Implement a vector replacement that operates only on integers, vectorOfInt (you don't need to use templates like the normal STL). Your class should have the following interface:
    • A no-argument constructor that allocates a 32-element vector
    • A constructor that takes an initial size as the argument
    • A method get, taking an index and returning the value at that index
    • A method set, that takes an index and a value, and sets the value at that index
    • A method pushback that adds an element to the end of the array, resizing if necessary
    • A method pushfront that adds an element to the beginning of the array
    • A copy constructor and assignment operator
    Your class should not leak memory; any memory it allocates must be deleted. Try to think carefully about how your class can be misused, and how you should handle those scenarios. What do you do if a user gives a negative initial size? What about accessing a negative index?

    I have attached the solution to this message in the cpp file.

    Would like to know if folks find any issues with the code.
    Attached Files Attached Files

  2. #2
    Guest
    Guest
    Unless your code is truly enormous, it's better if you paste it directly into your post (between [code][/code] tags):
    Code:
    #include <iostream>
    
    using namespace std;
    
    class VectorOfInt
    {
    
        public:
            VectorOfInt();
            VectorOfInt(int user_array_size);
            ~VectorOfInt();
            int get(int index, int *result);
            int set_value(int index, int value);
            int pushback(int value);
            int pushfront(int value);
            int fill_array(int number_of_elements);
            int auto_fill_array();
            int grow_array();
            int print_array();
            int print_array_constructor();
            VectorOfInt& operator=(const VectorOfInt& other);
            VectorOfInt (const VectorOfInt& other);
    
        private:
            int _array_size;
            int *_internal_array;
            int _number_of_elements;
    
    };
    
    VectorOfInt :: VectorOfInt()
    {
        _array_size = 32;
        _number_of_elements = 0;
        _internal_array = new int [_array_size];
        for(int i = 0; i< _array_size; i++)
        {
            _internal_array[i] = 0;
        }
        cout<<"\nThis is the state of the array after the default constructor is run";
        print_array_constructor();
    }
    
    VectorOfInt :: VectorOfInt(int user_array_size)
    {
        if(user_array_size <0)
        {
            cout<<"VectorOfInt :: VectorOfInt(int user_array_size):The array size requested is less than 0, which is not allowed so defaulting to an array size of 0";
            _array_size = 0;
        }
        else
        {
            _array_size = user_array_size;
        }
        _number_of_elements = 0;
        _internal_array = new int [_array_size];
        for(int i = 0; i< _array_size; i++)
        {
            _internal_array[i] = 0;
        }
        cout<<"\nThis is the state of the array after the size constructor is run";
        print_array_constructor();
    }
    
    VectorOfInt :: ~VectorOfInt()
    {
        delete [] _internal_array;
    }
    
    
    int VectorOfInt :: get(int index, int * result)
    {
    
        if((index <0) || index >= _array_size)
        {
            cout<<"\nint VectorOfInt :: get(int index, int * result):Invalid array index "<<index;
            *result = 0;
            return(-1);
        }
    
        *result = _internal_array[index];
        /*cout<<"\nThis is the state of the array after the get method  is run with index value "<<index;
        print_array();*/
        return(0);
    }
    
    int VectorOfInt :: set_value(int index, int value)
    {
    
        if((index <0) || index >= _array_size)
        {
            cout<<"\nint VectorOfInt :: set_value(int index, int value):Invalid array index "<<index;
            return(-1);
        }
    
        _internal_array[index]=value;
       /* cout<<"\nThis is the state of the array after the set method is run with index  "<<index<<" and value at index "<<value;
        print_array(); */
        return(0);
    }
    int VectorOfInt:: fill_array (int number_of_elements)
    {
        if((number_of_elements <0) || number_of_elements > _array_size)
        {
            return(-1);
        }
        for(int i= 0; i<number_of_elements;i++)
        {
            int value;
            cout<<"Enter the "<<i<<" value"<<endl;
            cin>>value;
            set_value(i,value);
    
        }
        _number_of_elements = number_of_elements;
        cout<<"\nThis is the state of the array after the fill array is run";
        print_array();
        return(0);
    }
    
    int VectorOfInt :: auto_fill_array ()
    {
        if(_array_size >=2)
        {
    
    
        for(int i=0; i<_array_size -2; i++)
        {
            set_value(i,i);
        }
        _number_of_elements = _array_size-2;
        }
        cout<<"\nThis is the state of the array after the auto fill array is run";
        print_array();
        return(0);
    }
    
    int VectorOfInt :: pushback(int value)
    {
        if(_number_of_elements ==_array_size)
            grow_array();
        cout<<"\nPush back was called with value "<<value;
        set_value(_number_of_elements++,value);
        cout<<"\nThis is the state of the array after the pushback "<<value<<" is run";
        print_array();
        return(0);
    
    }
    
    int VectorOfInt :: pushfront(int value)
    {
        if(_number_of_elements ==_array_size)
            grow_array();
            for(int i = _number_of_elements++;i>=1;i--)
            {
                set_value(i,_internal_array[i-1]);
            }
            set_value(0,value);
            cout<<"\nThis is the state of the array after the pushfront "<<value<<" is run";
            print_array();
            return(0);
    }
    
    int VectorOfInt ::grow_array()
    {
        cout<<"\nThis is the state of the array before the grow array is run ";
        print_array();
        if(_array_size==0)_array_size++;
        int *p_new_array = new int[_array_size*2 ];
        for ( int i = 0; i < _array_size; ++i )
        {
        p_new_array[ i ] = _internal_array[ i ];
        }
        delete [] _internal_array;
        _internal_array=p_new_array;
        _array_size *=2;
        cout<<"\nThis is the state of the array after the grow array is run ";
        print_array();
        return(0);
    }
    int VectorOfInt::print_array()
    {
        cout<<"\narray size is "<<_array_size;
        cout<<"\nnumber of elements in the array is "<<_number_of_elements;
        cout<<"\nindex";
        for(int i=0;i<_number_of_elements;i++)
        {
            cout<<"\t"<<i;
    
        }
        cout<<"\nvalue";
         for(int i=0;i<_number_of_elements;i++)
        {
            cout<<"\t"<<_internal_array[i];
    
        }
    
        return(0);
    }
    int VectorOfInt::print_array_constructor()
    {
        cout<<"\narray size is "<<_array_size;
        cout<<"\nnumber of elements in the array is "<<_number_of_elements;
        cout<<"\nindex";
        for(int i=0;i<_array_size;i++)
        {
            cout<<"\t"<<i;
    
        }
        cout<<"\nvalue";
         for(int i=0;i<_array_size;i++)
        {
            cout<<"\t"<<_internal_array[i];
    
        }
    
        return(0);
    }
    
    VectorOfInt& VectorOfInt::operator=(const VectorOfInt& other)
    {
        if (this == & other)
            return *this;
            delete [] _internal_array;
            _array_size=other._array_size;
            _number_of_elements=other._number_of_elements;
            _internal_array = new int [_array_size];
        for(int i=0;i<_array_size;i++)
        {
            _internal_array[i]=other._internal_array[i];
        }
    
        return *this;
    }
    
    
    VectorOfInt::VectorOfInt (const VectorOfInt& other)
    {
    
        _array_size=other._array_size;
        _number_of_elements=other._number_of_elements;
        _internal_array = new int [_array_size];
        for(int i=0;i<_number_of_elements;i++)
        {
            this->_internal_array[i]=other._internal_array[i];
        }
    }
    int main()
    {
        cout << "Hello world!" << endl;
        VectorOfInt VectorOfInt1;
        VectorOfInt1.auto_fill_array();
        int value;
        VectorOfInt1.get(5,&value);
        cout<<"\nThe value at index 5 is "<<value;
        VectorOfInt1.set_value(6,60);
        cout<<"\nThis is the state of the array after the set method is run with index  "<<6<<" and value at index "<<value;
        VectorOfInt1.print_array();
    
        VectorOfInt1.pushback(70);
        VectorOfInt1.pushfront(70);
        VectorOfInt1.pushfront(80);
        VectorOfInt1.pushback(80);
    
        cout<<"\nThis is for VectorOfInt2\n";
    
        VectorOfInt VectorOfInt2(45);
    
    
        VectorOfInt2.auto_fill_array();
        VectorOfInt2.get(7,&value);
        cout<<"\nThe value at index 7 is "<<value;
        VectorOfInt2.set_value(8,60);
        cout<<"\nThis is the state of the array after the set method is run with index  "<<8<<" and value at index "<<60;
        VectorOfInt2.print_array();
        VectorOfInt2.pushback(70);
        VectorOfInt2.pushfront(70);
        VectorOfInt2.pushfront(80);
        VectorOfInt2.pushback(80);
    
        cout<<"\nThis is for VectorOfInt3\n";
    
        VectorOfInt VectorOfInt3(-45);
    
    
        VectorOfInt3.auto_fill_array();
    
        VectorOfInt3.get(9,&value);
        cout<<"\nThe value at index 9 is "<<value;
        VectorOfInt3.set_value(10,60);
        cout<<"\nThis is the state of the array after the set method is run with index  "<<10<<" and value at index "<<60;
        VectorOfInt3.print_array();
        VectorOfInt3.pushback(70);
        VectorOfInt3.pushfront(70);
        VectorOfInt3.pushfront(80);
        VectorOfInt3.pushback(80);
    
    
        cout<<"\nThis is for VectorOfInt4\n";
    
        VectorOfInt VectorOfInt4(0);
    
    
        VectorOfInt4.auto_fill_array();
        VectorOfInt4.get(0,&value);
        cout<<"\nThe value at index 0 is "<<value;
        VectorOfInt4.set_value(0,60);
        VectorOfInt4.pushback(70);
        VectorOfInt4.pushfront(70);
        VectorOfInt4.pushfront(80);
        VectorOfInt4.pushback(80);
    
    
    cout<<"\nThis is for VectorOfInt5\n";
    
        VectorOfInt VectorOfInt5(15);
    
    
        VectorOfInt5.auto_fill_array();
        VectorOfInt5.get(9,&value);
        cout<<"\nThe value at index 5 is "<<value;
        VectorOfInt5.set_value(6,60);
        VectorOfInt5.pushback(70);
        VectorOfInt5.pushfront(70);
        VectorOfInt5.pushfront(80);
        VectorOfInt5.pushback(80);
    
        VectorOfInt5 = VectorOfInt5 ;
        cout<<"\n The state of the VectorInt5 after assigning to itself is ";
        VectorOfInt5.print_array();
    
        VectorOfInt5 = VectorOfInt1 ;
        cout<<"\n The state of the VectorInt5 after assigning to VectorInt1 is ";
        VectorOfInt5.print_array();
    
        VectorOfInt VectorOfInt6(VectorOfInt5);
         cout<<"\n The state of the VectorInt6 after running copy constructor on it using VectorOfInt5 is  ";
        VectorOfInt6.print_array();
    
        cout<<"\n The state of the VectorInt5 after running copy constructor on it is  ";
        VectorOfInt5.print_array();
    
    
    
        return 0;
    }
    My compiler immediately warned me about the misleading indentation following the if-statement on line #152:
    Code:
        if(_number_of_elements ==_array_size)
            grow_array(); // only this line is executed conditionally
            for(int i = _number_of_elements++;i>=1;i--)
            {
            ...
    Haven't examined the code itself.

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    4,630
    Your constuctors should look more like (using initialization lists):

    Code:
    #include <iostream>
    
    
    class VectorOfInt
    {
    
        public:
            VectorOfInt();
            VectorOfInt(int user_array_size);
            ~VectorOfInt();
            int get(int index, int *result);
            int set_value(int index, int value);
            int pushback(int value);
            int pushfront(int value);
            int fill_array(int number_of_elements);
            int auto_fill_array();
            int grow_array();
            int print_array();
            int print_array_constructor();
            VectorOfInt& operator=(const VectorOfInt& other);
            VectorOfInt (const VectorOfInt& other);
    
        private:
            int array_size;
            int number_of_elements;
            int *internal_array;
    };
    
    VectorOfInt :: VectorOfInt() : array_size(32), number_of_elements(0), internal_array(new int[array_size]{0})
    {
    
        std::cout<<"\nThis is the state of the array after the default constructor is run\n";
        print_array_constructor();
    }
    Be sure the order of the variables in the initialization list match the definition order.

    By the way I removed the leading underscore because I really really detest (I know, I know, some people adore them.) the use of underscores (either leading or trailing) as I find them easy to miss. Also because leading underscores are reserved for the implementation in a lot of cases I don't like using them anywhere, including here where they are technically correct (yuck).

    Haven't gone any deeper into the class as yet.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,630
    By the way your "get" function is incorrect:

    • A method get, taking an index and returning the value at that index
    Your get:

    Code:
    int VectorOfInt :: get(int index, int * result)
    {
     
        if((index <0) || index >= _array_size)
        {
            cout<<"\nint VectorOfInt :: get(int index, int * result):Invalid array index "<<index;
            *result = 0;
            return(-1);
        }
     
        *result = _internal_array[index];
        /*cout<<"\nThis is the state of the array after the get method  is run with index value "<<index;
        print_array();*/
        return(0);
    }
    IMO, you have too many parameters. And in C++ pointers should be avoided whenever possible, this is one of those whenevers. You have a function returning an int, why not use that return value instead of the horrible pointer.

    Also, again IMO, instead of trying to return an error value you should consider throwing an exception.

  5. #5
    Registered User
    Join Date
    Apr 2017
    Posts
    11
    Thanks, yeah that's a very good and helpful suggestion. I didn't understand
    Code:
     VectorOfInt :: VectorOfInt() : array_size(32), number_of_elements(0), internal_array(newint[array_size]{0}).
    What's the 0 in the curly braces for? Oh! You are initializing all the elements to 0. Is that what you are doing?

  6. #6
    Registered User
    Join Date
    Apr 2017
    Posts
    11
    I intended it as such.

  7. #7
    Registered User
    Join Date
    Apr 2017
    Posts
    11
    How will I throw an exception in here?

  8. #8
    Registered User
    Join Date
    May 2010
    Posts
    4,630
    What's the 0 in the curly braces for? Oh! You are initializing all the elements to 0. Is that what you are doing?
    Yes. If you had a better book (more up to date teaching modern C++) you would probably be able to refer to your book. But alas that book isn't very up to date and really isn't teaching modern C++. It's more like C on steroids but not good C++.

    I intended it as such.
    What exactly did you intend?

    How will I throw an exception in here?
    Hasn't your book explained exceptions? But in any case, IMO, the checking of the index should probably be done before you call the function.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Jumping into C++ - Chapter 7 - Practice problem 1
    By ambro1987 in forum C++ Programming
    Replies: 2
    Last Post: 09-18-2017, 09:00 AM
  2. Jumping into C++ : Chapter 6 Practice Problem 2
    By Markkusz in forum C++ Programming
    Replies: 3
    Last Post: 10-09-2015, 08:26 AM
  3. Jumping into c++ practice problem poker chapter 9
    By menkle in forum C++ Programming
    Replies: 2
    Last Post: 09-06-2015, 02:43 PM
  4. Linked Lists Chapter 15 Practice Problem 1 Jumping Into C++
    By ArtemisFowl2nd in forum C++ Programming
    Replies: 34
    Last Post: 04-30-2014, 12:59 PM
  5. Jumping Into C++ Chapter 14 Practice Problem 1
    By ArtemisFowl2nd in forum C++ Programming
    Replies: 5
    Last Post: 04-16-2014, 09:36 PM

Tags for this Thread