Vector UML

Feb 10, 2011 at 5:16am
Here is the question:
(Implementing vector class) The vector class is provided in the standard C++ library. Implement the vector class an exercise. The standard vector class has many functions. For this exercise , implement only the functions defined in the UML class diagram, as shown in the image below. Use dynamic memory allocation where appropriate.

http://i56.tinypic.com/34f1wg4.png

I'm really not even sure how to start this out. I understand how to use templates and vectors separately, but together and in a class we haven't stepped into yet. Any help with getting me started would be greatly appreciated!!

Thanks
Feb 10, 2011 at 7:45am
If you're uncommon to templates, start with the following:

Step 1: Create a "pure" vector class for an specific type (You said you are comfortable with vectors!)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Vector_int
{
public:
  Vector_int();
  int at(size_t idx) const;
  int& at(size_t idx);
  //...
private:
  int* _vals;
}

int Vector_int::at(size_t idx) const
{
//...
}


Step 2: Introduce a typedef to provide a first layer of generalization
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef int T;
class Vector_T
{
public:
  Vector_T();
  T at(size_t idx) const;
  T& at(size_t idx);
  //...
private:
  T* _vals;
}

T Vector_T::at(size_t idx) const
{
//...
}


Step 3: Transform into a template
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template <typename T>
class Vector
{
public:
  Vector();
  T at(size_t idx) const;
  T& at(size_t idx);
  //...
private:
  T* _vals;
}

template <typename T>
T Vector<T>::at(size_t idx) const
{
//...
}


Of course you can start with step 2 or 3 right away if you feel save.
I'd recommend starting with step 2 since it makes debugging easier and transformation is not that hard afterwards.
Feb 10, 2011 at 8:40pm
Why would you do typedef...why not go right to putting the template tags?

Also I am familiar with the vector format, but is there anything special you have to do to the header and/or implementation files in order for the class to operate correctly?
Feb 10, 2011 at 11:02pm
Template classes must be completely implemented within the header file or within a file #included by the header file.
Feb 11, 2011 at 1:29am
Here's what I have done thus far. I know that the vector class is part of the C++ library, but this assignment wants us to manually create the member functions in the UML diagram. http://i56.tinypic.com/34f1wg4.png

It errors out in the main() anywhere I try to use "intVector." Tells me expression must have class type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef VECTOR_H
#define VECTOR_H

template<typename T>
class Vector
{
public:
  Vector();
  Vector(int Vsize);
  void push_back(T value) const;
  void pop_back();
  T at(T &index);
  bool empty() const;
  void clear() const;
  void swap(Vector &v);

  // These accessors are inline member functions
  int getSize() const;

  // Mutator
  void setSize(int);

private:
  unsigned int size;
};


#endif


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// vector.cpp
// Class implementation file for the Vector class

#include "vector.h"
#include<iostream>
#include <iomanip>
using namespace std;

// Default constructor

template<typename T>
Vector<T>::Vector()
{
  size = 16;
  elements = new T[size];
}

// Overloaded constructor

template<typename T>
Vector<T>::Vector(int Vsize)
{
  setSize(Vsize);
  elements = new T[size];
}

template<typename T>
void Vector<T>::setSize(int pX)
{
	size = pX;
}

template<typename T>
int Vector<T>::getSize() const
{
     return size;
}

// Removes all elements from this vector
template<typename T>
void Vector<T>::clear()
{
  delete [] elements;
  size = 0;
}

// Returns true if this vector is empty
template<typename T>
bool Vector<T>::empty() const
{
  return (size == 0);
}

template<typename T>
void Vector<T>::push_back(T value)
{
  return elements[size++] = value;
}

template<typename T>
void Vector<T>::pop_back()
{
  return elements[--size];
}

template<typename T>
T Vector<T>::at(T index)
{
  return elements[index];
}

