Two Dimensional Array Using Vector

c++ vector one dimensional and two dimensional arrays value assignment

The reason this is happening is because of two reasons.

  1. The vector you are trying to access is empty
  2. You are trying to put an int into a vector that was supposed to hold vector<int>s.
    Fixed code:
#include <vector>
#include <iostream>
int main()
{
std::vector<int> oneDimArray;
oneDimArray.push_back(5);
for (int i = 0; i < oneDimArray.size(); i++)
{
std::cout << oneDimArray[i];
}
std::vector<std::vector<int>> twoDimArray;
twoDimArray.push_back(oneDimArray); //You can put a vector of ints in here

for (int i = 0; i < twoDimArray.size(); i++)
{
for (int j : twoDimArray[i])
{
std::cout << j;
}
}
return 0;
}

twoDimArray[0].push_back(5) is invalid because the vector had no size yet. After you have pushed back something, or done twoDimArray.resize(new size here);, then you can do that (as long as it isn't out of range).

Also, once a vector has size, you can access the elements of the vector inside the vector by going like twoDimArray[0][0] = 1;. That would give the first value of the first vector inside of the vector to get the value 1.

Multidimensional Vectors in C++

If you are able to use C++11, multidimensional arrays and vectors of vectors can be initialized in a similar manner.

int a1[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
std::vector<std::vector<int>> a2 = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };

However, there are differences that must be understood to access the elements without running into undefined behavior.

For a multidimensional array, memory for the elements of the array is required to be allocated contiguously. For a vector of vector, the memory for the elements is most likely going to be disjoint.

Memory for a1:

a1[0][0]    a1[1][0]    a1[2][0]
| | |
v v v
+---+---+---+---+---+---+---+---+---+
| | | | | | | | | |
+---+---+---+---+---+---+---+---+---+

Memory for a2 (most likely):

a2[0][0]
|
v
+---+---+---+
| | | |
+---+---+---+

a2[1][0]
|
v
+---+---+---+
| | | |
+---+---+---+

a2[2][0]
|
v
+---+---+---+
| | | |
+---+---+---+

Also, it is possible to defined a vector of vectors in which the number of columns is not same for each row.

std::vector<std::vector<int>> a2 = { {1, 2, 3}, {4, 5}, {6, 7, 8, 9} };

In a multidimensional array, the number of columns is guaranteed to be same for each row.

Given the above multidimensional array a1, a1[1][2] will be a valid element and a1[2][3] will be an invalid element. In the case of a vector of vectors, using the above line, a2[1][2] is not a valid element and a2[2][3] is a valid element.

Initializing a two-dimensional std::vector

Use the std::vector::vector(count, value) constructor that accepts an initial size and a default value:

std::vector<std::vector<int> > fog(
ROW_COUNT,
std::vector<int>(COLUMN_COUNT)); // Defaults to zero initial value

If a value other than zero, say 4 for example, was required to be the default then:

std::vector<std::vector<int> > fog(
ROW_COUNT,
std::vector<int>(COLUMN_COUNT, 4));

I should also mention uniform initialization was introduced in C++11, which permits the initialization of vector, and other containers, using {}:

std::vector<std::vector<int> > fog { { 1, 1, 1 },
{ 2, 2, 2 } };

How to define a vector of two dimensional array?

You shouldn't name a variable like a type. You are shadowing std::array. You should rename the variable and use std::array instead of C-arrays:

#include <array>
#include <string>
#include <vector>

using StrArr2D = std::array<std::array<std::string, 16>, 16>;

int main() {
StrArr2D arr;
std::vector<StrArr2D> vec;
vec.push_back(arr);
}

You can keep the variable name array if you avoid using namespace std; and use full qualified names.

Can I use std::vector<std::vector<T>> to represent two dimensional arrays in C++?

Of course you may use class std::vector to simulate arrays. For example

#include <iostream>
#include <vector>

int main()
{
size_t n;
size_t m;

std::cout << "Enter the number of rows: ";
std::cin >> n;

std::cout << "Enter the number of columns: ";
std::cin >> m;

std::vector<std::vector<int>> v( n, std::vector<int>( m ) );

return 0;
}

Also consider using of the combination of std::vector with std::array when the number of columns is a compile time constant.

A definition of so-called 3-dimensional array can look as for example

std::vector<std::vector<std::vector<int>>> 
v( 2, std::vector<std::vector<int>>( 3, std::vector<int>( 4 ) ) );

A more interesting example

#include <iostream>
#include <vector>
#include <numeric>

int main()
{
size_t n;
size_t m;

std::cout << "Enter the number of rows: ";
std::cin >> n;

std::cout << "Enter the number of columns: ";
std::cin >> m;

std::vector<std::vector<int>> v( n, std::vector<int>( m ) );

for ( size_t i = 0; i < n; i++ )
{
std::iota( v[i].begin(), v[i].end(), i * m );
}

for ( const auto &v1 : v )
{
for ( auto x : v1 ) std::cout << x << ' ';
std::cout << std::endl;
}

return 0;
}

If to enter 3 and 5 correspondingly for n and m then the output will be

0 1 2 3 4 
5 6 7 8 9
10 11 12 13 14

handling a 2 dimensional vector c++

A vector is size 0 until you tell it to resize, or unless you initialize it with a specific size. Pass the size of your vector in when you create it:

for(int i=1;i<112;i++){
n_2.push_back(vector<struct nodo>(112-i));
for(int j=1;j<112-i;j++){
n_2[i][j].last_prod=j;
}
}

Also, it looks like you are skipping over the 0th index, which means your first value in your array will be skipped. That is probably undesired.

Finally, if your array is a constant size, consider using std::array rather than std::vector. Note that std::array is a C++11 feature and may not be available depending on your compiler.

If I were writing this code, I'd probably write it like this:

#include <array>
using namespace std;

// allocate an array of 112 <struct nodo> arrays, each of size 112
array<array<struct nodo, 112>, 112> n_2;
for (int i = 0; i < 112; i++)
{
for (int j = 0; j < 112; j++)
{
n_2[i][j].last_prod = j;
}
}

Or alternatively, if I don't have a compiler that supports C++11:

#include <vector>
using namespace std;

// allocate a vector of size 112 of <struct nodo> vectors, each of size 112
vector<vector<struct nodo> > n_2(112, vector<struct nodo>(112));
for (int i = 0; i < 112; i++)
{
for (int j = 0; j < 112; j++)
{
n_2[i][j].last_prod = j;
}
}

Even more ideally, you should use a 1 dimensional vector, and simply treat it as a 2 dimensional vector. This way, you can do a single allocation of memory all at once rather than 112 smaller allocations. This is getting pretty nitpicky but obviously a O(1) solution is better than an O(n) solution which is better than a O(n^2) solution in terms of allocations since allocations are slow.

C++ Two Dimensional std::vector best practices

When you want a square or 2d grid, do something similar to what the compiler does for multidimensional arrays (real ones, not an array of pointers to arrays) and store a single large array which you index correctly.

Example using the Matrix class below:

struct Map {
private:
Matrix<MapCell> cells;

public:
void loadMap() {
Matrix<MapCell> cells (WIDTH, HEIGHT);

for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
// modify cells[i][j]
}
}

swap(this->cells, cells);
// if there's any problem loading, don't modify this->cells
// Matrix swap guarantees no-throw (because vector swap does)
// which is a common and important aspect of swaps
}
};

