Dynamic array size to calculate the determinant of a matrix - c++

Basically, I have written a program to calculate the determinant of a matrix.
However, this feels like quite static yet (i.e. the dimension is passed as an argument). Is there any way to make it more dynamic (without vectors) with something like pointers?
#include <bits/stdc++.h>
using namespace std;
#define N 4
void getCofactor(int mat[N][N], int temp[N][N], int p, int q, int n)
{
int i = 0, j = 0;
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
{
if (row != p && col != q)
{
temp[i][j++] = mat[row][col];
if (j == n - 1)
{
j = 0;
i++;
}
}
}
}
}
int determinantOfMatrix(int mat[N][N], int n)
{
int D = 0;
if (n == 1)
return mat[0][0];
int temp[N][N];
int sign = 1;
for (int f = 0; f < n; f++)
{
getCofactor(mat, temp, 0, f, n);
D += sign * mat[0][f] * determinantOfMatrix(temp, n - 1);
sign = -sign;
}
return D;
}

There is no way to pass a pointer to an array of dynamic size. And the inner dimensions of an array cannot be dynamic anyway.
What you can do instead is use a one dimensional dynamic array, pass pointer to element of that array as usual, and store the rows one after the other, and calculate the index based on the row size passed as an array. This results in the same layout as an array of arrays would have, but the "virtual" dimensions can be dynamic.

Related

unknown row but constant column

i need to make a function that take an int matrix of known columns but varies rows which will be used later in sorting and checking if the matrix is row-magic/column magic I know how to do the sorting, and everything else but my issue is setting the end of my loops because they could be either 4/5/6
Note: I am a student so they don't expect me to use sizeof
int sort(int A[? ][5]) {
int i, j, temp;
for (i = 0; i < ? ; i++) { // the number of rows
int min = A[i][0];
for (j = 0; j < 5; j++) { //the number of columns
temp = A[i][j];
if (min > temp) {
int swap = min;
min = temp;
temp = swap;
}
}
int swap = A[i + 1][0];
if (swap < A[i][5]) {
int swap1 = A[i][5];
swap = A[i][5];
swap1 = A[i + 1][0;]
}
}
}
The array A decays to a pointer when it's passed to the function and a pointer doesn't contain any information about the size. You have to pass the number of rows as additional function argument:
int sort(int A[][5], int rows)

stack around a variabe corrupted plus programs stops after inputting certain value c++

My program is meant to generate a dynamic 2d array then sort then transpose the array(swtitching columns and rows) My problem is when i input a certain value(7) for the rows and columns a stack around the variable indices becomes corrupted furthermore my code starts generating numbers that make no since i think its because it some is out of bounds please help me im relalitvely new to c++
//
// C++ program template
//
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
void init_array(int ** array_in, int rows, int cols, int list[]);
void print_array(int ** array_in, int rows, int cols);
void selection_sort(int array_in[], int elements);
int ** transpose(int ** array_in, int ** array_out, int rows, int cols);
const unsigned int SIZE = 4000;
int count1 = 0;
int main(void)
{
int rows = 0, cols = 0, j = 0, k = 0;
int**numbers = nullptr;
int**arraytranspose = nullptr;
cout << "Enter rows and columns" << endl;
cin >> rows >> cols;
int length = rows * cols;
int list[4000] = { 0 };
numbers = new int*[rows];
arraytranspose = new int*[rows];
for (k = 0; k < cols; k++)
{
numbers[k] = new int[cols];
arraytranspose[k] = new int[cols];
}
// initialize the array with unique values
init_array(numbers, rows, cols, list);
print_array(numbers, rows, cols);
selection_sort(list, count1);
int count3 = 0;
for (int count2 = 0; count2 < 3999; count2++) {
for (int i = 0; i < rows; i++)
{
for (int c = 0; c < cols; c++)
{
if (list[count2] != 0)
{
numbers[i][c] = list[count2];
}
count2++;
}
}
}
print_array(numbers, rows, cols);
cout << endl << endl;
print_array(transpose(numbers,arraytranspose,rows,cols), rows, cols);
system("pause");
return 0;
}
void selection_sort(int array_in[], int elements)
{
int index = 0, smallest = 0, hold = 0, count = 0, location = 0;
for (index = 0; index < SIZE - 1; index++) // Loop to control number of passes
{
smallest = index;
// Find the index of the smallest element
for (location = index + 1; location < SIZE; location++)
{
if (array_in[location] < array_in[smallest])
{
smallest = location;
} // End If
} // End Inner for loop
hold = array_in[smallest];
array_in[smallest] = array_in[index];
array_in[index] = hold;
count++; // Count number of swaps
}
cout << "There were " << count << " element exchanges during the sort. " << endl << endl;
return;
}
void init_array(int ** array_in, int rows, int cols, int list[])
{
int j = 0, k = 0, value = 0;
int indices[4000] = { 0 };
count1 = 0;
while (j < rows)
{
k = 0;
while (k < cols)
{
value = rand() & 4000;
if (indices[value] != 1)
{
array_in[j][k] = value;
indices[value] = 1;
list[count1] = array_in[j][k];
k++;
count1++;
}
}// end while
j++;
}
return;
}
void print_array(int ** array_in, int rows, int cols)
{
int j = 0, k = 0;
for (j = 0; j < rows; j++) {
for (k = 0; k < cols; k++) {
cout << setw(5) << array_in[j][k];
}
cout << endl;
}
return;
}
int** transpose(int ** array_in, int ** array_out,int rows, int cols)
{
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
array_out[r][c] = array_in[c][r];
}
}
return array_out;
}
numbers = new int*[rows];
arraytranspose = new int*[rows];
This allocates memory for a pair of arrays, an array of rows values.
Immediately afterwards:
for (k = 0; k < cols; k++)
{
numbers[k] = new int[cols];
arraytranspose[k] = new int[cols];
}
And this set the first cols values in these arrays, but they are rows values in size. So, if rows is less than cols, this results in memory corruption and undefined behavior, as the shown code writes to values of the array that do not exist.
This is the first obvious flaw in the shown code that's obvious from a cursory inspection, but it's likely there are other similar flaws as well; they generally result from unsafe programming practices like the ones shown here, like manual memory allocation, and lack of bounds checking. Modern C++ code offers plenty of safe programming practices, like using std::vectors to manage dynamically-sized arrays, and iterators.
Simply fixing this specific bug will be merely a bandaid, even if it turns out to be the only bug fix. Your real, long-term fix is to rewrite this entire code, and start using modern C++ containers, containers, and algorithms, which, when used correctly, will eliminate most opportunities for this entire class of bugs.

