looping through a dynamically allocated matrix - c++

So I have looked through some online questions to figure out how to setup and fill a dynamic multidimensional array and I thought I had it down but for some reason my function will not access the anything past the first(0) column. For my test I put in a 2X2 array:
2 2 (part of another function that gives the size of the matrix)
1 2
3 4
When I debug it I only get
1 random# from initializing the array
3 random# from initializing the array
I'm not sure what I am doing wrong with this piece of code, I am also new to C++.
double* matrix_read(const int m, const int n)
{
double **mat = new double*[m];
for (int j = 0; j < m; ++j) {
mat[j] = new double[n];
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
cin >> mat[i][j];
}
}
double debug = mat[2][2];
return *mat;
}
Inside the main function this is what I send to the function.
int x, y, m, n;
cin >> x;
cin >> y;
double *mat_a = matrix_read(x, y);
cin >> m; //2nd matrix read in
cin >> n;
double *mat_b = matrix_read(m, n);

Your matrix is represented as an array of pointers, each pointer in the array points, in turn, to an array of doubles. Each of these arrays are contiguous in memory, but not among themselves. This means that, mat[0][0] is right before mat[0][1] in memory. But mat[1][0] may be in a completely different location.
By returning only the first line of your matrix, *mat (the same as mat[0]), you will lose information. All you have access to is the first line.
You should return the whole matrix.
double** matrix_read(...) {
...
return mat;
}
(Edit: Besides, someone will have to delete the matrix later.. and they have to delete several arrays, ugh. You should make a structure wrapper for matrices, or use a single array, or use a vector of vectors)

Related

Overflow error when using C++ std::cin, has strange value inside variable (C++11)

For a C++ program, I've implemented 2 functions:
Make1DArray that takes array size as input and creates a 1D array of that size
Make2DArray that takes size of row and column and creates a 2D array of the given row and column sizes
The main function looks like this:
int main()
{
cout << "enter 1d array length: ";
int x;
cin >> x;
Make1DArray(x);
cout << "enter 2d array row size: ";
int nrows, ncols;
cin >> nrows;
cout << "enter 2d array col size: ";
cin >> ncols;
Make2DArray(nrows, ncols);
return 0;
}
When I input x = 10000000000 (10^10), the program outputs does not run the second function and asks for input. The message outputs look like this:
enter 1d array length: 100000000000
enter 2d array row size: enter 2d array col size:
So I checked the values for x, nrow, and ncol and the values were this:
x = 2147483647
nrows = 0
ncols = 32767
I googled a bit and found out that when an overflow error happens, cin would assign x the closest value.
For nrows I understand it might get 0, as an error happened.
What I don't get is why the third variable, ncols is assigned value 32767. I did find out that 32767 is the max value of a short int but I don't know why the variable ncols would get this value.
Could anyone explain me this? Thanks!
ETA: I wasn't sure if I should add the two functions because they're really simple but just in case, they look like this:
void Make1DArray(int arrSize) {
int *arr;
arr = (int *)malloc(arrSize * sizeof(int));
for (int i = 0; i < arrSize; i++)
{
arr[i] = i;
}
}
void Make2DArray(int nrows, int ncols) {
int **arr = (int **)malloc(nrows * sizeof(int *));
for (int i = 0; i < nrows; i++)
arr[i] = (int *)malloc(ncols * sizeof(int));
int count;
for (int i = 0; i < nrows; i++)
for (int j = 0; j < ncols; j++)
{
arr[i][j] = ++count;
}
}
The problem
THe problem is that the first overflow sets the failbit due to the value overflow. The subsequent readings are not performed, leaving nrows and ncols in an undefined state. If you'd initialize theses variables, you'll notice that they wouldn't change.
Solution
Do not use int for holding the size but size_t instead. This should work with your example figures on most compilers.
If you want your code to be bullet proof, check the state on cin to see if input was valid and handle any errors if necessary (including cin.clear() to clear the fail state before resuming reading).
Not related: in the code of your functions (which leak memory by the way), iterate on a size_t as well. And avoid malloc(): in C++ prefer new for dynamically creating objects.

