Two dimensional array using vector - c++

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;
}

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;
}

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

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.

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.

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]<<" ";

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;
}

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();
}
}
}

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

Related

Sorting columns of a matrix according to a particular row in c++

Is there a simple way to sort matrix in c++ according to eg. first row, so that all elements rearrange accordingly?
Example:
int matrix[3][3] = { {5,2,4},
{1,7,8},
{9,2,6} };
After sorting by first row it would look like this:
{2,4,5},
{7,8,1},
{2,6,9}
Preferably, I'd like to use sort() function, and I don't mind using vectors if it would make the task easier.
As the comments said, it's easier to sort a matrix by a column than by a row, since std::sort with the use of a lambda function will do the job for the former.
My recommendation is to sort the column indices by the row, then use the sorted indices to rebuild the matrix:
#include <algorithm>
using namespace std;
const int n = 3; // size of matrix
int sort_by_row = 0; // row to sort by
int original[n][n] = { {5,2,4},
{1,7,8},
{9,2,6} };
int main() {
int col_indices[n];
for (int i = 0; i < n; i++) col_indices[i] = i; // create column indices 0...n-1
sort(col_indices, col_indices + n, [] (const int &a, const int &b) { // sort indices by row
return original[sort_by_row][a] < original[sort_by_row][b];
});
int sorted[n][n]; // rebuild matrix
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
sorted[i][j] = original[i][col_indices[j]];
}
}
}
In this method, you iterate over the matrix once only, whereas if you transpose the matrix, sort, then transpose it back, you iterate over the matrix twice (during transposition).

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

I am confused about c++ two dimensioanal vectors
#include <vector>
int main()
{
//First Code
std::vector<int> oneDimArray;
oneDimArray.push_back(5);
for (int i = 0; i < oneDimArray.size(); i++)
{
std::cout << oneDimArray[i];
}
//Second Code
std::vector<std::vector<int>> twoDimArray;
twoDimArray[0].push_back(5); //Here giving error
for (int i = 0; i < twoDimArray.size(); i++)
{
for (int j : twoDimArray[i])
{
std::cout << j;
}
}
return 0;
}
when i try to run this code First Code is working. But in Second Code i am getting vector out of range error while trying to push back. I guess at first i should say twoDimArray's first size to it. But i dont know how. Because i am definig this twoDimArray in my .h file so if i do this i must do it there. Please can you help me?
The reason this is happening is because of two reasons.
The vector you are trying to access is empty
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.

Segmentation fault by pushing back 2D vector

I have a function that takes a numeric string and assigns each element into a single dimension vector:
void insert(vector<int> &matrix, string s)
{
for (int i=0; i<s.length(); i++)
matrix.push_back(s[i]-'0');
}
Then, at my main function I declare a 2D vector:
vector<vector<int>> matrix;
Now for example I try to execute the function:
insert(matrix[0],"12345");
It will simply give me error Segmentation fault, and I don't know why.
How do I solve this problem ?
I think because you are declaring your 2Dvector like
vector<vector> matrix;
so by declaring like this your matrix is of size 0.
Since your matrix is empty you cannot access elements from that. Instead init your 2d vector with some default values like 0 and give a try.
#include <vector>
#include <iostream>
using namespace std;
void insert(vector<int> &matrix, string s)
{
for (int i=0; i<s.length(); i++)
matrix.push_back(s[i]-'0');
}
int main()
{
int n=2,m=2;
vector<vector<int> > matrix(n, vector<int>(m));
insert(matrix[0],"12345");
for (auto i:matrix)
{
for (auto j:i)
{
cout << j;
}
}
}
I am not sure if this is what you are expecting from your insert func

Best way to convert 2D vector to C type (for SGX enclave)

