How to store multidimensiona vectors in a vector

Ok so I have a vector that creates a map, now I want to be able to create multiple maps and call them to be created when going to the next screen, so I'm using a vector for that, but how do i push te multi dim. vector back into it? This way I can create multiple multi dim. vectors and store the created maps in them.


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 <vector>
#include <string>

//TODO
/*
//1. Figure out how to store map coordinates in other vector.
*/

using namespace std;

void CreateMap(int rows, int columns, vector<vector<char> > vectMap, vector<int> Maps);
void ResizeMap(int rows, int columns, vector<vector<char> > vectMap, vector<int> Maps);

int main()
{
    int rows = 20, columns = 30;

    vector<vector<char> > vectMap(rows, vector<char>(columns));
    vector<int> Maps;

    Maps.push_back(/*???*/);

    /* Pseudo code
    
        vector push back rows and columns;
    */

    CreateMap(rows, columns, vectMap, Maps);

    return 0;
}

void CreateMap(int rows, int columns, vector<vector<char> > vectMap, vector<int> Maps)
{
    for(int i = 0; i < rows; i++)
    {
        for(int j = 0; j < columns; j++)
        {
            vectMap[i][j] = '.';
            cout << vectMap[i][j];
        }
        cout << endl;
    }
}

void ResizeMap(int rows, int columns, vector<vector<char> > vectMap, vector<int> Maps)
{

}
Last edited on
Also what is this second element in the vector at the end? I have been looking on the web to try to figure it out but I cant seem to.

vector<vector<char> > intVect(5, vector<char>(5, 6));

As far as i can tell, the first 5 is the rows(or columns i forget which comes first) and the second is the columns. but what does the 6 do? I change it to 60 and run it and nothing is different.
The 6 is the value to set all the vectors elements to.

From http://www.cplusplus.com/reference/vector/vector/vector/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// default (1)	
explicit vector (const allocator_type& alloc = allocator_type());

// fill (2)	
explicit vector (size_type n, const value_type& val = value_type(),
                 const allocator_type& alloc = allocator_type());

// range (3)	
template <class InputIterator>
         vector (InputIterator first, InputIterator last,
                 const allocator_type& alloc = allocator_type());

// copy (4)	
vector (const vector& x);


You can see the fill constructor takes a value as the second parameter.

Your CreateMap function above sets the elements of the vector of vectors on line 40

vectMap[i][j] = '.';

so the original value is irrelevant.

Andy

Last edited on
ah i see now. so what about my first question? I want to be able to save the rows and columns into a vector but I am unsure how to push back into a 2d vector. Im unsure if i need to sotre the vectMap in the other vector or not. but I figure i can just push back the values into the second vector and use the first to output them, but I cant figure out how. I have been loloking up stuff about 2d vectors but i couldnt find anything that helped me.
Last edited on

I want to be able to save the rows and columns into a vector but I am unsure how to push back into a 2d vector

Well, the first thing to be aware of is that there's no such thing as a 2d vector.

vector<vector<char> > vectMap;

is declaring a vector of (vector of chars).

Yes, you can access it like a 2d array using e.g. vec[row][col] if you ensure that all the vectors of chars (vector<char>) held by the vector<vector<char> > are the same size, but there is no mechanism to ensure this.

To push_back into a vector of chars you push chars.

To push_back into a vector of vector or chars, you push vectors of chars.

You can either push the chars into the vector of chars before you push it into the vector of vector of chars:

1
2
3
4
5
6
7
8
9
vector<char> temp;
temp.push_back('h');
temp.push_back('e');
temp.push_back('l');
temp.push_back('l');
temp.push_back('o');

vector<vector<char>> vec;
vec.push_back(temp);


or after

1
2
3
4
5
6
7
8
9
vector<vector<char>> vec;
vec.push_back(vector<char>()); // push empty vector<char>

// get back most vector<char> and push_back into it
vec.back().push_back('h');
vec.back().push_back('e');
vec.back().push_back('l');
vec.back().push_back('l');
vec.back().push_back('o');


Andy

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
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;

// take 1
//
// push back row values into a temporary vector<char> and then
// push this vector<char> into the vector<vector<char>>
//
// note 'vec' param is a reference
void CreateVectorOfVectors_take_1(int row_count, int col_count, vector<vector<int>>& vec) {
    for(int row = 1; row <= row_count; ++row) {
        vector<int> temp;
        for(int col = 1; col <= col_count; ++col) {
            int val = row * 10 + col;
            temp.push_back(val);
        }
        vec.push_back(temp);
    }
}