Way to ensure a dynamically allocated matrix is square?

I would like to determine if there is a way to determine whether a dynamically allocated matrix is square (nxn).
The first thing that came to mind was to see if there is a way to find out whether a pointer is about to point to an invalid memory location. But according to these posts:
C++ Is it possible to determine whether a pointer points to a valid object?
Testing pointers for validity (C/C++)
This cannot be done.
The next idea I came up with was to somehow use the sizeof() function to find a pattern with square matrices, but using sizeof() on a pointer will always yield the same value.
I start off by creating a dynamically allocated array to be of size nxn:
int **array = new int*[n]
for(int i = 0; i < n; i++)
array[i] = new int[n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
array[i][j] = 0;
}
}
Now I have a populated square matrix of size nxn. Let's say I'm implementing a function to print a square 2D array, but a user has inadvertently created and passed a 2D array of size mxn into my function (accomplished by the code above, except there are more row pointers than elements that comprise the columns, or vice versa), and we're also not sure whether the user has passed a value of n corresponding to n rows or n columns:
bool(int **arr, int n){
for(int rows = 0; rows < n; rows++)
for(int cols = 0; cols < n; cols++)
cout << *(*(arr + rows) + cols) << " ";
// Is our next column value encroaching on unallocated memory?
}
cout << endl;
// Is our next row value out of bounds?
}
}
Is there any way to inform this user (before exiting with a segmentation fault), that this function is for printing square 2D arrays only?
Edit: corrected 3rd line from
array[i] = new int[i]
to
array[i] = new int[n]
There is NO way to find out information about an allocation. The ONLY way you can do that, is to store the information about the matrix dimensions somewhere. Pointers are just pointers. Nothing more, nothing less. If you need something more than a pointer, you'll need to define a type that encapsulates all of that information.
class Matrix2D
{
public:
Matrix2D(int N, int M)
: m_N(N), m_M(M), m_data(new int[N*M]) {}
int N() const { return this->m_N; }
int M() const { return this->m_M; }
int* operator[] (int index) const
{ return m_data + m_M * index; }
private:
int m_N;
int m_M;
int* m_data;
};

C++ passing array by value causing segment fault

Hey everyone I am relearning C++ by doing some hacker rank challenges and am getting a segment fault error. The program should take in the dimensions for the matrix and compute both diagonals, then add them together. I am pretty sure the error is in how the 2d array is passed to the computeMainDiagonal and computeSecondaryDiagonal functions. Thanks for the help !
int ComputeMatrixMainDiagonal(int matrixDimensions, int* matrix){
int rowIndent = 0;
int diagonalValue;
for(int i = 0;i < matrixDimensions;i++){
diagonalValue =+ (&matrix)[i][rowIndent];
rowIndent++;
}
return diagonalValue;
}
int ComputeMatrixSecondaryDiagonal(int matrixDimensions, int* matrix){
int rowIndent = matrixDimensions;
int diagonalValue;
for(int i = matrixDimensions;i > 0;i--){
diagonalValue =+ (&matrix)[i][rowIndent];
rowIndent--;
}
return diagonalValue;
}
int main() {
int matrixDimension;
int differenceAcrossSumsOfDiagonal;
int matrixMainDiagonal;
int matrixSecondaryDiagonal;
int * matrixPointer;
cin >> matrixDimension; //get matrix dimensions
int matrix[matrixDimension][matrixDimension]; //declare new matrix
for(int index = 0; index < matrixDimension;index++ ){ //populate matrix
for(int i = 0; i < matrixDimension;i++){
cin >> matrix[index][i];
}
}
matrixMainDiagonal = ComputeMatrixMainDiagonal(matrixDimension,&matrix[matrixDimension][matrixDimension]);
matrixSecondaryDiagonal = ComputeMatrixSecondaryDiagonal(matrixDimension,&matrix[matrixDimension][matrixDimension]);
differenceAcrossSumsOfDiagonal = (matrixMainDiagonal + matrixSecondaryDiagonal);
cout << differenceAcrossSumsOfDiagonal;
return 0;
}
Your segmentation fault likely occurs because &matrix[matrixDimension][matrixDimension] does not mean what you think it means. Your question title suggests that you think this is a way to pass the array by value (though why you would want to do so escapes me), but pass-by-value vs. pass-by-reference is a matter of how the function is declared, not of how it is called.
The expression &matrix[matrixDimension][matrixDimension] would be the address of the matrixDimensionth element of the matrixDimensionth row of the matrix. This is outside the bounds of the matrix, as the maximum index for an array is one less than the array dimension. Even if you wrote &matrix[matrixDimension - 1][matrixDimension - 1], however, it would not be what you want. You want the address of the first element of the array, which is &matrix[0][0] or simply matrix, though these are inequivalent on account of having different type (corresponding to different senses of what the elements of matrix are).

