Accessing Matrices from Vector of Pointers Passed to Function in C++ - c++

I started writing in C++ a few months ago and am having some trouble using pointers. In the code that I've been writing for work, I've defined several matrices using the matrix_t class that I wrote. I created a vector that contains pointers to these matrices. I pass the vector to a function which accesses the matrices. Here's a simple example of what I'm trying to do:
#include <iostream>
#include "matrix_t.h"
using namespace std;
int mat_access (vector <matrix_t<int>*> &pmatrices)
{
matrix_t<int> mat = *pmatrices[0];
return mat.get_cell(0, 0);
/*get_cell(r, c) returns the value at row r, column c*/
}
int main()
{
vector <matrix_t<int>*> pmatrices(1);
matrix_t <int> mat (1, 1, 1);
/*mat_1(v, r, c) has r rows, c columns, and is filled with the value v*/
pmatrices[0] = &mat;
for (size_t i = 0; i < 5; i ++)
{
int k = mat_access(pmatrices);
cout << k;
}
}
If I step through the function while debugging, it works the first time the function mat_access is called. However, the second time that get_cell is called (even though its for the same row and column of the same matrix) a breakpoint is triggered and I get an error message in the output that says an invalid address is being accessed. I'm using App Verifier and the call stack location it returns has no source code. If I don't pass the vector of pointers to a function, but instead just access it directly in the main method, it works fine. Also, If I run the same code using vectors instead of matrices, it works fine. I don't think it's a problem with get_cell because I've used it at several other places in my code and I'm sure the indexing is correct. Here's what it looks like within the matrix_t class:
T get_cell (size_t row, size_t col) const
{ try
{
if (row >= n_rows || col >= n_cols)
throw myerror("Index out of bounds");
}
catch (exception &e)
{
cout << "Exception: " << e.what() << '\n';
}
return t_array [col * n_rows + row];
}
t_array contains the matrix elements and n_rows is the number of rows of the matrix. If all else fails, I'll just combine my matrices into one matrix and pass that to the function, but I'd like to understand why this isn't working. Any input would be appreciated.

Syntactically, I don't see any issues with your code. Try running this snippet (equivalent to what you have above) and see if you encounter the same error. If not, most likely the issue is in your matrix code.
int foo(vector<int*> &v) {
int x = *v[0];
return x;
}
int main() {
vector<int*> v(1);
int x = 9;
v[0] = &x;
for(int i = 0; i < 5; ++i) {
int y = foo(v);
cout << y << endl;
}
return 0;
}

Related

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.

why my function doesn't change my object's attribute