C++ 2d static array and memory allocation

I think, I have just made a mistake: I was allocating a static 2D array and accessing it as 1 dimension.
Could you tell me how bad it is - method geta?
The code below works fine on my Windows, and Linux: actual is always eqauls to expected and stride is always equals to N.
#include "stdafx.h"
#define N 2000
int a[N][N];
int geta(int i, int j) {
return *(a[0] + i * N + j);
}
int main()
{
printf("Hello\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
a[i][j] = i + j;
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int const expected = a[i][j];
int const actual = geta(i, j);
if (actual != expected) {
printf("wrong data at [%d,%d] expected=%d actual=%d", i, j, expected, actual);
}
}
}
for (int i = 1; i < N; i++) {
int stride = a[N] - a[N - 1];
if (stride != N) {
printf("wrong: i=%d c=%d N=%d", i, stride, N);
}
}
return 0;
}
Could you tell me how bad it is - method geta?
Bad. But correct. C++ guarantees memory for a to be contiguous and the memory layout to be row major, so your code returns in a correct manner the expected element. Let's see how:
The type of a[0] is int[2000] 1) . But as soon as you do arithmetic on it it decays, i.e. int*. So +i*N moves the pointer to the (beginning of the) line i and +j moves the pointer to the column j.
1) actually it's int(&)[2000] but not that relevant here

passing 2d float array to a function in C++ [duplicate]

