24

I want to create 2D array using vector. But, when I do this, I get seg fault. Can anyone please explain what I am doing wrong, and possible solution for this problem.

I made everything public since I dont want to deal with getters and setters now. I want to get the concept of 2D array clear.

#include <iostream>
#include <vector>
using namespace std;

class point
{   
    public:
        point():x(0),y(0){}
        ~point(){}
        point(float xx,float yy):x(xx),y(yy){}
        float x,y;
};

int main()
{
    vector<vector<point> > a; // 2D array
    point p(2,3);
    a[0][0] = p; // error here
    return 0;
}
1
  • 1
    But x and y should be public. There is no invariant on point that would require that the members be private. Adding get_x, get_y, set_x, and set_y would make any mathematical function on points nearly impossible to read. Commented Dec 2, 2009 at 23:30

8 Answers 8

51

Your vector is empty. So you can't use [0][0].

Here is how you declare it:

a.push_back(vector<point>());
a[0].push_back(p);

If you know how many items you will have from the start, you can do :

vector<vector<point> > a(10, vector<point>(10));

It's a vector containing 10 vectors containing 10 point. Then you can use

a[4][4] = p;

However, I believe that using vector of vectors is confusing. If you want an array, consider using uBLAS http://www.boost.org/doc/libs/1_41_0/libs/numeric/ublas/doc/index.htm

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>

int main () {
    using namespace boost::numeric::ublas;
    matrix<double> m (3, 3);
    for (unsigned i = 0; i < m.size1 (); ++ i)
        for (unsigned j = 0; j < m.size2 (); ++ j)
            m (i, j) = 3 * i + j;
    std::cout << m << std::endl;
}
Sign up to request clarification or add additional context in comments.

1 Comment

If you have your answer, mark it as such. Otherwise state what extra informatino you need ;)
12

Here's another suggestion. What you're trying to accomplish has been done before and can be found within the Boost Multi-Array.

Comments

7

You have constructed a vector of vectors that is empty, and have tried to dereference the first element without adding any elements to it.

Vectors don't work like (some) associative arrays, where attempting to access a value that's missing will add it to the collection. You need to ensure the vectors have an appropriate number of entries before you try to access them by using the appropriate form of the vector constructor or by using push_back.

Comments

3

You're creating your 2D array just fine. The problem is that when you create it, it's an empty array -- it doesn't hold any points at all yet. You try to use the point at [0][0] before you've actually created a point there. Normally, to put a new element into a vector, you use resize() to set the size of the vector, or push_back() to add items one at a time. In this case, the latter will probably be a bit clumsy -- since you have a vector of vectors of point, you need to create a vector of point, push a point onto that vector, then push that vector onto your array.

Comments

2

The simplest way would be to use resize() method as follow:

vector <vector<int>> v;
cin>>n>>m; //n is rows and m is columns
v.resize(n,vector<int>(m));
for(i=0;i<n;i++)      // inserts elements into the vector v
 for(j=0;j<m;j++)
  cin>>v[i][j]; 

for(i=0;i<n;i++)      //accesses elements of vector v
 for(j=0;j<m;j++)
   cout<<v[i][j]<<" ";

2 Comments

it should be vector<vector<int> >. Leave space between 2 > otherwise theres an error.
Yeah. But as a programmer it's your responsibility to write compiler independent code.
1

Managed to get it working. Picked up the idea for the 'typedef' from somewhere else. Try the below code, it works:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <vector>


using namespace std;

int main()
{
    int i = 0;
    int j = 0;

///////////////////////////////////////////////////////////

    typedef vector<string> vecRow;
    typedef vector<vecRow> vecCol;

    vecRow vr;
    vecCol vc;
///////////////////////////////////////////////////////////
// Assigning string elements to the 2d array

    for(i=0;i<10;i++)
    {
            for(j=0;j<5;j++)
            {
                vr.push_back("string ["+to_string(i)+"]["+to_string(j)+"]");
            }
            vecRow vr_temp = vecRow(vr);
            vc.push_back(vr_temp);
            vr.clear();
    }

///////////////////////////////////////////////////////////
// Printing back the elements from the 2D array

    for(auto element : vc)
    {
            for(unsigned int ictr = 0;ictr < element.size() ; ictr++)
            {
                cout<<element[ictr]<<"\t";
            }
            cout<<endl;
    }

    getchar();
    return 0;
}

Comments

0

You can define vectorMatrix[][], which is a matrix of vectors as follows.

Class:

class vectorMatrix
{
  std::vector<object> **cell;

  int columns;
  int rows;

  public:
  vectorMatrix(int columns, int rows);
  virtual ~vectorMatrix();

  void addCellAt(int row, int column, const object& entry);

  virtual std::vector<object>* getCell(int row, int column);

  void clearMatrix();
};

Define constructor:

vectorMatrix::vectorMatrix(int columns, int rows)
{
   this->columns = columns;
   this->rows = rows;

   cell = new std::vector<object>* [columns];

   for (int i = 0; i < columns; i++)
   {
       cell[i] = new std::vector<object>[rows];
   }
}

A method for adding an entry:

void vectorMatrix::addCellAt(int row, int column, const object& entry)
{
       cell[channel][timeSlot].push_back(entry);
}

Getting a pointer to the vector in a given row and column:

std::vector<object>* vectorMatrix::getCell(int row, int column)
{
    return &cell[row][column];
}

Clearing all the matrix:

void vectorMatrix::clearMatrix()
{
    for (int tmpRow = 0; tmpRow < columns; tmpRow ++)
    {
        for(int tmpColumn = 0; tmpColumn < rows; tmpColumn ++)
        {
            cell[tmpRow][tmpColumn].clear();
        }
    }
}

Comments

0

You can use resize(); e.g., here I resize a to a 100 x 200 array:

  vector<vector<point> > a; // 2D array                                         
  a.resize(100);
  for_each(a.begin(),a.end(),[](vector<point>& v){v.resize(200);});
  point p(2,3);
  a[0][0] = p; // ok now                                                    

7 Comments

The same is accomplished by constructing vector<vector<point>> a(100, vector<point>(200));
Or vector<vector<point>> a(100); for (auto& v : a) v.resize(200);
Is there a way to dynamically set the size of a std::array -- perhaps with templates? template <int w, int h> struct A {array<array<point,w>,h> a;};
Sure, you can do that, but it won't be dynamic; it'll be determined at compile time. std::array lives on the stack, so its size must be known to the compiler. If the size is determined at runtime, it must live in the heap.
But built in arrays like a[n] can be sized at runtime (e.g., void foo(int n) {int a[n]; ... }
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.