I'm trying to write an SGX enclave that takes in a 2D vector of int (representing a grayscale image), but edger8r accepts only C types.
I am aware of this and this, but could someone provide an example on how to transform a type like:
vector< vector <int> > ImagePixels;
into a C type so that I can pass it to an SGX enclave?
std::vector has a data() method that will give you a plain pointer to its data. However, you'll need to do something with that second layer of vectors, so you'll need to create a temporary array that will store a list of plain pointers from the inner vector.
#include <algorithm>
#include <iostream>
#include <vector>
extern "C" int my_c_function(int **double_pointer, int rows, int cols) {
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
printf("%d ", double_pointer[i][j]);
}
printf("\n");
}
}
int main() {
std::vector<std::vector<int>> ImagePixels{{1, 2, 3}, {4, 5, 6}};
// transform a vector of vectors into a vector of pointers
std::vector<int*> ptrs(ImagePixels.size());
std::transform(begin(ImagePixels), end(ImagePixels), begin(ptrs),
[](std::vector<int> &inner_vec) {
return inner_vec.data();
});
my_c_function(ptrs.data(), ImagePixels.size(), ImagePixels[0].size());
}
Live example: https://onlinegdb.com/BJvb3yG3f
However, if you have control of the entire code, I would suggest using a flat structure, where you just store the whole picture into a falt std::vector<int> row-by-row. You could even do a simple wrapper around std::vector to make it easier to manipulate such a structure:
class image {
public:
image(int rows = 0; int cols = 0)
: rows_{rows}, cols_{cols}, data_(rows * cols) {}
int &operator ()(int row, int col) {
return data_[row * cols_ + col];
}
int *data() { return data_.data(); };
// needs a few more utilities and constant versions of the methods
private:
std::vector<int> data_;
int rows_;
int cols_;
};
Then you can do:
image im(3, 2);
// set pixels
im(0, 0) = 1;
im(0, 1) = 2;
int *d = im.data(); // a plain pointer to an array of data

Fill 2D vector in C++

I'm trying to fill 2D vector in C++ with characters, but when I run this code it ends with one line characters (*..).
How can I fill 2D vector like this:
*.*
.**
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<char> > vec2D;
std::vector<char> rowV;
unsigned int row=2;
unsigned int col=3;
char c;
unsigned int temp=0;
while(temp!=col)
{
while(rowV.size()!=row)
{
std::cin>>c;
rowV.push_back(c);
}
vec2D.push_back(rowV);
++temp;
}
return 0;
}
You should clear rowV after each insertion, otherwise it will be full and no other characters will be added. Also, row should be swapped by col and vice-versa, otherwise you will get a 3x2 (and not 2x3) 2D vector.
while(temp!=row)
{
while(rowV.size()!=col)
{
std::cin>>c;
rowV.push_back(c);
}
vec2D.push_back(rowV);
rowV.clear(); // clear after inserting
++temp;
}
It helps to know what [pushing back a 2DVector with an empty 1D vector] looks like.
See the example below.
#include <algorithm>
#include <cmath>
#include <iostream>
#include <vector>
using namespace std;
//-v-----A FUNCTION TO PRINT 2D VECTORS
template<typename T> //We don't know what type the elements are yet, so we use a template
void printVec2D(vector<vector<T>> a) // a is the name of our input 2Dvector of type (T)
{
for (int i = 0; i < a.size(); i++) {// a.size() will equal the number of rows (i suppose rows/columns can depend on how you look at it)
for (int j = 0; j < a[i].size(); j++) {// a[i].size() is the size of the i'th row (which equals the number of columns, foro a square array)
std::cout << a[i][j] << "\t";
}
std::cout << "\n";
}
return;
}
//-^--------
int main()
{
int X = 3; int Y = 3;
int VectorAsArray[3][3] = {{1,2,3},
{14,15,16},
{107,108,109}};
vector<vector<int>> T;
for (int i = 0; i < X; i++)
{
T.push_back({});// We insert a blank row until there are X rows
for (int j = 0; j < Y; j++)
{
T[i].push_back(VectorAsArray[i][j]); //Within the j'th row, we insert the element corresponding to the i'th column
}
}
printVec2D(T);
//system("pause"); //<- I know that this command works on Windows, but unsure otherwise( it is just a way to pause the program)
return 0;
}