I have a 2-dimensional array and I am passing it into a function to carry out certain operations. I'd like to know the correct way of doing it...
#define numRows 3
#define numCols 7
#define TotalNum (numRows*numCols)
int arr[numRows][numCols] = {{0,1,2,3,4,5,6}, {7,8,9,10,11,12,13},{14,15,16,17,18,19,20}};
void display(int **p)
{
printf("\n");
for (int i = 0; i< numRows;i++)
{
for ( int j = 0;j< numCols;j++)
{
printf("%i\t",p[i][j]);
}
printf("\n");
}
}
int main() {
display(arr);
}
I get an error message:
'display': cannot convert parameter1 from 'int' to 'int*'
Is this the correct way of passing a 2-dimensional array into a function? If not, what is the correct way?
You should declare your function like this:
void display(int p[][numCols])
This C FAQ thoroughly explains why. The gist of it is that arrays decay into pointers once, it doesn't happen recursively. An array of arrays decays into a pointer to an array, not into a pointer to a pointer.
If (like in your case), you know the dimensions of the array at compilation-time, you can write justvoid display(int p[][numCols]).
Some explanation: You probably know that when you pass an array to a function, you actually pass a pointer to the first member. In C language, 2D array is just an array of arrays. Because of that, you should pass the function a pointer to the first sub-array in the 2D array. So, the natural way, is to say int (*p)[numCols] (that means p is a pointer, to an array of numCols ints). In function declaration, you have the "shortcut" p[], that means exactly the same thing like (*p) (But tells the reader, that you pass a pointer to a beginning of array, and not to just an one variable)
There are several, sometimes equivalent ways of doing this. By declaring an array (cf. method_c()), by using a pointer (cf. method_b()) or by using a pointer to an array of an array (cf. method_a()). method_b(), using a single pointer, is slightly more difficult to get right since it is not easy to use standard array indexing and hence, we use pointer arithmetic. method_a() and method_c() are basically equivalent since arrays decay non-recursively to pointers during compilation. Here is a little program illustrating all three methods. We first initialize a 2x4-array arr in a simple for loop and print it. It will look like this:
arr:
0 1 2 3
0 1 2 3
Afterwards we call all three methods. method_a() adds 1, method_b() adds 2 and method_c() adds 3 to all elements. After each call we print out the array arr again. If a function worked correctly you will easily see it on the output. Size is arbitrary and can be regulated via the two macros ROW and COL. One last note, method_c() relies on variable-length array present since C99.
#include <stdio.h>
#include <stdlib.h>
#define ROW 2
#define COL 4
void method_a(int m, int n, int (*ptr_arr)[n]);
void method_b(int m, int n, int *ptr_arr);
void method_c(int m, int n, int arr[][n]);
int main(int argc, char *argv[]) {
int arr[ROW][COL];
int i;
int j;
for(i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
arr[i][j] = j;
}
}
printf("Original array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
method_a(ROW, COL, arr);
printf("method_a() array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
printf("method_b() array:\n");
method_b(ROW, COL, (int *)arr);
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
method_c(ROW, COL, arr);
printf("method_c() array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
return EXIT_SUCCESS;
}
void method_a(int m, int n, int (*ptr_arr)[n])
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
ptr_arr[i][j] = j + 1;
}
}
}
void method_b(int m, int n, int *ptr_arr)
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
/* We need to use pointer arithmetic when indexing. */
*((ptr_arr + i * n) + j) = j + 2;
}
}
/* The whole function could have also been defined a bit different by taking
* the i index out of the pointer arithmetic. n alone will then provide our
* correct offset to the right. This may be a bit easier to understand. Our
* for-loop would then look like this:
* for (i = 0; i < m; i++)
* {
* for (j = 0; j < n; j++)
* {
* *((ptr_arr + n) + j) = j + 2;
* }
* ptr_arr++;
* }*/
}
void method_c(int m, int n, int arr[][n])
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
arr[i][j] = j + 3;
}
}
}
You are doing in wrong way. You can pass 2-d array with the help of pointer to an array, or simply pass an array or through Single pointer.
#define numRows 3
#define numCols 7
void display(int (*p)[numcols],int numRows,int numCols)//First method//
void display(int *p,int numRows,int numCols) //Second Method//
void display(int numRows,int numCols,int p[][numCols]) //Third Method
{
printf("\n");
for (int i = 0; i < numRows;i++)
{
for ( int j = 0; j < numCols;j++)
{
printf("%i\t",p[i][j]);
}
printf("\n");
}
}
int main() {
display(arr,numRows,numCols);
}
Declare it simply
void display(int (*p)[numCols][numRows]);
This way your p pointer conveys all necessary informations and you can extract all the dimensions from it without repeating numCols and numRows over and over.
void display(int (*p)[numCols][numRows])
{
size_t i, j;
printf("sizeof array=%zu\n", sizeof *p);
printf("sizeof array[]=%zu\n", sizeof **p);
printf("sizeof array[][]=%zu\n", sizeof ***p);
size_t dim_y = sizeof *p / sizeof **p;
printf("dim_y = %zu\n", dim_y);
size_t dim_x = sizeof **p / sizeof ***p;
printf("dim_x = %zu\n", dim_x);
for(i=0; i<dim_y; i++) {
puts("");
for(j=0; j<dim_x; j++)
printf(" %6d", (*p)[i][j]);
}
}
This is particularly interesting if you use typedefs (which I don't like btw)
typedef int matrix[5][6];
In that case the dimensions are not visible in the signature of the function but the function will still have the correct values for the dimensions.
You can change the signature of display method as follows:
void display(int (*p)[numCols])
Here, p is a pointer to the row of a 2D array. The pointer only needs to know the number of columns in the array.
Actually speaking, pointer need to know the size of each row. This is very important for pointer arithmetic. So that when you increment the pointer, the pointer must point to next row.
Note here, p is not a normal integer pointer. It's a integer pointer to the memory size equal to integer_size x columns.
In main you don't need to change anything. display(arr) is just fine.

how to pass 2 dimensional array if both dimensions are unknown at compile time

what is this the correct way to pass 2 dimensional array of unknown size?
reprVectorsTree::reprVectorsTree(float tree[][], int noOfVectors, int dimensions)
how to access the elements of this array later in the function?
How to pass a 2 dimensional array from the calling function?
-----edit----
I want to do with an array as the calling is done from a c code and there is a c to c++ interface
-----edit-----
How to define pass a 2 dimensional array from the calling function?
float tree[15][2] = {{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1}};
reprVectorsTree *r1 = new reprVectorsTree(tree[0][0],8,2);
what is wrong with the above code?
I get a cannot convert parameter 1 from 'float' to 'float **'
Use pointers..
reprVectorsTree(tree, noOfVectors, dimensions);// Calling function.
Function Definition:
reprVectorsTree(float **tree, int noOfVectors, int dimensions){
}
I think it will be helpful to you.
If the size is unknown, you can use a simple float *tree pointer to a 1D array. The syntax for turning to particular elements wouldn't be as of 2D arrays however:
reprVectorsTree::reprVectorsTree(float *tree, int noOfVectors, int dimensions)
{
...
tree[ row_number * dimensions + column_number ] = 100.234;
}
In the calling code you will have something like this:
float d2array[ROWS][COLUMNS];
...
reprVectorsTree(&d2array[0][0], ROWS, COLUMNS);
updated
Consider the following example of different approaches of passing a 2D array:
#include <iostream>
#include <malloc.h>
float test[2][4] =
{
{3.0, 4.0, 5.0, 0},
{6.0, 7.0, 8.0, 0}
};
void print(float *root, int rows, int columns)
{
for (int row = 0; row < rows; ++row)
{
for (int col = 0; col < columns; ++col)
{
std::cout << root[row * columns + col ] << " ";
}
std::cout << std::endl;
}
}
float *test2[2] =
{
&test[0][0],
&test[1][0],
};
void print2(float **root, int rows, int columns)
{
for (int row = 0; row < rows; ++row)
{
for (int col = 0; col < columns; ++col)
{
std::cout << root[row][col] << " ";
}
std::cout << std::endl;
}
}
int main()
{
print(&test[0][0], 2, 4);
//print(test2, 2, 4); // doesn't work
print2(test2, 2, 4);
//print2(&test[0][0], 2, 4); // doesn't work
//print2(&test[0], 2, 4); // doesn't work
float **dynamic_array = (float **)malloc(2 * sizeof(float *));
dynamic_array[0] = (float *)malloc(4 * sizeof(float));
dynamic_array[1] = (float *)malloc(4 * sizeof(float));
for (int row = 0; row < 2; ++row)
{
for (int col = 0; col < 4; ++col)
{
dynamic_array[row][col] = (float)(row * 4 + col);
}
}
print2(dynamic_array, 2, 4);
//print(dynamic_array, 2, 4); // doesn't work
return 0;
}
#include <iostream>
using namespace std;
int
main(void)
{
int layers = 3; // can be calculated in run-time
int elem = 5; // can be calculated in run-time
int* pArray = new int[layers * elem];
/* usage */
for (int i = 0; i < sizeof(pArray) / sizeof(pArray[0]); ++i) // traverse through layers
{
for (int j = 0; j < sizeof(pArray[0])/ sizeof(int); ++j) // traverse through elements in layer
{
// do some stuff
}
}
}
In modern C, starting from C99, it is a simple as that
void foo(size_t n, size_t m, double A[n][m]) {
//
}
and here you go. The only thing that you'd have to have in mind is that the sizes must come before the array in the argument list.
To avoid to allocate such a beast on the stack on the calling side you should just do
double (*A)[m] = malloc(sizeof(double[n][m]));
such a "matrix" can be used as you are used to with something like A[i][j] and a call to foo would just look like
foo(n, m, A);
First idea was to use vectors. But if you are working with a C code, pass it as a reprVectorsTree(float** tree, int noOfVectors, int dimensions).
For your case:
float tree[15][2] = {{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1},{2,1}};
int nRows = 15;
int nCols = 2;
float** arr = new float*[nRows];
for (int i = 0; i < nRows; ++i) {
arr[i] = new float[nCols];
}
for (int i = 0; i < nRows; ++i) {
for (int j = 0; j < nCols; ++j) {
arr[i][j] = tree[i][j];
}
}
reprVectorsTree *r1 = new reprVectorsTree(arr, nRows, nCols);