// take 2
//
// push back an empty vector<char> and then push the chars into
// the backmost vector in the vector<vector<char>>
//
// note 'vec' param is a reference
void CreateVectorOfVectors_take_2(int row_count, int col_count, vector<vector<int>>& vec) {
    for(int row = 1; row <= row_count; ++row) {
        vec.push_back(vector<int>());
        for(int col = 1; col <= col_count; ++col) {
            int val = row * 10 + col;
            vec.back().push_back(val);
        }
    }
}

void DumpVectorOfVectors(const vector<vector<int>>& vec) {
    const int row_count = vec.size();
    if(0 == row_count)
        return;
    const int col_count = vec.front().size();
    for(int row = 0; row < row_count; ++row) {
        assert(col_count == vec[row].size());
        for(int col = 0; col < col_count; ++col) {
            cout << " " << vec[row][col];
        }
        cout << "\n";
    }
}

int main() {
    vector<vector<int>> vec_1;
    CreateVectorOfVectors_take_1(3, 4, vec_1);
    DumpVectorOfVectors(vec_1);
    cout << "\n";

    vector<vector<int>> vec_2;
    CreateVectorOfVectors_take_2(4, 3, vec_2);
    DumpVectorOfVectors(vec_2);
    cout << "\n";

    return 0; 
}
Last edited on
You constructed vectMap as a two dimensional vector with the optional size feature so your vector already has 20 elements of 30 char. Why do you think you need to push_back() additional elements into your vector? You already seem to understand that you can access the vector with array notation vectMap[i][j] so I'm confused as to what you want to accomplish.
We'll what Im trying to do is make a game map in the console, now when i hit a certain spot i want to go to another map, i want to be able to push back the width and height of the new maps into the vector so it can just clear the old and get the new and create it. I am unsure if i can just push the rows and columns back into the vector intVect as is or if i have to make another vector of vectors to hold the maps. I haven't read andy's post yet so maybe that will be the answer to my question but that is basically what i am trying to do.
@Andy, is there a simpler solution? I feel like there should be. Also How do i get the size of a vector of vectors? If i do intVect.size() i get the first element but how do i get the second?
I want to be able to create multiple maps and call them to be created when going to the next screen, so I'm using a vector for that, but how do i push te multi dim. vector back into it?
Stay on target, Luke!

1
2
3
4
5
6
std::vector<Map> maps;
for ( something ) {
  Map map; // initialize/set
  maps.push_back( map );
}
std::cout << "We have " << maps.size() << " maps\n";

How do i get the size of a vector of vectors?

Size of what, exactly? My "maps" is a vector and has a "size".

"Vector of what?", you ask. Lets say:
using Map = std::vector<std::vector<char>>;
See http://en.cppreference.com/w/cpp/language/type_alias

Aha! a vector of vectors of vectors of characters. Each of those vectors can be of different size, or even empty, so counting the characters is a nested iteration.
1
2
3
4
5
6
7
8
using std::cout;
cout << "We have " << maps.size() << " maps\n";
for ( const auto & map : maps ) {
  cout << '\t' << map.size() << '\n';
  for ( const auto & row : map ) {
    cout << "\t\t" << row().size << '\n';
  }
}

You, however, seem attempt to to ensure elsewhere that each map has a vector of same size and each vector within the map-vector is of same size.
i want to be able to push back the width and height of the new maps into the vector so it can just clear the old and get the new and create it.

I am having trouble parsing this sentence...

Are you saying you want to resize the vector of vectors?

From what you're saying, I think you should consider using a class to encapulate your vector of vectors, as this would allow you to enforce the requirement that all vectors in the "2d vector" are the same size.

Andy
Yes, but i mean what if i didnt want the vectors to be the same size? what if i wanted one that is 10x25?
The vectors I'm talking about are the vector<char>s stored in the vector<vector<char>>

There's nothing to stop you doing

1
2
3
4
5
vector<vector<char>> map;
map.push_back(vector<char>(1));
map.push_back(vector<char>(2));
map.push_back(vector<char>(3));
map.push_back(vector<char>(4));


if you use the vector<vector<char>> directly, which not very good as a "2d vector".