I'm trying to do a Matrix class using C++ Vector, but i don't know why the inside of "Matrix result" inside my function isn't passed to my object but it remain enclosed inside the function.
for semplicity so far I've tryed only to do an "addition function" among two Matrices.
I have tryied to work with pointer but in this way (according to my knowledgs) i cant call my funtion to an object in this wise:
foo.function1(bar1).function2(bar2);
but working with pointer i have to call function in this manner:
foo.function1(bar1);
foo.function2(bar2);
//and so on..
this is my header file:
#include <iostream>
#include <vector>
using namespace std;
class Matrix
{
public:
Matrix (int height, int width);
Matrix add(Matrix m);
Matrix applyFunction(double (*function)(double));
void print();
private:
vector<vector<double> > matrix;
int height;
int width;
};
this is the .cpp file:
Matrix::Matrix(int height, int width)
{
this->height = height;
this->width = width;
this->matrix = vector<vector<double> >(this->height, vector<double>(this->width));
}
Matrix Matrix::add(Matrix m)
{
Matrix result(this->height, this->width);
if (m.height== this->height&& m.width== this->width)
{
for (int i = 0; i < this->height; i++)
{
for (int j = 0; j < this->width; j++)
{
result.matrix[i][j] = this->matrix[i][j] + m.matrix[i][j];
}
return result;
}
}
else
{
cout << "Impossible to do addition, matrices doesn't have the same dimension" << endl;
return result;
}
}
Matrix Matrix::applyFunction(double(*function)(double))
{
Matrix result(this->height, this->width);
for (int i = 0; i < this->height; i++)
{
for (int j = 0; j < this->width; j++)
{
result.matrix[i][j] = (*function)(this->matrix[i][j]);
}
}
return result;
}
void Matrix::print()
{
for (int i = 0; i < this->height; i++)
{
for (int j = 0; j < this->width; j++)
{
cout << this->matrix[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
the output should be the addition beetwen A B 2x2:
x1 x2
x3 x4
but computer show only zeros.
Your member functions all return a new object (they return "by value").
From your usage of chaining, it seems like you actually want to modify the object and return *this by reference.
Otherwise you'll need something like:
auto bar2 = foo.function1(bar1);
auto bar3 = foo.function2(bar2);
// etc
There are no pointers here at present.
There are two variants how you can implement your add
Matrix add(Matrix m)
{
// optimisation: you don't need separate result, m already IS a copy!
// so you can just calculate:
...
{
m.matrix[i][j] += this->matrix[i][j];
}
return m;
}
or:
Matrix& add(Matrix const& m)
// ^ accept const reference to avoid unnecessary copy
// ^ returning reference(!)
{
...
{
// modifies itself!
this->matrix[i][j] += m.matrix[i][j];
}
return *this; // <- (!)
}
This allows now to do:
Matrix m0, m1, m2;
m0.add(m1).add(m2);
// m0 now contains the result, original value is lost (!)
So you don't need the final assignment as in first variant:
m0 = m0.add(m1).add(m2);
// or assign to a new variable, if you want to retain m0's original values
which is what you lacked in your question (thus you did not get the desired result).
Maybe you want to have both variants, and you might rename one of. But there's a nice feature in C++ that you might like even better: Operator overloading. Consider ordinary int:
int n0, n1;
n0 += n1;
int n2 = n0 + n1;
Well, suppose you know what's going on. And if you could do exactly the same with your matrices? Actually, you can! You need to do is overloading the operators:
Matrix& operator+=(Matrix const& m)
{
// identical to second variant of add above!
}
Matrix operator+(Matrix m) // again: the copy!
{
// now implement in terms of operator+=:
return m += *this;
}
Yes, now you can do:
Matrix m0, m1, m2;
m0 += m1 += m2;
m2 = m1 + m0;
Alternatively (and I'd prefer it) you can implement the second operator (operator+) as free standing function as well:
// defined OUTSIDE Matrix class!
Matrix operator+(Matrix first, Matrix const& second)
{
return first += second;
}
Finally: If dimensions don't match, better than returning some dummy matrix would be throwing some exception; std::domain_error might be a candidate for, or you define your own exception, something like SizeMismatch. And please don't output anything to console or elsewhere in such operators, this is not what anybody would expect from them, additionally, you impose console output to others who might consider it inappropriate (perhaps they want output in another language?).

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.

Can I search a vector of vectors of characters to find a specific character and get its coordinates?

I have a map of a room that I have put into a vector of vectors of characters (vector>). The map will look something like this:
# * #
* * D
S * #
where # are walls, * are path areas, S is the start and D is the end. I will not know what the map looks like ahead of time so I want my program to be able to read any map with similar characteristics to the one above.
Thus, I would like to be able to search my vector of vectors to find the coordinates/location of S, so I know where the starting point of the maze is. I have only been able to find examples for just a single vector (one-dimension). Is this possible to do with a vector of vectors (two-dimensions)? If so, how can I do it?
Here is the code I used to create the matrix:
vector<vector<char>> GetMap(int& M, int& N) //function to get the map of a room
{
vector<vector<char>> matrix{}; //give a matrix
char char_buf;
for (int rows = 0; rows < M; rows++)
{
matrix.push_back(vector<char>()); //Put a new empty row in your matrix
for (int cols = 0; cols < N; cols++)
{
cin >> char_buf; //Here we get a char from cin
matrix.back().push_back(char_buf); //That you push back in your sub-vector
}
}
return matrix;
}
First of all, your GetMap function is constantly pushing back new elements. That's a big no no when you already have the size of the matrix available to you (M and N). Also, there is really no need for the size parameters to be of type int&. A simple int is fine and, in most cases, even more efficient.
Rule of thumb: Only use references for non-basic types like vector, string and pretty much all classes.
Also, the fact that you use int& and not const int& doesn't allow you to call the function by passing rvalues (variables without names). For example GetMap(5, 5).
Now, to finally answer your question. Since you already have an idea on how to parse the whole matrix in your GetMap function. I really don't see the problem in creating a similar function that would get the position of a desired character.
The full working code with some enhancements:
#include <iostream>
#include <vector>
using namespace std;
struct Pos{
Pos() : x(0), y(0) {}
Pos(int x, int y) : x(x), y(y) {}
int x;
int y;
};
vector<vector<char>> GetMap(const int height, const int width) //function to get the map of a room
{
//Create the matrix with the constructor (much more efficent than constantly push_back'ing elements)
vector<vector<char>> matrix(height, vector<char>(width));
//Go through every single char in the matrix
for (int rows = 0; rows < height; rows++)
{
for (int cols = 0; cols < width; cols++)
{
cin >> matrix[rows][cols];
}
}
return matrix;
}
Pos getElementPos(const vector<vector<char>>& matrix, const char toFind)
{
int height = matrix.size();
int width = matrix[0].size();
//Go through every single char in the matrix
for (int rows = 0; rows < height; rows++)
{
for (int cols = 0; cols < width; cols++)
{
if(matrix[rows][cols] == toFind){
return Pos(cols, rows);
}
}
}
// In the event that we couldn't find the element
return Pos(-1, -1);
}
int main(){
vector<vector<char>> map = GetMap(5, 5);
Pos dPos = getElementPos(map, 'D');
cout << "\nThe coordinates of D are " << dPos.x << " and " << dPos.y << '\n';
return 0;
}

Error in passing a matrix as an argument

I am trying to get an understanding of how to work with matrices in C++. The code at the bottom is supposed to take an input matrix and return the places where there are 0s. However, I am getting the following errors:
matrix.cpp:47:3: error: no matching function for call to 'make_zero' make_zero(i,j,l);
^~~~~~~~~
matrix.cpp:8:6: note: candidate function not viable: no known conversion from 'double [i][j]' to
'double (*)[col]' for 3rd argument
void make_zero(int row, int col, double matrix[row][col])
^
1 error generated.
when I try to run the following code:
// Matrix
#include <iostream>
#include <stdio.h>
using namespace std;
void make_zero(int row, int col, double matrix[row][col])
{
int k,l;
for(k=0;k<row;k++)
for(l=0;l<col;l++)
{
if(matrix[k][l]==0)
printf("%d %d\n",k,l);
}
}
int main ()
{
int i = 0,j = 0;
cout << "Enter no of rows of the matrix";
cin >> i;
cout << "Enter no of columns of the matrix";
cin >> j;
double l[i][j];
int p = 0, q = 0;
while (p < i) {
while (q < j) {
cout << "Enter the" << p + 1 << "*" << q + 1 << "entry";
cin >> l[p][q];
q = q + 1;
}
p = p + 1;
q = 0;
}
cout << l << "\n";
make_zero(i,j,l);
}
Any help would be appreciated. Thanks.
There are a bunch of ways to do this with pointers. The most common is
void make_zero(int row, int col, double ** matrix)
defines a pointer (usually rows) to a pointer (usually columns). Unfortunately
double l[i][j];
does not define a pointer to a pointer. If this syntax is supported by the compiler, and the compiler is not required to allow arrays of variable length, it most likely defines a pointer to a 1D array (double l[i*j];) and hides the indexing arithmetic used to convert the array to two dimensions. Anyway, it can't be passed to a double ** because it isn't a double **
Trying to pass as an array is troublesome
void make_zero(int row, int col, double matrix[][NUMBER_OF_COLUMNS])
The number of columns in the array must be known to perform the indexing arithmetic and be provided to any functions called with it. This means that number of columns cannot be changed at run time because the indexing used by the function will be rendered invalid.
Getting around this would require changes to the compiler that will drive it further and further from the C++ standard. A bad idea since there are a number of simple ways around calling functions with multi dimensional arrays. Most depend on arrays of arrays or std::vectors of std::vectors.
And when it comes to these solutions, as far as I'm concerned, the best is don't. I'm not going to cover them.
None of the arrays representing a dimension are guaranteed to be anywhere close to the others in memory, and this limits the CPU's ability to read and cache. Without caching and being able to look ahead, a modern CPU is at a serious performance disadvantage. (Read for more information: Why is it faster to process a sorted array than an unsorted array?)
So what you want is a 1 D array, and those are easy to pass around. The indexing math is also easy, row number * size of column + column number, but you need to pass at least the size of the column around. Rather than scatter the book-keeping around like this:
void make_zero(int row, int col, std::vector<double> matrix)
make a wrapper class like this:
class Matrix
{
private:
std::vector<double> myArray;
size_t nrRows;
size_t nrColumns;
public:
Matrix(size_t rows, size_t columns) :
myArray(rows * columns), // allocate vector to store matrix.
nrRows(rows),
nrColumns(columns)
{
}
size_t getNrRows() const
{
return nrRows;
}
size_t getNrColumns() const
{
return nrColumns;
}
// gets value at row, column and returns a reference so caller can
// modify the value
double& operator()(size_t row, size_t column)
{
// note: No sanity check for row >= nrRows or column > nrColumns
return myArray[row * nrColumns + column];
}
// gets value at row, column and returns a copy so caller cannot
// change the contents of the Matrix
double operator()(size_t row, size_t column) const
{
return myArray[row * nrColumns + column];
}
};
Using the vector gets around a number of common pointer-to-array problems by managing its own memory. No destructor is required and Matrix can be copied and moved without requiring special handling because vector performs all that heavy lifting for us.
And as a usage example, let's make a function that prints the matrix out:
std::ostream & operator<<(std::ostream & out, const Matrix & in)
{
for (size_t i = 0; i < in.getNrRows(); i++)
{
for (size_t j = 0; j < in.getNrColumns(); j++)
{
out << in(i,j) << ' ';
}
out << "\n";
}
return out;
}
And modifying OP's main function to use Matrix we get:
int main()
{
int i = 0, j = 0;
cout << "Enter no of rows of the matrix";
cin >> i;
cout << "Enter no of columns of the matrix";
cin >> j;
Matrix matrix(i,j);
int p = 0, q = 0;
while (p < i)
{
while (q < j)
{
cout << "Enter the" << p + 1 << "*" << q + 1 << "entry";
cin >> matrix(p,q);
q = q + 1;
}
p = p + 1;
q = 0;
}
cout << matrix << "\n";
make_zero(matrix);
}
void make_zero(int row, int col, double ** matrix)
Note, that you need to pass also size of the matrix separately.
Also you can use
std::vector<std::vector<double> >
instead and pass this object by reference, pointer, or just make a copy.
Actually, it works, but your problem in this line also:
double l[i][j];
i, j is unknown during the compile time.
You have 2 ways.
1) dynamically allocate the memory
2) use std::vector<std::vector<double> >. Default constructor already sets zero values. But you can do it manually like this:
#include <iostream>
#include <vector>
void make_zero(std::vector<std::vector<double> > & to_zero) {
for (int i = 0; i < to_zero.size(); ++i) {
for (int j = 0; j < to_zero[i].size(); ++j) {
to_zero[i][j] = 0;
}
}
}
void print_double_vector(const std::vector<std::vector<double> > & to_print) {
for (int i = 0; i < to_print.size(); ++i) {
for (int j = 0; j < to_print[i].size(); ++j) {
std::cout << to_print[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
int main() {
// your code goes here
int n, m;
std::cin >> n >> m;
std::vector<std::vector<double> > d(n, std::vector<double>(m));
print_double_vector(d);
make_zero(d);
print_double_vector(d);
return 0;
}
http://ideone.com/0X53Yj