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

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.

Related

Debug Assertion Failed: Expression vector subscript out of range

I dont understand why it says subscript out of range when I have reserved the space in the vector. I have created a short form of my code to explain what the problem is better:
#include <vector>
#include <string>
#include <thread>
#include <iostream>
using namespace std;
class A {
public:
vector<vector<string>> foo;
thread* aThread;
A() {
foo.reserve(10); //makes sure we have space...
aThread = new thread([this]() {
for (int i = 0; i < 10; i++) {
foo[i].push_back("Hello"); // Debug assertion failed. :(
}
});
}
};
int main()
{
A a;
a.aThread->join();
for (int i = 0; i < 10; i++) {
for (int j = 0; j < a.foo.size(); j++) {
cout << a.foo[i][j] << " ";
}
cout << endl;
}
return 0;
}
Here it gives the error as soon as I am trying to add the element into my foo vector inside the thread. I cannot figure out what is wrong. Please help.
foo.reserve(10)
Reserves space for elements in foo, but it does not populate any of the elements with an empty std::vector.
You can change it to:
foo.resize(10);
Which will reserve the space and create the empty vector< string > elements, so that you can access them.

Access vector of vector pointers

I wanted to create a matrix with vectors. In the below code, I created a vector with each entry containing a pointer to another vector(myvector) that acts as columns. I push random values to the myvector (i.e. columns). But when I try to access the values of arrays, it pops an compile error saying "error: no match for 'operator*' (operand type is 'std::vector<int>') at the cout statement. I wonder how do I access the values. I'm pretty sure this is a naive question.
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
std::vector<vector<int>*> main;
for(int j=0; j<3; j++){
vector<int> *myvector = new vector<int>;
main.push_back(myvector);
}
main[0]->push_back(1);
main[0]->push_back(4);
main[1]->push_back(6);
main[1]->push_back(7);
main[1]->push_back(8);
main[2]->push_back(3);
for(int j=0; j<3; j++){
for(uint32_t i=0; i<main[j]->size(); i++)
std::cout<<main[j][i]<<" ";
cout<<"\n";
}
return 0;
}
You could just have done
vector<vector<int>> main;
each index of vector main represents another vector
so to push a number in the first column you can do
main[0].push_back = (_number_)
To access a number in first row in first column we can do main[0][0]
This example shows both the syntax you where looking for, and also an example of how you should use std::vector without new/delete.
#include <iostream>
#include <vector>
#include <memory>
// using namespace std; <== teach yourself NOT to do this.
// https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
void access_pointers_in_2d_vector()
{
std::vector<std::vector<int>*> values; // don't call your variables main!
for (int j = 0; j < 3; j++)
{
std::vector<int>* myvector = new std::vector<int>;
values.push_back(myvector);
}
values[0]->push_back(1);
values[0]->push_back(4);
values[1]->push_back(6);
values[1]->push_back(7);
values[1]->push_back(8);
values[2]->push_back(3);
for (int j = 0; j < 3; j++)
{
for (uint32_t i = 0; i < values[j]->size(); i++)
{
//==================================================================
// this is the syntax you're looking for
// first dereference the pointer then use operator[]
std::cout << (*values[j])[i] << " ";
//==================================================================
}
std::cout << "\n";
}
// don't forget to cleanup your memory!
// if you typed new somewhere then there should
// ALWAYS be a matching delete in your code too!
for (int j = 0; j < 3; j++)
{
delete values[j]; // <<==== !!!!!!!
}
}
// for dynamic memory managment new/delete aren't recommended anymore.
// use std::unique_pointer (or if your design really requires it std::shared_ptr)
void using_unique_pointer()
{
// If you really need pointers, use std::unique_ptr
// it will prevent you from introducing memory leaks
const std::uint32_t size = 3ul;
std::vector<std::unique_ptr<std::vector<int>>> values(size);
for (auto& p : values)
{
p = std::make_unique<std::vector<int>>();
}
values[0]->push_back(1);
values[0]->push_back(4);
values[1]->push_back(6);
values[1]->push_back(7);
values[1]->push_back(8);
values[2]->push_back(3);
// output loop is same as for normal pointers.
// no need to call delete, std::unique_ptr will do that for you
}
void without_pointers()
{
// However your whole code in idiomatic c++ should look like this.
// https://en.cppreference.com/w/cpp/container/vector/vector constructor (10)
// https://en.cppreference.com/w/cpp/language/range-for these loops avoid bugs related to
// letting indices go out of bounds.
std::cout << "\nusing (nested) initializer list and range based for loops : \n";
std::vector<std::vector<int>> rows{ {1,4}, {6,7,8}, {3} };
for (const auto& row : rows)
{
for (const auto& value : row)
{
std::cout << value << " ";
}
std::cout << "\n";
}
}
int main()
{
access_pointers_in_2d_vector();
using_unique_pointer();
without_pointers();
return 0;
}

Segmentation fault (core dumped) in c++ with 2d vector

