2D & 3D VECTORS (c++)

Started by
8 comments, last by 3Dgonewild 16 years, 10 months ago
How do you declare a 2d or 3d vector? And how can i load a file full of integers(tile map) in a 2d vector integer array?
Advertisement
I don't get your question. You might speak of a multidimensional array or of vectors (which have only one dimension).

If you speak about multimensional arrays
The C way (bad, not encapsulated), static (in the initialiazed segment if global, on stack otherwise; please avoid creating huge arrays on stack):
type my_array[elem_count_dim1][elem_count_dim_2];

Of course, you can continue the list if you want more dimensions.
The size of the array (in memory) is the product of all dimension by the size of the array type.

The C way (bad, not encapsulated), dynamic (on the heap)
type **my_array;// creationmy_array = new type*[elem_count_dim1];for (int i=0; i<elem_count_dim1; ++i°{  my_array = new type[elem_count_dim2];}// deletionfor (int i=0; i<elem_count_dim1; ++i°{  delete [] my_array;}delete [] my_array;


The C++ way, boosterized: use boost multi array

The C++ way, not boosterized: you can use the standard library (ie creating a vector of vector of int) but that's a bit convoluted. Or you can create a class which encapsulate the C case (or something similar).

If you speak about a vector
Hum. Create a class or a struct with the fields you want. I mean, if you search for 2D vector or 3D vector class on the intarweb, you'll be flooded with results.

Best regards,
I assume you mean SC++L vector (the dynamic array) and not a mathematical vector.

Quote:How do you declare a 2d or 3d vector?

Don't. There's no such thing. You can fake it by nesting types, for example
std::vector< std::vector< int > > tryingToBe2D;

however this is not really a two dimensional array... the technique scales to n-D vectors, but is still not usually a good idea.

In C++, it's often not a good idea to use n-D arrays or vectors, because they're (generally) not very space or memory efficient, and they're almost always jagged arrays (not rectangular) instead.

It's instead preferable to use a n-D interface to a one-dimensional array. You can construct the interface however you like... the most straightforward method is not to have an interface at all and just do the indexing directly. You can replace a 2D array of (width * height) elements with a single array of (width * height) elements:
std::vector< int > linearArray(width * height);

To access element (x,y) of the array, you index it as follows:
int element = linearArray[y * width + x];

This works because the array (or vector) elements are arranged contiguously (most attempts at n-D arrays lose this guarantee, which makes them somewhat less memory efficient). Every (width) elements of the array is one "row" of the grid, which is why you multiply the y/row value by the width.

This scales to any dimension of array. While it might seem a little strange at first, it's generally a much better method than actually attempting to use the constructs that C++ provides to make "2D" arrays.
First of all , thanks for the replies..


So its called "SC++L vector" , dohh..okkk!


@jpetrie:

Thanks for the nice examples , but , what changes do i have to make in order to create a tile map?


with a normal 2d array , i do the following :


int data[25][25];int whatiwant =data[1][20];


With a sc++l vector , i could do it like this : ?

std::vector< int > ARRAY(25 * 25);int whatiwant = ARRAY[1 * 25 + 20];


Am i right?or i missed something?
I don't know why jpetrie wrote "SC++L" but it's more "STL Vectors" (standard library vector), hence where std:: come from (standard namespace). Don't forget the #include at the top of your file.

http://msdn2.microsoft.com/en-us/library/cscc687y(VS.80).aspx
http://msdn2.microsoft.com/en-us/library/k449z507(VS.80).aspx
Quote:Original post by Dunge
I don't know why jpetrie wrote "SC++L" but it's more "STL Vectors" (standard library vector), hence where std:: come from (standard namespace). Don't forget the #include at the top of your file.

http://msdn2.microsoft.com/en-us/library/cscc687y(VS.80).aspx
http://msdn2.microsoft.com/en-us/library/k449z507(VS.80).aspx


He wrote SC++L because std::vector is a part of the Standard C++ Library, which the two links you posted also suggests.

STL, short for Standard Template Library, is something else, altough related.
I've tried to open a tile map file , but my application exits :/.

Here's the source:

#include <cstdlib>#include <iostream>#include <vector>#include <sstream>#include <fstream>using namespace std;int main(int argc, char *argv[]){std::vector< int > ARRAY(25 * 25);//FILE has 24 cols & 24 rows (since we start from 0 , its 25x25)std::ifstream map( "MAP.TXT" );if( map == NULL ) { return false; }for( int t = 0; t < 24*24; t++ ){int c = -1;map >> c;ARRAY[t]=c;if( map.fail() == true ) { return false;}}int whatiwant = ARRAY[1 * 24 + 24];cout<<whatiwant<<endl;    system("PAUSE");    return EXIT_SUCCESS;}


The tile map :
map.txt
111110000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111



Please ,tell me what im doing wrong!!!!!!!!!!!!
You're reading integers from the file. What is the first integer in your file? Here's a tip; it's not 1.

Read characters instead, since that's what the file contains and how you are supposed to interpret the file.
On your loop, you recognize that the maximum index is one less than the size (25*25), but you apply that rule to both dimensions (and you end up with 24*24).
The number of elements in the array is 25*25=3125, so your maximum index should be 25*25-1=3124. Since you use '<' instead of '<=', you can use the actual size.
With the size you supplied (24*24), your 1 short per dimension (49 elements overall).
If you were to keep your structure as it is, which Brother Bob advised against, you should write "for (int t=0;t<ARRAY.size();t++)", or use stl iterators, "for (std::vector<int>::iterator iter=ARRAY.begin();iter!=ARRAY.end();iter++)".
Apply this concept to your array access also.

The reason why Brother Bob stated that you shouldn't read integers is that by default ifstream will read the integers as delimited by whitespace. So, on the first line, instead of reading a character per a series of steps, it will read the whole first line as an integer=11111000000000011111111.
To read using characters:
char c;map >> c;//Translate into integerint x=c-'0'; //If you're going to use non-numerical characters, this is a bad idea

EDIT: Forgot to mention - Be sure you check for whitespace! Otherwise, it'll keep on reading as if nothing happened.

Slight note:
Your expression "if (map.fail()==true)" is redundant - the if goes to the statement / block following if the expression inside is true (nonzero).
Projects:> Thacmus - CMS (PHP 5, MySQL)Paused:> dgi> MegaMan X Crossfire
Yeah! , works!!!!
0 * 25+5 returns 0!!!
#include <cstdlib>#include <iostream>#include <vector>#include <sstream>#include <fstream>using namespace std;int main(int argc, char *argv[]){std::vector< int > ARRAY(25 * 25);std::ifstream map( "MAP.TXT" );if( map == NULL ) { return false; } for( int t = 0; t < ARRAY.size(); t++ ){char c;map >> c;int cA = c-'0';ARRAY[t]=cA;}int whatiwant = ARRAY[0 * 25+5];cout<<whatiwant<<endl;system("PAUSE");return EXIT_SUCCESS;}


Thanks for the great help!!!

This topic is closed to new replies.

Advertisement