Variants of matrix classes abound, and there are many ways to tailor for specific use. Here's an example in less than 100 lines that gets you 80% or more of what you need:

#include <algorithm>
#include <memory>
#include <vector>

template<class T, class A=std::allocator<T> >
struct Matrix {
typedef T value_type;
typedef std::vector<value_type, A> Container;

Matrix() : _b(0) {}
Matrix(int a, int b, value_type const& initial=value_type())
: _b(0)
{
resize(a, b, initial);
}
Matrix(Matrix const& other)
: _data(other._data), _b(other._b)
{}

Matrix& operator=(Matrix copy) {
swap(*this, copy);
return *this;
}

bool empty() const { return _data.empty(); }
void clear() { _data.clear(); _b = 0; }

int dim_a() const { return _b ? _data.size() / _b : 0; }
int dim_b() const { return _b; }

value_type* operator[](int a) {
return &_data[a * _b];
}
value_type const* operator[](int a) const {
return &_data[a * _b];
}

void resize(int a, int b, value_type const& initial=value_type()) {
if (a == 0) {
b = 0;
}
_data.resize(a * b, initial);
_b = b;
}

friend void swap(Matrix& a, Matrix& b) {
using std::swap;
swap(a._data, b._data);
swap(a._b, b._b);
}

template<class Stream>
friend Stream& operator<<(Stream& s, Matrix const& value) {
s << "<Matrix at " << &value << " dimensions "
<< value.dim_a() << 'x' << value.dim_b();
if (!value.empty()) {
bool first = true;
typedef typename Container::const_iterator Iter;
Iter i = value._data.begin(), end = value._data.end();
while (i != end) {
s << (first ? " [[" : "], [");
first = false;
s << *i;
++i;
for (int b = value._b - 1; b; --b) {
s << ", " << *i;
++i;
}
}
s << "]]";
}
s << '>';
return s;
}

private:
Container _data;
int _b;
};


Related Topics



Leave a reply



Submit