I'm trying to create a puzzle solver using c++ for the first time. i've managed to create a sctruct named board with a 2d string vector and two interget repersenting the position of blank space.
However when i am assigning values to board i ran into this Segmentation fault (core dumped) and i dont know where i did wrong. If someone can pointed it out it would be much appreciate.
#include <vector>
#include <iterator>
#include <list>
#include <string.h>
using namespace std;
struct Board
{
vector<vector<string>> board;
int blankx, blanky;
};
Board getBoard(string state)
{
Board board;
vector<vector<string>> matrix;
int count = 0;
for (size_t i = 0; i < 3; i++)
{
for (size_t j = 0; j < 3; i++)
{
board.board [i][j] = state[count];
if (state[count] == '#')
{
board.blankx = i;
board.blanky = j;
}
count++;
}
}
return board;
}
void findCost(string beginstate, string goalstate)
{
int cost = 0;
Board initBoard, finalBoard;
initBoard = getBoard(beginstate);
// printBoard(initBoard);
cout << "the optimal cost is : " << cost << "\n";
}
int main()
{
string beginState, goalState;
cout << "please enter the begin state:\n";
cin >> beginState;
cout << "please enter the goal state:\n";
cin >> goalState;
findCost(beginState, goalState);
}
struct Board
{
vector<vector<string>> board;
int blankx, blanky;
};
When a Board gets created, its board member is a completely empty vector.
Board board;
// ...
board.board [i][j] = state[count];
This creates a Board, then proceeds and assign values to its board std::vector.
That the [] operator for std::vectors does is that it accesses existing values in the vector. It does not create them. They must exist already. The vector must already be resize()d, or values must be push_back()ed into the vector so that board.board[i][j] is an existing value.
Because board.board is completely empty, and has no values at all, this becomes undefined behavior, and the reason for your crash.
There are two critical bugs here:
The default initialized vector board is empty, try to access elements in it will cause the segment fault crash.
It can be fixed by initializing it:
constexpr size_t kNum = 3;
struct Board {
vector<vector<string>> board = {kNum, {kNum, string{}}};
int blankx, blanky;
};
The index is mixed-used: the i in the second loop should be j, or we will get a crash even if the previous one is fixed. May fix as:
for (size_t i = 0; i < kNum; i++) {
for (size_t j = 0; j < kNum; j++) {
As others pointed out, a std::vector is empty, and thus you are accessing the elements out-of-bounds.
The simplest solution, if you stay with using vector, is on construction, where you would initialize the vector appropriately sized:
struct Board
{
std::vector<std::vector<std::string>> board;
int blankx, blanky;
// default constructor creates the board
Board() : board(3, std::vector<std::string>(3)) {}
};

Initialize all elements in matrix with variable dimensions to zero

I'm trying to initialize an int matrix in C++, with user-inputted dimensions, with every element set to zero. I know there are some elegant ways to do that with a one-dimensional array so I was wondering if there are any similar ways to do it with a two-dimensional array without using for loops and iterating through every element.
I found a source that gave several different ways, including std::fill (I've modified the code so that the dimensions are read with cin):
#include <iostream>
using namespace std;
int main() {
int x;
cin >> x;
int matrix[x][x];
fill(*matrix, *matrix + x * 3, 0);
for (int i = 0; i < x; i++) {
for (int j = 0; j < 3; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
}
But why does this work, and why would the pointer to the matrix in the arguments for fill be necessary if it's not necessary for a one-dimensional array? That source said it was because matrixes in C++ are treated like one-dimensional arrays, which would make sense, but that is why I don't understand why the pointer is needed.
I don't know if this is relevant, but in case it can help, I've described my previous attempts below.
At first I thought I could initialize all elements to zero like in a one-dimensional array. For the matrix, this worked fine when the side lengths were not read with cin (i.e. when I declared the matrix as int matrix[3][3] = {{}}; as answered here) but when I tried getting the side lengths from cin I started getting errors.
This was my code:
#include <iostream>
using namespace std;
int main() {
int x;
cin >> x;
int matrix[x][x] = {{}};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
}
And when I tried to compile it, it threw this error:
matrix_test.cpp:7:14: error: variable-sized object may not be initialized
int matrix[x][x] = {{}};
^
1 error generated.
Why you're getting the error
c-style arrays (such as int matrix[3][3]) must have size specified at the point you declare it. They can't vary in size in C++.
What you could do instead.
If you use std::vector, there's a really elegant way to do it:
#include <vector>
#include <iostream>
int main() {
using namespace std;
int x;
cin >> x;
auto matrix = vector<vector<int>>(x, vector<int>(x, 0));
// This is how we can print it
for(auto& row : matrix) {
for(auto& elem : row) {
cout << elem << ' ';
}
cout << '\n';
}
}
In C++17, you can shorten this even further:
auto matrix = vector(x, vector(x, 0));
What vector(number, thing) means is "Create a vector of number, where each element is thing".
The second dimension of two-dimension array must be a compile time constant, but in your code x is not.
Actually if you write a function with a two-dimension parameter, the second dimension must also be a compile time constant. That's because the array is stored linearly in the memory and the compiler must know the second dimension to calculate the offset correctly.

Two dimensional array using vector

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