template<typename T>
void Vector<T>::swap(Vector &v)
{
	int size = v.getSize();
	newElements = new T[size];

	for (int i = 0; i < v.getSize(); i ++)
	{
		newElements[i] = this->elements[i];
	}
	return newElements;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include<iostream>
#include<iomanip>
#include "vector.h"
#include <string>

using namespace std;

int main()
{
    Vector<int> intVector();
    
    // Store numbers 1, 2, 3, 4, 5, ....10 to the vector
    for (int i = 0; i < intVector.size(); i++)
	{
        intVector.push_back(i + 1);
	}
        
    // Display the numbers in the vector
    cout << "Numbers in the vector: ";
    for (int i = 0; i < intVector.getSize(); i++)
	{
        cout << intVector[i] << " ";
	}
        
    Vector<string> stringVector;
    
    // Store strings into the vector
    stringVector.push_back("Dallas");
    stringVector.push_back("Houston");
    stringVector.push_back("Austin");
    stringVector.push_back("Norman");
    
    // Display the string in the vector
    cout << "\nStrings in the string vector: ";
    for (int i = 0; i < 10; i++)
        cout << stringVector[i] << " ";
        
    stringVector.pop_back(); // Remove the last element
    
    Vector<string> v2;
    v2.swap(stringVector);
    v2[0] = "Atlanta";
    
    // Redisplay the string in the vector
    cout << "\nStrings in the vector v2: ";
    for (int i = 0; i < v2.getSize(); i++)
        cout << v2.at(i) << " ";

    return 0;
}
Last edited on Feb 11, 2011 at 6:30am
Feb 11, 2011 at 6:32am
I have also tried to put a value in the constructor like so...

Vector<int> intVector(10);

It still errors out, telling me the operator "[]" doesn't math any operand.
Feb 11, 2011 at 7:52am
Do you know what that means?
Vector<int> intVector();
It's a declaration of a function intVector taking no arguments and returning a Vector<int>!
replace it with
Vector<int> intVector;

Did you read jsmith's comment:
Template classes must be completely implemented within the header file or within a file #included by the header file.

?

You haven't defined operator[]:
1
2
3
4
5
6
7
8
9
10
11
12
template<typename T>
Vector
{
//...
T& operator[](int idx);
};

template<typename T>
T& Vector<T>::operator[](int idx)
{
//...
};



Btw. "at" should have an index type of int, unsigned int etc. not T!
Where do you store your information? The only variable is size...
Feb 11, 2011 at 5:28pm
Do you know what that means?
Vector<int> intVector();
It's a declaration of a function intVector taking no arguments and returning a Vector<int>!
replace it with
Vector<int> intVector;


Ok, so that is for the default constructor. Now if I have arguments like below...how come it still does work?

Vector<int> intVector(10);

I don't understand why I have to define the operator..I thought vectors were supposed to work like arrays.
Last edited on Feb 11, 2011 at 5:30pm
Feb 11, 2011 at 9:41pm
kraigballa wrote:
I don't understand why I have to define the operator..I thought vectors were supposed to work like arrays.
They do, if you make them this way. Of course, the job is already done if you use the appropriate STL container - http://www.cplusplus.com/reference/stl/vector/. But you have to do something similar yourself, if I understand correctly - reinvent the wheel type of exercise. Just as the STL version redefines the subscript operator, so should you, if you want your Vector to be used as array.

Regards
Feb 14, 2011 at 5:59am
Ok here is what I have. When I run the program it crashes right away...not sure what may be wrong.

header/implementation file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#ifndef VECTOR_H
#define VECTOR_H

template <class itemType>
class vector
{
  public:

  // constructors/destructor
    vector( );                        // default constructor (size==0)
    vector( int size );               // initial size of vector is size

  // operator overloads
    const vector & operator = ( const vector & vec );
    itemType & operator [ ] (unsigned int index );   // indexing with range checking

  // member functions
    int  length( ) const;                   // capacity of vector
    void resize( int newSize );             // change size dynamically;
                                            // can result in losing values
	void push_back(itemType value);
	void pop_back();
	itemType at(int &index);
	bool empty() const;
	void clear() const;
	void swap(vector &v);

  private:
    unsigned int  mySize;                            // # elements in array
    itemType * myList;                      // array used for storage
};


#include<iostream>
#include <iomanip>


template <class itemType>
vector<itemType>::vector(): mySize(0), myList(0) // initialization list
{
}

template <class itemType>
vector<itemType>::vector(int size) : mySize(0), myList(new itemType[size])
{
}

// Removes all elements from this vector
template <class itemType>
void vector<itemType>::clear() const
{
	delete [] myList;
	mySize = 0;
}

// Returns true if this vector is empty
template <class itemType>
bool vector<itemType>::empty() const
{
	return (mySize == 0);
}

// Need to reallocate the vector to accomodate for the addition
template <class itemType>
void vector<itemType>::push_back(itemType value)
{
		itemType* reallocated = new itemType[mySize + 1];
		for(int i = 0; i < mySize; i++)
		{
			reallocated[i] = myList[i];
		}
		mySize++;
		reallocated[mySize] = value;
		delete[] myList;
		myList = reallocated;
}

template <class itemType>
void vector<itemType>::pop_back()
{
		if(mySize == 0){
		}
		else{
		--mySize;
		}
}

// Testing index to see if less than size. If bigger throw error
template <class itemType>
itemType vector<itemType>::at(int &index)
{
		if(index < mySize)
		{
			return myList[index];
		}
		else
		{
			throw range_error("Index out of bounds!");
		}
}

template<typename itemType>
void vector<itemType>::swap(vector &v)
{
		itemType* temp = v.myList;
		v.myList = this->myList;
		this->myList = temp;

		unsigned int temp1 = v.mySize;
		v.mySize = this->mySize;
		this->mySize = temp1;

}

template <class itemType>
const vector<itemType> &
vector<itemType>::operator = (const vector<itemType> & rhs)
{
  if (this != &rhs)                         // don't assign to self!
  {
    delete [] myList;                       // get rid of old storage
    mySize = rhs.length();
    myList = new itemType [mySize];         // allocate new storage

    // copy rhs
    for(int k=0; k < mySize; k++)
    {
      myList[k] = rhs.myList[k];
    }
  }
  return *this;                             // permit a = b = c = d
}

template <class itemType>
int vector<itemType>::length() const
{
  return mySize;
}

template <class itemType>
itemType & vector<itemType>::operator [] (unsigned int k)
{
  if (k < 0 || mySize <= k)
  {
    cerr << "Illegal vector index: " << k << " max index = "
         << mySize-1 << endl;
    abort();
  }
  return myList[k];
}

#endif 


cpp file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<iostream>
#include<iomanip>
#include "test.h"
#include <string>

using namespace std;

int main()
{
    vector<int> intVector(10);
    
    // Store numbers 1, 2, 3, 4, 5, ....10 to the vector
	for (int i = 0; i < intVector.length(); i++)
	{
        intVector.push_back(i + 1);
	}
        
    // Display the numbers in the vector
    cout << "Numbers in the vector: ";
    for (int i = 0; i < intVector.length(); i++)
	{
        cout << intVector[i] << " ";
	}
        
    vector<string> stringVector;
    
    // Store strings into the vector
    stringVector.push_back("Dallas");
    stringVector.push_back("Houston");
    stringVector.push_back("Austin");
    stringVector.push_back("Norman");
    
    // Display the string in the vector
    cout << "\nStrings in the string vector: ";
    for (int i = 0; i < 10; i++)
        cout << stringVector[i] << " ";
        
    stringVector.pop_back(); // Remove the last element
    
    vector<string> v2;
    v2.swap(stringVector);
    v2[0] = "Atlanta";
    
    // Redisplay the string in the vector
    cout << "\nStrings in the vector v2: ";
	for (int i = 0; i < v2.length(); i++)
        cout << v2.at(i) << " ";
	system("pause");
    return 0;
}
Feb 14, 2011 at 7:04am
1
2
3
4
for (int i = 0; i < intVector.length(); i++)
	{
        intVector.push_back(i + 1);
	}

1
2
3
4
5
6
7
8
9
10
11
12
void vector<itemType>::push_back(itemType value)
{
		itemType* reallocated = new itemType[mySize + 1];
		for(int i = 0; i < mySize; i++)
		{
			reallocated[i] = myList[i];
		}
		mySize++;
		reallocated[mySize] = value;
		delete[] myList;
		myList = reallocated;
}

You keep pushing elements and it size keeps increasing as you reallocate the size of array no matter if it is indeed full or not.
Feb 14, 2011 at 7:26am
You read more strings from the stringVector than you push in!
try this:
1
2
3
4
 for (vector<string>::const_iterator it = vectorString.begin(); it != vectorString.end(); ++it)
  {
    cout << *it << " ";
  }

or this:

1
2
3
4
 for (int i = 0; i < vectorString.size(); ++i)
  {
    cout << vectorString[i] << " ";
  }


This works regardless the actual size of the vector
Feb 14, 2011 at 6:22pm
Onur...yes I saw the error..I put 10 just to test it out with hard numbers and forgot to change it back to stringVector.length()

Mercurialol - I'm not sure what you mean...push_back is supposed to work the way you described. I push elements and the size keeps increasing. Vectors are similar to arrays, but their size increase if they are full. Is there something wrong with the code you pasted?
Feb 15, 2011 at 8:07am
I found another error.
Try to push_back a value then clear the list twice!
1
2
3
4
vectory<int> v;
v.push_back(1);
v.clear();
v.clear();


This signature looks rather strange:
 
vector::itemType vector::at(int &index);


Why take the index as reference? You don't want to modify it, it's inefficient, it doesn't allow you to use it with a literal (vector.at(1)), since you cannot take a non-const reference to a literal. You maybe want to change it to this:

 
vector::itemType& vector::at(int index);


This allows you to modify the element at position index.

Also try to think what should happen if a vector goes out of scope, i.e. is destructed?
The default destructor won't do it.

Last edited on Feb 15, 2011 at 8:08am
Topic archived. No new replies allowed.