• Advertisement
Sign in to follow this  

vectors

This topic is 4616 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok,ok. You win. I need to learn about vectors. I think I have the basic primise down, but I am running into trouble with two-dimensional vectors. I guess I am not very good at searching the internet, because I can't seem to find what I am looking for. The only thing I found was how to declare a two-dimension vector. std::vector<std::vector<int> > testVec; Now, I know you use push.back to add elements to the vector. But how do you add elements to the first dimension? Would you add elements to the second deminsion like this? testVec[1].push_back(3); Thanks for any help clearing this up.

Share this post


Link to post
Share on other sites
Advertisement
What you have written would be equivilant to testVec[1][3] if it was just a normal array.

Share this post


Link to post
Share on other sites
Quote:

What you have written would be equivilant to testVec[1][3] if it was just a normal array.


This code compiles without any errors, but crashes at runtime. I assume that is becasue there isn't a testVec[1] yet. And I don't think the 3 defines the number of elements, it just gives the value of that element. Please correct me if I am wrong.

Share this post


Link to post
Share on other sites
push_back inserts a value to the end of the array so


std::vector<int> array;

array.push_back( 3 );
array.push_back( 7 );

array[0] == 3
array[1] == 7





This is what you want


std::vector< std::vector<int> > array;

//to create a 5x3 array for example
array.resize( 5 );

for(int i =0;i < 5;++i)
array.resize( 3 );

//now you can access it as a normal array
array[0][0] = x;





EDIT: Or do what Cygon said :)

Share this post


Link to post
Share on other sites
Vectors are not really suited for two-dimensional arrays, because each row of the array could have a different length. std::vector::push_back() does only one thing: It appends an element to the end of the vector, enlarging it by one each time it is called.

I would recommend using boost's multi_array for arrays with more than one dimension, simply because it keeps things straight and is less efford to manage. Assuming you used a vector instead, the code would look like this:


#include <vector>

using namespace std;

int main() {
typedef vector<vector<int> > IntVector2;

// Construct matrix of 100 x 100
IntVector2 MyInts(100, vector<int>(100));

// Access without bounds checking
MyInts[10][20] = 1234;

// Access with bounds checking
MyInts.at(10).at(20) = 1234;
}



-Markus-


Share this post


Link to post
Share on other sites
Oh sorry my mistake I thought that was just an example line.

You want to do:


std::vector<std::vector<int> > testVec;

std::vector<int> Array;
testVec.push_back(Array);
testVec[0].push_back(3);



or

std::vector<std::vector<int> > testVec;

testVec.resize(1);
testVec[0].push_back(3);



However both of these have a problem. Each time you change the size of testVec to add more int vectors the vector will copy each of the int vectors (well not everytime but we still dont want it to happen). The way around this is to declare your vector as a vector pointers to int vectors, like this


std::vector<std::vector<int>* > testVec;

testVec.push_back(new std::vector<int>);
testVec[0]->push_back(3);



though if you do it this way at the end of your code or the vectors life remember to delete all the new vectors we amde like so


for(std::vector<std::vector<int>* >::iterator IT = testVec.begin(); IT != testVec.end(); ++IT)
delete *IT;



Remember you can use typedefs to get rid of horrid lines like std::vector<std::vector<int>* >::iterator

Share this post


Link to post
Share on other sites
I made a couple of classes a while ago to handle doing 2D and 3D vectors. I made it for a client a while ago so that explains why it's part of the std namespace, you can take it out of there if you want.... Have fun!

main.cpp - to test
#include "vector2d.h"
#include "vector3d.h"
#include <iostream>
using namespace std;


int main(){

// Make a 3D vector of integer values (3x4x2)
std::vector3D<int> vec(3, 4, 2);

// Set the value of all of them to 5
vec.SetAll(5);

// Change some others to other numbers
vec(0,0,0) = 1;
vec(1,1,1) = 2;

// Display all
for(int z = 0; z < vec.MaxZ(); z++){
for(int y = 0; y < vec.MaxY(); y++){
for(int x = 0; x < vec.MaxX(); x++){
cout << vec(x,y,z);
} cout << endl;
} cout << endl;
}

// Change dimensions and then display again
vec.MaxX(5);
vec.MaxZ(1);
cout << "Max X: " << vec.MaxX() << endl;
cout << "Max Y: " << vec.MaxY() << endl;
cout << "Max Z: " << vec.MaxZ() << endl << endl;

for(int z = 0; z < vec.MaxZ(); z++){
for(int y = 0; y < vec.MaxY(); y++){
for(int x = 0; x < vec.MaxX(); x++){
cout << vec(x,y,z);
} cout << endl;
} cout << endl;
}

cin.get();
return 0;
}




