2D vector usage

I know there are multiple threads relating to the declaration and usage of 2D vectors, but I'm having trouble wrapping my head around how it works and the threads have been closed for comments or questions.

In short, I've taken code snippets from some of these threads and have tried to make use of them based on my limited understanding of how it works, but my results are not as anticipated.

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


int main()
{
    std::vector< std::vector< double > > Matrix( 3, std::vector< double >( 4 ) );

    //populate vector
    for (int i=0;i<10;i++)
    {
        vector<double> row;//creates empty row
        for (int j=0;j<20;j++)
            row.push_back(i+j);//add an element to the row
        Matrix.push_back(row);//add row to main vector Matrix
    }
    //output 2D vector
    for (int y=0;y<10;y++)
    {
        for (int x=0;x<20;x++)
            cout<<Matrix[y][x]<<" ";
        cout<<endl;
    }
}

I know that in a one dimensional vector, I can make use of push_back to add additional elements, however in this case it appears to cause a program crash. What am I doing wrong? I've also had difficulty making use of vectorname.size() in this scenario, wheras I understand how it works with one dimensional vectors.

EDIT: On my output loops, the values 10 and 20 within the loops were reversed, and fixing this eliminated the crash, yet it doesn't explain my program's output being filled with garbage or zero values.
Last edited on
closed account (j3Rz8vqX)
Ah, good job was just about to point out your edit.

When you first declared Matrix, you added 3 rows of vectors with 4 data each.

Actual presentation may look like this:

0 0 0 0
0 0 0 0
0 0 0 0

Then you "push_back" 10 rows from thereon; counting from 0.

0 ..
1 ..
2 ..
3 ..
4 ..
5 ..
6 .. //This is actually the 7th added row plus the 3 initial rows, making this the 10th row.
7 .. //Not displayed
8 .. //Not displayed
9 .. //Not displayed

As for your garbage data:
It's due to undefined behavior. The first 3 vectors have 4 declared data and garbage there after.

Either remove predefined vectors in matrix, or set their size to the appropriate size; 20 in your case.

Hope this helps.

Edit: the last three rows are also not shown. Possibly you may want to remove the predefined vector.
 
std::vector< std::vector< double > > Matrix;


Or limit the push_back or rows; -3 since you already have 3 rows preset.
 
for (int i=0;i<7;i++)


Coding on browser; errors may arise.
Last edited on
Thanks, Dput. I noticed if I change the vector declaration, I get output more like I had expected, so I can see that push_back is only adding to elements beyond what is initially declared.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main()
{
    vector< vector< double > > Matrix;

    //populate vector
    for (int i=0;i<10;i++)
    {
        vector<double> row;//creates empty row
        for (int j=0;j<10;j++)
            row.push_back(i+1+j);//add an element to the row
        Matrix.push_back(row);//add row to main vector
    }
    //output vector
    for (int y=0;y<10;y++)
    {
        for (int x=0;x<10;x++)
            cout<<Matrix[y][x]<<" ";
        cout<<endl;
    }
}

Now it works. I suppose the use of push_back or typical operators more like Matrix[1][3]=7; may be preferable depending on how the vector was declared and where the values are being added. Yet, how could I make use of Matrix.Size() within a 2D vector?
Last edited on
You are still using hardcoded values for row and column lengths.

The below is pseudo-C++.

vector<vector<int> > matrix;

matrix.push_back([0]);
matrix.push_back([1 2]);
matrix.push_back([3 4 5 6]);

matrix == [
    [0],
    [1 2],
    [3 4 5 6]
];

matrix.size() == 3; // height of matrix

matrix.at(0).size() == 1; // length of first row
matrix.at(1).size() == 2; // length of second row
matrix.at(2).size() == 4; // length of third row


So your for() loop for printing the matrix, if you don't want to use iterators or the C++11 range-based for() loop, should look a bit like:

1
2
3
for (int y=0; y < matrix.size(); ++y)
    for (int x=0; x < matrix.at(y).size(); ++x)
        // ... 