Extract rows/columns from ** matrices in C/C++

I have a square matrix double **A
I know how to iterate through this matrix:
for (int i = 0; i < MATRIX_SIZE; i++) {
for (int j = 0; j < MATRIX_SIZE; j ++) {
int val = A[i][j];
printf("val: %d\n", val);
}
}
However, I'm wondering how I can assign an entire row or column to a variable given I have this ** matrix (The ** pointer to pointer nonsense is still a little confusing. I believe its saying a list of list of doubles).
To add a little more background, I'm trying to extract rows and columns so I can perform a cuda matrix multiplication. I see a lot of documentation online that uses one-dimensional vectors to represent matrices (i.e. double* A) However, I am getting confused with the **
A two-dimensional array of doubles (double **) can be looked at as a one-dimensional array of one-dimensional arrays of doubles.
double **arr; // properly initialized
for(int rowNumber = 0; rowNumber < MATRIX_SIZE; ++rowNumber)
{
double *row = arr[rowNumber];
// do something with this row
for(int colNumber = 0; colNumber < MATRIX_SIZE; ++colNumber)
{
double value = row[colNumber];
// do something with value
}
}
In the above example, row is a pointer to a contiguous row of values from the initial array. This works because a two dimensional array is usually allocated like this:
double **arr = new double*[ROW_COUNT];
for(int rowNumber = 0; rowNumber < ROW_COUNT; ++rowNumber)
{
arr[rowNumber] = new double[COL_COUNT];
}
Getting a pointer to a column in the matrix (like we did with row above) is not possible because the values in a column are not contiguous, only the values in each row are contiguous.
In C++, you can use std::array
std::array< std::array<int, MATRIX_SIZE>, MATRIX_SIZE> A;
std::array<int, MATRIX_SIZE> ith_row = A[i];
std::array<int, MATRIX_SIZE> &ith_row_ref = A[i];
A[i][j] is a type of int, but A[i] is a int pointer, so if you want get a row to a variable, you can do this:
for (int i = 0; i < MATRIX_SIZE; i ++) {
int* val = A[i];
for (int j = 0; j < MATRIX_SIZE; j ++) {
printf("%d\n", val[j]);
}
}
but you can't get a column to a variable.
You can assign rows to variables easily but you can't assign columns because of the way that memory is laid out.
You can think of double pointers like this.
The first pointer points to the item to give you the row.
I'm going to make a 3w 4c matrix to show you an example
Theoretical (How you should think about it in your head)
Your first double pointer
p
|
V 0 1 2 <-indexes
0 [p1]->[1,2,3]
1 [p2]->[0,2,3]
2 [p3]->[1,0,3]
3 [p4]->[1,2,0]
which corresponds to the matrix
1,2,3
0,2,1
1,0,3
1,2,0
So you can thinking about getting the 0 at index (1,0) as
int **p = //some place that holds the matrix;
int *row2 = p[1];
int value = p[0];
The reason why it's not as straightforward as declaring a two dimensional
array is because when get the double pointer, you're not sure of the layout of the memory. The numbers could be stored like this
p1 p3 p2 p4
| | | |
[123103021120...] <- //this is basically RAM or "memory"
and you would have no idea as the programmer.
I hope this cleared some things up!

