C++ Vector of vectors, cannot edit - c++

I have a MatrixGraph class with a member variable M that is of type vector<vector<double> >. I have a constructor that takes in an unsigned, and makes a NxN matrix from that input, and I want to initialize it to zero. The problem is when I run my code the debugger kicks in when I am trying to assign stuff. I have tried to methods, the first:
MatrixGraph::MatrixGraph(unsigned num_nodes) {
for(int i = 0;i < num_nodes;i++) {
for(int j = 0;j < num_nodes;j++) {
M[i][j] = 0.0;//breaks on this line
}//end i for loop
}//end j for loop
}
and the second method i tried i found on here but that didn't work either:
MatrixGraph::MatrixGraph(unsigned num_nodes) {
for(int i = 0;i < num_nodes;i++) {
M[i].resize(num_nodes);//breaks on this line
}
}
i commented on here where the last line on the call stack is before i get errors. The next line after that on the call stack shows me the class vector and is saying that my Pos is greater than the size of my vector. I assume that this is a size zero matrix, but i don't know why i cant make it bigger. Any suggestions?
Thanks!

The reason your code is failing is that you cant use the [] operation on a vector before that element exists. The usual way to add a value to a vector is to use push_back.
If you want to initialize to 0 you want assign(). Resize the outer vector to the required size and then assign each of the inner vectors with 0
M.resize(num_nodes);
for(int i = 0;i < num_nodes;i++)
{
M[i].assign(num_nodes,0.0f);
}//end i for loop
This can also be done. It is cleaner code but a tad less efficient since it makes 1 extra vector object.
vector<double> temp;
temp.assign(num_nodes,0.0);
M.assign(num_nodes,temp);
or just
M.assign(num_nodes,vector<double>(num_nodes,0.0));
neatest one(courtesy #Mike Seymour) would be
MatrixGraph(unsigned num_nodes)
: M(num_nodes, vector<double>(num_nodes,0.0))
{}
(thanks Mike Seymour for the constructor syntax)
What you are doing here is initializing the outer vector with a temp vector full of 0.0s

You need to populate your vector M with data: M.resize(num_nodes)
This should do it:
MatrixGraph::MatrixGraph(unsigned num_nodes)
{
M.resize(num_nodes);
for(int i = 0;i < num_nodes;i++)
{
M[i].resize(num_nodes);
for(int j = 0;j < num_nodes;j++)
{
M[i][j] = 0.0;
}//end j for loop
}//end i for loop
}

Related

2-D vector Size

In C++ , I Made A Code That has A 2D Vector in it and Users are Required to give The inputs In 2D vector . I find It difficult To find The no. of rows in 2 vector with the help of size function.
#include <bits/stdc++.h>
#include <vector>
using namespace std;
int diagonalDifference(vector<vector<int>> arr)
{
int d = arr[0].size();
cout << d;
return 0;
}
int main()
{
int size;
cin >> size;
vector<vector<int>> d;
for (int i = 0; i < size; i++)
{
d[i].resize(size);
for (int j = 0; j < size; j++)
{
cin >> d[i][j];
}
}
cout << diagonalDifference(d);
}
The Output Should BE No. Rows , But it is coming NULL
Here
vector<vector<int>> d;
for (int i = 0; i < size; i++)
{
d[i].resize(size);
//...
d is a vector of size 0 and accessing d[i] is out of bounds. You seem to be aware that you first have to resize the inner vectors, but you missed to do the same for the outer one. I dont really understand how your code can run as far as printing anything for arr[0].size(); without segfaulting. Anyhow, the problem is that there is no element at arr[0].
But first, Look at your function argument -> is a copy of your vector ,use (vector<> & my vec) to avoid the copying mechanism of vector class (copy constructor for instance) cause if you put there your vector as a parameter and u will make some changes inside the function brackets you will not see any results ( if you dont wanna change your primary vector from function main, keep it without changes).
Secondly, look at code snippet pasted below.
std::vector<std::vector<typename>> my_vector{};
my_vector.resize(width);
for (size_t i = 0; i < my_vector.size(); ++i)
{
my_vector[i].resize(height);
}
It gives you two dimensional vector
Operator[] for vector is overloaded and you have to use my_vector[0].size() just
my_vector[1].size() and so on ! I recommend for that displaying the size by kind of loops given in c++ standards
Regards!

outputting a row of a vector

I am learning c++ and I am currently at halt.
I am trying to write a function such that:
It takes in input a one dimensional vector and an integer which specifies a row.
The numbers on that row are put into an output vector for later use.
The only issue is that this online course states that I must use another function that I have made before that allows a 1d vector with one index be able to have two indexes.
it is:
int twod_to_oned(int row, int col, int rowlen){
return row*rowlen+col;
}
logically what I am trying to do:
I use this function to store the input vector into a temporary vector as a 2D matric with i as the x axis and y as the y axis.
from there I have a loop which reads out the numbers on the row needed and stores it in the output vector.
so far I have:
void get_row(int r, const std::vector<int>& in, std::vector<int>& out){
int rowlength = std::sqrt(in.size());
std::vector <int> temp;
for(int i = 0; i < rowlength; i++){ // i is vertical and j is horizontal
for(int j = 0; j < rowlength; j++){
temp[in[twod_to_oned(i,j,side)]]; // now stored as a 2D array(matrix?)
}
}
for(int i=r; i=r; i++){
for(int j=0; j< rowlength; j++){
out[temp[i][j]];
}
}
I'm pretty sure there is something wrong in the first and last loop which turns into a 2D matric then stores the row.
I starred the parts that are incomplete due to my lack of knowledge.
How could I overcome this issue? I would appreciate any help, Many thanks.
takes in input a one dimensional vector
but
int rowlength = std::sqrt(in.size());
The line of code appears to assume that the input is actually a square two dimensional matrix ( i.e. same number of rows and columns ) So which is it? What if the number of elements in the in vector is not a perfect square?
This confusion about the input is likely to cuase your problem and should be sorted out before doing anything else.
I think what you wanted to do is the following:
void get_row(int r, const std::vector<int>& in, std::vector<int>& out) {
int rowlength = std::sqrt(in.size());
std::vector<std::vector<int>> temp; // now a 2D vector (vector of vectors)
for(int i = 0; i < rowlength; i++) {
temp.emplace_back(); // for each row, we need to emplace it
for(int j = 0; j < rowlength; j++) {
// we need to copy every value to the i-th row
temp[i].push_back(in[twod_to_oned(i, j, rowlength)]);
}
}
for(int j = 0; j < rowlength; j++) {
// we copy the r-th row to out
out.push_back(temp[r][j]);
}
}
Your solution used std::vector<int> instead of std::vector<std::vector<int>>. The former does not support accessing elements by [][] syntax.
You were also assigning to that vector out of its bounds. That lead to undefined behaviour. Always use push_back or emplate_back to add elements. Use operator [] only to access the present data.
Lastly, the same holds true for inserting the row to out vector. Only you can know if the out vector holds enough elements. My solution assumes that out is empty, thus we need to push_back the entire row to it.
In addition: you might want to use std::vector::insert instead of manual for() loop. Consider replacing the third loop with:
out.insert(out.end(), temp[r].begin(), temp[r].end());
which may prove being more efficient and readable. The inner for() look of the first loop could also be replaced in such a way (or even better - one could emplace the vector using iterators obtained from the in vector). I highly advise you to try to implement that.

Using comparison operators to sort string array

I looked everywhere and I could not find a concrete answer that suits my needs. I want use this type of format to sort a more complicated array than this example. It compiles, but when I run it I get the terminated by signal SIGSEV (address boundary error).
A simple example of what I am trying to do:
string array[] = {zipper, bad, dog, apple, car};
string temparray[5];
int counter = 0;
for(int i = 0; i < 5; i++){
for(int x = 0; x < 5; x++){
if(array[i] > array[x]){
counter++;
}
}
temparray[counter] = array[i];
}
for(int y = 0; y < 5; y++){
array[y] = temparray[y];
}
What seems to be the problem?
You never reset counter. Suppose that your array is {5,4,3,2,1}. Then after the first iteration of the for loop, you'd have counter=4. After the next iteration of the inner for loop, counter would be 7, and you'd be trying to access the 7th element in temparray on your line
temparray[counter] = array[i];
but temparray is only 5 elements long. I don't offhand know how the > and < operators work for std::string's, but I'd bet oaks to acorns this is your problem.
You can fix this just by adding
counter=0;
directly after the aforementioned line:
temparray[counter] = array[i];
or by initializing it to zero at the start of the loop, or declaring it in the loop or what have you.

Initializing a member vector<vector<int>> in the constructor value-by-value

I have a class that should generate a 2D vector of ints (in the range of 0-1) that I want to use as a map (called matrix).
class generator
{
public:
void draw(void);
void iterate(void);
generator();
~generator();
private:
vector<vector<int>> matrix;
};
In the constructor I want to fill the matrix with random data:
vector<vector<int>> matrix(height, vector<int>(width));
for (int i = 0; i < height; i++){
for (int j = 0; j < width; j++) {
matrix[i][j] = rand() % 2;
}
}
But I get a read acess violation.
Thank you for your time and effort.
DEPRECATED UPDATE:
I tried using the member function .data() to retrieve the pointer to the data and accessing it directly
ptr = matrix[i][j].data();
*ptr = rand() % 2;
But the result doesn't differ. I'm fairly convinced that this isn't about how I want to access the vector but how I set it up.
UPDATE 2:
The correction provided below does result in the vector being filled as intended. When trying to
cout << matrix[i][j];
in the draw member function I get a read-acess-violation again.
UPDATE 3:
As suggested I checked when exactly this error happens. It happens on the very first try do print out the first integer at matrix[0][0]. The value returned is 0x8. Important: If not replaced by a constant matrix.size() already causes the error.
UPDATE 4:
This is basically my draw()
void generator::draw() {
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix[i].size(); j++) {
cout << matrix[i][j];
}
cout << endl;
}
}
The original source has been updated to reflect the current one.
UPDATE 4:
Slightly cut source code at http://pastebin.com/83vrDJWZ
UPDATE 5:
One more simple mistake on my part has been resolved in the comments. Problem is silved. Thank you all.
Looks like the problem is an invalid pointer due to:
vector<vector<int>*> matrix;
You have a vector of pointers to vector of int, but you never actually allocate the inner elements.
Instead use:
vector<vector<int>> matrix;
And during the initialization steps:
matrix[i].resize(width); // instead of: matrix[i]->resize(width);
Actually, you could simplify it a bit:
std::vector<std::vector<int>> matrix(height, std::vector<int>(width));
Still have to iterate to fill the data, though.

how to add elements to front of 2d vector

I have a game that creates a random string of letters and then inputs it to a 2d vector. I was oringally using an array and it filled the array with random letters as it should, but the array was giving me some problems. My friend suggested a 2d array.
Here is the print function that gives me the error that actually causes a break in the program:
const vector<vector<char>>& Board::get_board()
{
for (int i = 0; i < 16; i++)
{
letters.insert(letters.begin(), 1, random_letter());
}
uppercase(letters);
random_shuffle(letters.begin(), letters.end());
int counter = 0;
for (size_t i = 0; i < 4; i++){
for (size_t j = 0; j < 4; j++)
{
board[0].push_back(letters[counter++]);
}
}
I keep getting the array to fill the first row, but then it throws an exception. I'm not sure what the exception is, but when I try to move forward, it tells me the code exited with exception 0 and points to the board[][] line in the print method. I don't think the second vector is being filled. How can I do this? Should I make another temp vector, or use a pair method? I tried the pair method before without much success.
I just changed the 0 to i and indeed, that solved the issue. Thanks! I think that I was thinking the vector would just push to the front counter number of times, not that we had 2 dimensions where the board[i] set the row. Thanks again. Silly error.
Your vector isn't being populated correctly in your get_board() method:
board[0].push_back(letters[counter]);
You're always pushing back onto the first element, but then you use it with the expectation that the board vector has 4 entries in it with the print() method. You also never increment counter and so you always push back the same letter...
Okay, based on comments, you've said you fixed how populate to something more like?
int counter = 0;
for (size_t i = 0; i < 4; i++){
for (size_t j = 0; j < 4; j++)
{
board[i].push_back(letters[counter++]);
}
}
I also don't see the point of the if statement in the print() method.