Of course instead of int, it is recommended to use std::vector::size_type, or std::size_t or at least unsigned int, because comparing signed with unsigned is nasty.

1
2
3
4
5
6
7
#include <cstddef>

// ...

for (std::size_t y=0; y < matrix.size(); ++y)
    for (std::size_t x=0; x < matrix.at(y).size(); ++x)
        // ... 

closed account (j3Rz8vqX)
Example of Matrix.Size():
1
2
3
std::cout<<"Number of rows in Matrix: "<<Matrix[y].size()<<endl; //this will print out the number of rows for Matrix.

std::cout<<"Number of columns in Matrix: "<<Matrix[y][x].size()<<endl; //this will print out the number of columns for Matrix. 


I have not test the above code; simply written on browser - may not work.
I have not test the above code; simply written on browser - may not work.

It would work if Matrix was 3D.

However for a 2D matrix, Matrix[y][x].size() doesn't work because Matrix[y][x] is a simple double.

So the simple correction is:

1
2
3
4
5
6
std::cout<<"Number of rows in Matrix: "<<Matrix.size()<<endl;
//this will print out the number of rows for Matrix.

std::cout<<"Number of columns in Matrix: "<<Matrix[y].size()<<endl;
//this will print out the number of columns for Matrix.
// this will print out the length of row y of the Matrix 

Last edited on
Thanks guys, this explains an awful lot. So I need to specify which size I am determining, and the above demonstrates how to do so. Also, Catfish's pseudocode explains a lot about the workings of a vector in comparison to an array. I was able to adapt the output loops to make use of size(), and changed the horizontal number of elements so I could more easily determine between horizontal and vertical.
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
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    // a vector of vectors
    vector< vector< double > > Matrix;//declare 2D vector

    //populate vector
    for (int y=0;y<10;y++)
    {
        vector<double> row;//creates empty row
        //inner loop populates row
        for (int x=0;x<12;x++)
            row.push_back(x+1+y);
        Matrix.push_back(row);//add row to vector Matrix
    }
    //output vector based on vertical and horizontal sizes
    for (int y=0;y<Matrix.size();y++)
    {
        for (int x=0;x<Matrix[y].size();x++)
            cout<<Matrix[y][x]<<" ";
        cout<<endl;
    }
}

1 2 3 4 5 6 7 8 9 10 11 12
2 3 4 5 6 7 8 9 10 11 12 13
3 4 5 6 7 8 9 10 11 12 13 14
4 5 6 7 8 9 10 11 12 13 14 15
5 6 7 8 9 10 11 12 13 14 15 16
6 7 8 9 10 11 12 13 14 15 16 17
7 8 9 10 11 12 13 14 15 16 17 18
8 9 10 11 12 13 14 15 16 17 18 19 
9 10 11 12 13 14 15 16 17 18 19 20
10 11 12 13 14 15 16 17 18 19 20 21

As I experiment further, I may have more questions, but this helps cover the basics while allowing me to leverage the potential advantages of using vectors over arrays.
Last edited on
You could use std::setw() to beautify the printing of the Matrix.
And I'll repeat myself: do not use int in your for() loops.

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

int main()
{
    // a vector of vectors
    vector<vector<double> > Matrix; // declare 2D vector

    // populate vector
    for (size_t y=0; y < 10; y++)
    {
        vector<double> row; // creates empty row

        //inner loop populates row
        for (size_t x=0; x < 12; x++)
            row.push_back(x+1+y);

        Matrix.push_back(row); // add row to vector Matrix
    }

    // output vector based on vertical and horizontal sizes
    for (size_t y=0; y < Matrix.size(); y++)
    {
        for (size_t x=0; x < Matrix[y].size(); x++)
            cout << setw(4) << Matrix[y][x];

        cout << '\n';
    }

    cout << endl;
}


Edit: small style edits.
Last edited on
I missed that earlier, Catfish666. Thanks, this is much better. I similarly had formatted output, but merely added an additional space to values under 10.
Topic archived. No new replies allowed.