Passing multidimensional arrays (without initially defining its dimensions) into a function in C++

I have been looking for code on how to create a matrix determinant calculator, and I found code from ( Matrix determinant algorithm C++ ).
I adopted the code to try it, but i realized that i did not know how to pass in a multidimensional array into the function, without defining its dimensions first (i got errors).
So, can you please show me how to pass a multidimensional array into a function without defining its dimensions first (i.e how int a[MAX][MAX] is an argument, what is 'MAX').
I hope my question is clear, thank you for your help.
This is the (edited) code:
-sample input would be a square matrix and its size.
int determinant(int oMat[][], int n){
int sMat[n][n]; //Temporary matrix
int det = 0; //Initializing 'det'.
if(n==1){
det = oMat[0][0]; //Calculating.
return det;
}else if(n==2){
det = oMat[0][0]*oMat[1][1] - oMat[1][0]*oMat[0][1]; //Formula for 2x2.
return det;
}else{
for(int p=0; p<n; p++){ //Selecting 'oMat' row one.
int k=0; //'sMat' rows.
int m=0; //'sMat' columns.
//Creating the temporary matrix 'sMat'.
for(int i=1; i<n; i++){ //for 'oMat' rows.
for(int j=0; j<n; j++){
if(j==p){
continue;
}
sMat[k][m] = oMat[i][j]; m++;
if(m==n-1){
k++; //Go to the next row.
m = 0; //Start at column one (index 0).
}
}
}
det = det + oMat[0][p] * pow(-1,p) * determinant(sMat, n-1);
}
return det;
}
}
You can pass an array by reference and have the function figure out the size of the matrix. To do this use a template as follows
template <int R>
int determ(int (&a)[R][R]) {
//now R is the number of rows
std::cout << R << std::endl;
// rest of code here
}
If you're passing a 2-D array to function determ() as
int a[MAX][MAX];
determ(a, int n);
the function declaration should be:
determ(int a[][MAX], int n) { .. }
In the above declaration number of rows need not be specified as we are not allocating the memory for the array hence can be ignored. Number of columns is required for the dimension of the array.
There is two ways:
1) Declare your function as is:
int determ(int** a, int size, int n) {...} // 'size' aka 'MAX'
2) Use dynamic container such as std::vector:
int determ(const vector<vector<int>>& a, int n) {...}
You have a number of options:
Use a compile time size like MAX, and declare your array parameter in terms of that:
int determinant(int (*oMat)[MAX], int n) {
With that you are passing a pointer to the first element (= row) of your 2D array. The same can be done with the std::array<> template:
int determinant(array<array<int, MAX>, MAX> *oMat, int n) {
However, in both cases MAX must be a compile time constant. You may pass MAX in as a template parameter, allowing different code to work on matrices of different size, but the problem remains that MAX needs to be a compile time constant.
If you want to work with a dynamic size in C++, you have two choices: First you can use a vector of vector
int determinant(vector<vector<int> > *oMat, int n) {
This allows maximum flexibility, however, it does not enforce that the lines have the same size. oMat could be a ragged 2D array. The other way is to use a 1D array and calculate the indexes yourself:
int determinant(int size, int *oMat, int n) {
for(int i = 0; i < size; i++)
for(int j = 0; j < size; j++)
//Access the individual elements with
oMat[size*i + j];
The third approach is to drop back to C, because in contrast to C++, C allows for true dynamic 2D arrays:
int determinant(int size, int (*oMat)[size], int n) {
for(int i = 0; i < size; i++)
for(int j = 0; j < size; j++)
//Access the individual elements with
oMat[i][j];
You would create the array and call the function like this:
int n = /*whatever*/;
int (*matrix)[n] = malloc(n*sizeof(*matrix));
fillMatrix(n, matrix);
determinant(n, matrix, n);
free(matrix); //Don't forget the cleanup.