Andy
Last edited on
why is it not good as a 2d vector? it seems to work pretty well, actually just the same as a 2d array.
what if i wanted one that is 10x25?

There is no such thing. All vectors are one-dimensional.

You could have ten vectors that each contain 25 elements and then have one more vector that contains those ten vectors.

Alternatively, you could use a vector with 250 elements an do the indexing math. For example, with encapsulating class like Andy suggested.

to push width and height into a vector

Width and height are a pair of integers.
For example using MapSize = std::pair<size_t,size_t>;
If you want a vector of those, then do so: std::vector<MapSize> maps;
This Map class uses a vector of vectors to implement a dynamic 2d array.

Most of the vector functionality is hidden to outside code can't tamper with the size of the individual rows.

As it stands, it is a bit dozy about 0 x N and N x 0 (for non-zero N) arrays. Should probably trap these as invalid sizes.

Andy

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
#include <iostream>
#include <vector>
using namespace std;

//#define START_WITH_EMPTY_MAP

const char blank = '.';

class Map {
private:
    // the Row class just does exactly what vector<char> does,
    // but by using private inheritance all the methods of
    // vector<char> are hidden apart from operator[] which
    // has been made public. This is prevent resizing of
    // rows, etc.
    class Row : private vector<char> {
    public:
        using vector<char>::operator[];
        friend class Map;
    };

public:
    Map() {}

    Map(unsigned nrows, unsigned ncols) : data(nrows) {
        for(unsigned row = 0; row < nrows; ++row)
            data[row].resize(ncols, blank);
    }

    ~Map() {}

    const Row& operator [] (unsigned row) const {
        return data[row];
    }

    Row& operator [] (unsigned row) {
        return data[row];
    }

    bool empty() const {
        return data.empty();
    }

    void clear() {
        data.clear();
    }

    unsigned nrows() const {
        return data.size();
    }

    unsigned ncols() const {
        return data.empty() ? 0 : data.front().size();
    }

    void resize(unsigned nrows, unsigned ncols) {
        data.resize(nrows);
        for(unsigned row = 0; row < nrows; ++row)
            data[row].resize(ncols, blank);
    }

private:
    vector<Row> data;
};

void FillMapWithLetters(Map& map) {
    const unsigned nrows = map.nrows();
    const unsigned ncols = map.ncols();
    for(unsigned row = 0; row < nrows; ++row) {
        for(unsigned col = 0; col < ncols; ++col) {
            unsigned n = (row * ncols + col) % ('z' - 'a' + 1);
            map[row][col] = static_cast<char>('a' + n);
        }
    }
}

void DumpMap(const Map& map) {
    if(map.empty()) {
        cout << "<empty>\n";
    } else {
        const unsigned nrows = map.nrows();
        const unsigned ncols = map.ncols();
        for(unsigned row = 0; row < nrows; ++row) {
            for(unsigned col = 0; col < ncols; ++col) {
                cout << " " << map[row][col];
            }
            cout << "\n";
        }
    }
}

int main() {
#ifndef START_WITH_EMPTY_MAP
    const unsigned nrows = 6;
    const unsigned ncols = 9;
#endif

    struct ResizeData {
        unsigned nrows;
        unsigned ncols;
    };

    const ResizeData resizeData[] = {{4, 7}, {3, 9}, {5, 8}};
    const unsigned resizeData_count = sizeof(resizeData)/sizeof(resizeData[0]);

    vector<Map> maps;

#ifdef START_WITH_EMPTY_MAP
    cout << "Create empty map\n\n";
    Map map;
#else
    cout << "Create map of " << nrows << " x " << ncols << "\n";
    Map map(nrows, ncols);
    cout << "And fill with letters\n\n";
    FillMapWithLetters(map);
#endif
    maps.push_back(map);
    DumpMap(map);
    cout << "\n";

    for(unsigned j = 0; j < resizeData_count; ++j) {
        const ResizeData& rd = resizeData[j];
        cout << "Resize map to " << rd.nrows << " x " << rd.ncols << "\n\n";
        map.resize(rd.nrows, rd.ncols);
        maps.push_back(map);
        DumpMap(map);
        cout << "\n";
    }

    cout << "All previous maps\n\n";
    for(unsigned i = 0; i < maps.size(); ++i) {
        const Map& m = maps[i];
        DumpMap(m);
        cout << "\n";
    }

    return 0; 
}
Last edited on
Topic archived. No new replies allowed.