vector2d.h
/******************************************************************************
Title: 2D Vector Class Wrapper

Author: Rob Loach

Date: April 16, 2005

Description:
Manages a two-dimensional vector.

Usage:
// Declaration
std::vector2D<int> intVect2D(10,10); // Make a 10x10 vector of int's
std::vector2D<char> chrVect2D(5,10); // Make a 5x10 vector of char's

// Change size
intVect2D.MaxX(20); // Increase the x size to 20
chrVect2D.MaxY(3); // Decrease the y size to 3

// Get/change values
cout << intVect2D(0,0); // Display the first value in the array
cout << chrVect2D(2,3); // Display the element at 2x3
intVect2D(6,1) = 7; // Change the value of element 6x1 to 7
intVect2D.SetAll(400); // Set all elements to 400

\******************************************************************************/



#if !defined(__INCLUDED_STDVECTOR2D__)
#define __INCLUDED_STDVECTOR2D__


#include <vector>
#include <stdexcept>

namespace std {

template <class T>
class vector2D
{
public:
// Constructor
vector2D(unsigned int MaxX = 1, unsigned int MaxY = 1) {
m_MaxX = (MaxX < 1) ? 1 : MaxX;
m_MaxY = (MaxY < 1) ? 1 : MaxY;
for (int row = 0; row < m_MaxY; row++){
std::vector<T> vec(m_MaxX);
m_2DVector.push_back(vec);
}
}

// Get and Set elements
T& operator()(int x, int y){
if(x >= m_MaxX || y >= m_MaxY || x < 0 || y < 0)
throw std::out_of_range("vector2D() out of range");
else
return m_2DVector[y][x];
}

T Get(int x, int y){
if(x >= m_MaxX || y >= m_MaxY || x < 0 || y < 0)
throw out_of_range("vector2D() out of range");
else
return m_2DVector[y][x];
}

T Set(int x, int y, T value){
if(x >= m_MaxX || y >= m_MaxY || x < 0 || y < 0)
throw out_of_range("vector2D() out of range");
else
return m_2DVector[y][x] = value;
}

// Change the width of the vector
int MaxX(int maxX){
maxX = (maxX < 1) ? 1 : maxX;
if(maxX < m_MaxX){
for(int row = 0; row < m_MaxY; row++){
m_2DVector[row].erase(m_2DVector[row].begin()+maxX, m_2DVector[row].end());
}
} else if(maxX > m_MaxX){
for(int row = 0; row < m_MaxY; row++){
for(int col = 0; col < maxX - m_MaxX; col++){
T element;
m_2DVector[row].push_back(element);
}
}
}
return m_MaxX = maxX;
}

// Change the height of the vector
int MaxY(int maxY){
maxY = (maxY < 1) ? 1 : maxY;
if(maxY < m_MaxY){
m_2DVector.erase(m_2DVector.begin() + maxY, m_2DVector.end());
}else if(maxY > m_MaxY){
for(int i = 0; i < maxY - m_MaxY; i++){
std::vector<T> row(m_MaxX);
m_2DVector.push_back(row);
}
}
return m_MaxY = maxY;
}

// Set all elements of the vector
void SetAll(T value){
for(int x = 0; x < m_MaxX; x++)
for(int y = 0; y < m_MaxY; y++)
m_2DVector[y][x] = value;
}

// Get the dimension sizes
int MaxX(){ return m_MaxX; }
int MaxY(){ return m_MaxY; }
private:
std::vector< std::vector <T> > m_2DVector;
unsigned int m_MaxX;
unsigned int m_MaxY;
};
}

#endif





vector3d.h
/******************************************************************************
Title: 3D Vector Class Wrapper

Author: Rob Loach

Date: April 16, 2005

Description:
Manages a three-dimensional vector.

Usage:
// Declaration
std::vector3D<int> intVect3D(10,10,5); // Make a 10x10x5 vector of int's
std::vector3D<char> chrVect3D(5,10,1); // Make a 5x10x1 vector of char's

// Change size
intVect3D.MaxX(20); // Increase the x size to 20
chrVect3D.MaxY(3); // Decrease the y size to 3
chrVect3D.MaxZ(-4); // Set the z size to 1

// Get/change values
cout << intVect3D(0,0,0); // Display the first value in the array
cout << chrVect3D(2,3,4); // Display the element at 2x3x4
cout << chrVect3D.Get(5,3,2); // Display the element at 5x3x2
intVect3D(6,1,4) = 7; // Change the value of element 6x1x4 to 7
intVect3D.Set(6,1,4, 7); // Set the value of element 6x1x4 to 7
intVect3D.SetAll(500); // Set all elements to 500

\******************************************************************************/



#if !defined(__INCLUDED_STDVECTOR3D__)
#define __INCLUDED_STDVECTOR3D__

namespace std {

template <class T>
class vector3D
{
public:
// Constructor
vector3D(unsigned int MaxX = 1, unsigned int MaxY = 1, unsigned int MaxZ = 1) {
m_MaxX = (MaxX < 1) ? 1 : MaxX;
m_MaxY = (MaxY < 1) ? 1 : MaxY;
m_MaxZ = (MaxZ < 1) ? 1 : MaxZ;
for(int z = 0; z < m_MaxZ; z++){
vector< vector<T> > vecy;
for(int y = 0; y < m_MaxY; y++){
vector<T> vecx(MaxX);
vecy.push_back(vecx);
}
m_3DVector.push_back(vecy);
}
}

// Get and Set elements
T& operator()(int x, int y, int z){
if(x >= m_MaxX || y >= m_MaxY || z >= m_MaxZ || x < 0 || y < 0 || z < 0)
throw out_of_range("vector3D() out of range");
else
return m_3DVector[z][y][x];
}

T Get(int x, int y, int z){
if(x >= m_MaxX || y >= m_MaxY || z >= m_MaxZ || x < 0 || y < 0 || z < 0)
throw out_of_range("vector3D() out of range");
else
return m_3DVector[z][y][x];
}

T Set(int x, int y, int z, T value){
if(x >= m_MaxX || y >= m_MaxY || z >= m_MaxZ || x < 0 || y < 0 || z < 0)
throw out_of_range("vector3D() out of range");
else
return m_3DVector[z][y][x] = value;
}


// Change the width of the vector
int MaxX(int maxX){
maxX = (maxX < 1) ? 1 : maxX;
if(maxX < m_MaxX){
for(int z = 0; z < m_MaxZ; z++){
for(int row = 0; row < m_MaxY; row++){
m_3DVector[z][row].erase(m_3DVector[z][row].begin()+maxX, m_3DVector[z][row].end());
}
}
} else if(maxX > m_MaxX){
for(int z = 0; z < m_MaxZ; z++){
for(int row = 0; row < m_MaxY; row++){
for(int col = 0; col < maxX - m_MaxX; col++){
T element;
m_3DVector[z][row].push_back(element);
}
}
}
}
return m_MaxX = maxX;
}

// Change the size of the vector
int MaxY(int maxY){
maxY = (maxY < 1) ? 1 : maxY;
if(maxY < m_MaxY){
for(int z = 0; z < m_MaxZ; z++){
m_3DVector[z].erase(m_3DVector[z].begin() + maxY, m_3DVector[z].end());
}
}else if(maxY > m_MaxY){
for(int z = 0; z < m_MaxZ; z++){
for(int i = 0; i < maxY - m_MaxY; i++){
std::vector<T> row(m_MaxX);
m_3DVector[z].push_back(row);
}
}
}
return m_MaxY = maxY;
}

int MaxZ(int maxZ){
maxZ = (maxZ < 1) ? 1 : maxZ;
if(maxZ < m_MaxZ){
m_3DVector.erase(m_3DVector.begin() + maxZ, m_3DVector.end());
} else if(maxZ > m_MaxZ){
for(int i = 0; i < maxZ - m_MaxZ; i++){
vector< vector<T> > vecy;
for(int y = 0; y < m_MaxY; y++){
vector<T> vecx(m_MaxX);
vecy.push_back(vecx);
}
m_3DVector.push_back(vecy);
}
}

return m_MaxZ = maxZ;
}

// Get the dimension sizes
int MaxX(){ return m_MaxX; }
int MaxY(){ return m_MaxY; }
int MaxZ(){ return m_MaxZ; }

// Set all elements of the vector
void SetAll(T value){
for(int z = 0; z < m_MaxZ; z++)
for(int x = 0; x < m_MaxX; x++)
for(int y = 0; y < m_MaxY; y++)
m_3DVector[z][y][x] = value;
}
private:
vector< vector< vector <T> > > m_3DVector;
unsigned int m_MaxX;
unsigned int m_MaxY;
unsigned int m_MaxZ;
};


}

#endif



Share this post


Link to post
Share on other sites
Hey Rob, how comes you didn't make the number of dimensions a template parameter? [grin]

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
Hey Rob, how comes you didn't make the number of dimensions a template parameter? [grin]


I'm more concerned about the get/set methods passing/returning the value type by value, and missing constant-correctness [grin].

Share this post


Link to post
Share on other sites
I hate 2D vectors. They are ugly! But they can be useful. The only problem is that you can't guarantee, outside of a wrapper class that provides for it, that they will be "square", which means that each "row" is the same length. With a regular array of integers, for example:

int array[3][3];

it will look like this, always:

1 2 3
4 5 6
7 8 9

But with a vector, it could look like this:

1
2 3 4 5 6 7
8 9 10
11

12 13 14
15

And that is usually not what you are looking for. I didn't try out the wrapper posted here, but give it a try and let us know!

Share this post


Link to post
Share on other sites
Something tells me he wants a 2d geometric vector... Maybe im wrong though.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
Hey Rob, how comes you didn't make the number of dimensions a template parameter? [grin]
Heh... Someone hired me to write those classes and as you all know: "Time is money", so I had to write them up as quickly and as effectively as possible designed for easy use. If you manage to modify it to have the extra template parameter, I'll give you whatever part of my soul I still have left [smile].

Quote:
Original post by silverphyre673
But with a vector, it could look like this:

1
2 3 4 5 6 7
8 9 10
11

12 13 14
15

And that is usually not what you are looking for. I didn't try out the wrapper posted here, but give it a try and let us know!
That's exactly why I decided to make a class wrapper for the concept. It keeps all vector sizes correctly constant to what you set/change them to. The test code I posted to test out the wrapper demonstrates this.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement