i have a simple program for operations with matrixies, but i have a problem -> i have for example array[3][3] and i need some way how to get the number of dimensions- in this case 3, here is the code:
#include <stdio.h>
#include <stdlib.h>
int **count()
{
printf("Write number of rows and collumns in format ROWS space COLLUMNS");
int i = 0;
int j = 0;
scanf("%i %i", &i, &j);
int **mat1 = (int**)malloc(i*sizeof(int*));
for (int x = 0; x < j;x++){
mat1[x] = (int*)malloc(j*sizeof(int));
}
for (int x = 0; x < i;x++){
for (int y = 0; y < j;y++){
scanf("%i",&mat1[x][y]);
}
}
printf(Write number of rows and collumns in format ROWS space COLLUMNS");
int i2 = 0,j2 = 0;
scanf("%i %i", &i2, &j2);
int **mat2 = (int**)malloc(i2*sizeof(int*));
for (int x2 = 0; x2 < j2;x2++){
mat2[x2] = (int*)malloc(j2*sizeof(int));
}
for (int x2 = 0; x2 < i2;x2++){
for (int y2 = 0; y2 < j2;y2++){
scanf("%i",&mat2[x2][y2]);
}
}
int i3 = i, j3 = j;
int **mat3 = (int**)malloc(i3*sizeof(int*));
for (int x = 0; x < j3;x++){
mat3[x] = (int*)malloc(j3*sizeof(int));
}
for (int x3 = 0; x3 < i3;x3++){
for (int y3 = 0; y3 < j3;y3++){
mat3[x3][y3] = mat1[x3][y3] + mat2[x3][y3];
}
}
return mat3;
}
int writeMatrix(int **mat, int rows, int collumns)
{
int i = rows, j=collumns;
for (int x = 0; x < i;x++){
for (int y = 0; y < j;y++){
printf("%3i ",mat[x][y]);
}
printf("\n");
}
return 0;
}
int main()
{
int **m1 = count();
writeMatrix(m1,x,x);//HERE I NEED TO KNOW NUMBER OF ROWS AND COLLUMNS
free(m1);
}
Here is the code which worked for me in a case of normal array[][] but not in this case -
int y = (sizeof(m1)/sizeof(m1[0][0])) / (sizeof(m1)/sizeof(m1[0]));
You can't have a multidimensional array if you don't knwo statically the size of the first dimension, you'll need a jagged array (an array of arrays), as you did it.
And then you can still get the number of allocated rows and columns. Change the count prototype to:
int** count(int& rows, int& columns)
and in it do these assignments (after you've read the values of i and j):
rows = i;
columns = j;
And call count from main like this:
int rows;
int columns;
int** m1 = count(rows, columns);
Then you can call writeMatrix:
writeMatrix(m1, rows, columns);
BTW, unless you're doing this for educational purposes, you should use std::vector<std::vector<int>> (or some similar array class), not int**.
Related
So I got a function which creates me 2D array and fill it with test data.
Now I need to assign the pointer to an array
//Fill matrix with test data
int *testArrData(int m, int n){
int arr[n][m];
int* ptr;
ptr = &arr[0][0];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
*((ptr+i*n)+j) = rand()%10;
}
}
return (int *) arr;
}
int arr[m][n];
//Algorithm - transpose
for (int i = 0; i < m; i++){
for (int j = 0; j < n; j++){
arrT[j][i] = arr[i][j];
}
}
Is there any way of doing this?
There are at least four problems with the function.
//Fill matrix with test data
int *testArrData(int m, int n){
int arr[n][m];
int* ptr;
ptr = &arr[0][0];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
*((ptr+i*n)+j) = rand()%10;
}
}
return (int *) arr;
}
First of all you declared a variable length array
int arr[n][m];
Variable length arrays are not a standard C++ feature.
The second problem is that these for loops
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
*((ptr+i*n)+j) = rand()%10;
}
}
are incorrect. It seems you mean
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
*((ptr+i*m)+j) = rand()%10;
}
}
You are returning a pointer to a local array with automatic storage duration that will not be alive after exiting the function. So the returned pointer will be invalid.
And arrays do not have the assignment operator.
Instead use the vector std::vector<std::vector<int>>. For example
std::vector<std::vector<int>> testArrData(int m, int n){
std::vector<std::vector<int>> v( n, std::vector<int>( m ) );
for ( auto &row : v )
{
for ( auto &item : row )
{
item = rand() % 10;
}
}
return v;
}
This is how I would accomplish this. I agree with int ** because it is easy to understand if you dont know how to use vectors. Also, the rand() can cause trouble if you are using the result to index an array. Make sure to use abs(rand() % number) if you don't want negative numbers.
I've updated the answer due to some vital missing code.
// This method creates the overhead / an array of pointers for each matrix
typedef int* matrix_cells;
int **create_row_col_matrix(int num_rows, int num_cols, bool init_rnd)
{
num_rows = min(max(num_rows, 1), 1000); // ensure num_rows = 1 - 1000
num_cols = min(max(num_cols, 1), 1000); // ensure num_cols = 1 - 1000
int *matrix_total = new int[num_rows*num_cols];
// overhead: create an array that points to each row
int **martix_row_col = new matrix_cells[num_rows];
// initialize the row pointers
for (int a = 0; a < num_rows; ++a)
{
// initialize the array of row pointers
matrix_row_col[a] = &matrix_total[num_cols*a];
}
// assign the test data
if (init_rnd)
{
for (int run_y = 0; run_y < num_rows; ++run_y)
{
for (int run_x = 0; run_x < num_cols; ++run_x)
{
matrix_row_col[run_y][run_x] = abs(rand() % 10);
}
}
}
return matrix_row_col;
}
int src_x = 7, dst_x = 11;
int src_y = 11, dst_y = 7;
int **arr_src = create_row_col_matrix(src_y, src_x, true);
int **arr_dst = create_row_col_matrix(dst_y, dst_x, false);
for (int a = 0; a < dst_y; ++a)
{
for (int b = 0; b < dst_x; ++b)
{
arr_dst[a][b] = arr_src[b][a];
}
}
delete matrix_src[0]; // int *matrix_total = new int[src_y*src_x]
delete matrix_src; // int **matrix_row_col = new matrix_cell[src_y]
delete matrix_dst[0]; // int *matrix_total = new int[dst_y*dst_x]
delete matrix_dst; // int **matrix_row_col = new matrix_cell[dst_y]
// the overhead is matrix_src and matrix_dst which are arrays of row pointers
// the row pointers makes it convenient to address the cells as [rown][coln]
I'm trying to create random coordinates but to make sure they aren't used I decided to create a 2D array initialized at 0 to show each space is empty.
I'm using this function for the randomness:
int randomNoGenerator(int limit)
{
std::random_device r;
std::default_random_engine e1(r());
std::uniform_int_distribution<int> uniform_dist(1, limit);
int rand = uniform_dist(e1);
return rand;
}
And my main:
int main(void)
{
int numRows = 5;
int numCols = 7;
int **occupiedSpace;
occupiedSpace = (int **)calloc(numRows, sizeof(int *));
for (int i = 0; i < numRows; i++)
occupiedSpace[i] = (int *)calloc(numCols, sizeof(int));
for (int i = 0; i < 5; i++)
{
int x;
int y;
int match = 1;
x = randomNoGenerator(numCols);
y = randomNoGenerator(numRows);
//This is where the crash is happening?
occupiedSpace[x][y] = 1;
}
return 0;
}
My ultimate goal was to have something like where if it's empty it just replaces it with a 1. Otherwise it keeps generating X, Y if it's already occupied.
while (match)
{
x = randomNoGenerator(numCols);
y = randomNoGenerator(numRows);
if(occupiedSpace[x][y] = 0)
{
occupiedSpace[x][y] = 1;
match = 0;
}
}
You're generating your x and y coordinate the wrong way round. The outer index is the row, the inner index is the column, so you should do:
x = randomNoGenerator(numRows); // instead of numCols
y = randomNoGenerator(numCols); // instead of numRows
Then, you set up your random generator with wrong numbers. It should be uniform_dist(0, limit - 1) instead of uniform_dist(1, limit) since row and column indexing starts at 0.
You can also use std:array instead calloc :
std::array<std::array<int,5>,7> occupiedSpace;
for ( int i = 0; i < numCols; i++)
{ for (int j = 0; j < numRows; j++) occupiedSpace[i][j] = 0 ;
}
I have a University assignment whereby I have a 1D array, containing 262144 values. I've created a matrix class which places these values into an object with the datasource being the double* list of 262144 values.
I need to be able to obtain a sub-matrix (which I'm able to do) from ANOTHER set of 262144 values (which I've also placed into a matrix object).
However, I'm having serious trouble and I've been trying so hard for the last 3 days to try and replace original matrix values from a sub-matrix. I've tried passing by reference, creating Matrix*'s. I've tried everything we've been taught and even researched a few more methods, all of which I haven't understood. I'll throw my code in here to see if anyone can explain a method to me which will be able to do this.
Matrix::Matrix()
{
"Matrix::Matrix() is invoked";
}
Matrix::Matrix(const Matrix& m)
{
"Matrix::Matrix(const Matrix&) is invoked";
_M = m._M;
_N = m._N;
_data = new double[_M*_N];
for (int i = 0; i < _M*_N; i++)
{
_data[i] = m._data[i];
}
}
Matrix::Matrix(int sizeR, int sizeC, double *input_data)
{
"Matrix::Matrix(int sizeR, int sizeC, double *input_data is invoked";
_M = sizeR;
_N = sizeC;
_data = new double[_M*_N];
for (int i = 0; i < _M*_N; i++)
{
_data[i] = input_data[i];
}
}
Matrix Matrix::get_Block(int start_row, int end_row, int start_coloumn, int end_coloumn)
{
int rows = (end_row - start_row);
int columns = (end_coloumn - start_coloumn);
int ctr = 0;
double *temp_Data = new double[rows*columns];
for (int x = start_row; x < (rows + start_row); x++)
{
for (int y = start_coloumn; y < (columns + start_coloumn); y++)
{
temp_Data[ctr] = get(x, y);
ctr++;
}
}
Matrix block(rows, columns, temp_Data);
delete[] temp_Data;
return block;
}
Matrix Matrix::operator+(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] + other._data[x];
}
return temp;
}
Matrix Matrix::operator*(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] * other._data[x];
}
return temp;
}
Matrix Matrix::operator-(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] - other._data[x];
}
return temp;
}
void Matrix::replace_Block(Matrix& noisy, Matrix& shuffled,int k, int j, int i)
{
int val_to_replace = 0;
for (int i = 0; i < 3 * 3; i++)
{
val_to_replace = shuffled.get(i, j);
noisy.set(i, j, val_to_replace);
}
}
void Matrix::set_Block(Matrix block, Matrix& Noisy, int start_row, int end_row)
{
int ctr = 0;
int ctr2 = 0;
int ctr3 = 0;
for (int i = 0; i < 3; i++)
{
Noisy._data[(start_row*_M)+i+4] = block.get(i, ctr);
ctr++;
}
for (int j = 0; j < 3; j++)
{
Noisy._data[((start_row + 1)*_M) + j + 3] = block.get(j, ctr2);
ctr2++;
}
for (int j = 0; j < 3; j++)
{
Noisy._data[((start_row + 1)*_M) + j + 2] = block.get(j, ctr3);
ctr3++;
}
}
double Matrix::get_Sum(Matrix m)
{
double total = 0;
short row = m.get_M();
short column = m.get_N();
for (int j = 0; j < row; j++)
{
for (int i = 0; i < column; i++)
{
total += m.get(j,i);
}
}
return total;
}
double Matrix::get_Sum(Matrix* m)
{
double total = 0;
short row = m->get_M();
short column = m->get_N();
for (int j = 0; j < row; j++)
{
for (int i = 0; i < column; i++)
{
total += m->get(i, j);
}
}
return total;
}
double Matrix::get(int i, int j)
{
return _data[(i * _M) + j];
}
void Matrix::write_Block(int i, int j)
{
for (int ctr = 0; ctr < i; ctr++)
{
for (int ctr2 = 0; ctr2 < j; ctr2++)
{
std::cout << " " << this->get(ctr,ctr2);
}
std::cout << std::endl;
}
}
void Matrix::set(int i, int j, double val)
{
this->_data[(i*_M) + j] = val;
}
void Matrix::set_N(int N)
{
_N = N;
}
void Matrix::set_M(int M)
{
_M = M;
}
int Matrix::get_N()
{
return _N;
}
int Matrix::get_M()
{
return _M;
}
Matrix::~Matrix()
{
"Matrix::~Matrix() is invoked";
delete[] _data;
}
If it would be helpful to see main() I can supply that too, however all it really contains is the creation of the matrix objects using overloaded constructors.
explanation
Answer is only 4 years late . . .
Anyway. Maybe it will help somebody else. The secret is to use a std::valarray. With that it is utmost simple to work on a matrix. And, many many functions are available.
All the functions that you want to implement are already available.
And you sub-matrix coy can be a one liner . . .
Please see example code:
#include <iostream>
#include <algorithm>
#include <numeric>
#include <valarray>
#include <iomanip>
constexpr size_t NRows = 6;
constexpr size_t NCols = 8;
constexpr size_t SubNRows = 2;
constexpr size_t SubNCols = 3;
void debugPrint(std::valarray<int> &v, size_t nrows = NRows, size_t ncols = NCols)
{
for (int r = 0; r < nrows; ++r) {
for (int c = 0; c < ncols; ++c)
std::cout << std::setw(3) << v[r*ncols+c] << ' ';
std::cout << '\n';
}
std::cout << '\n';
}
int main()
{
std::valarray<int> v1(NRows * NCols); // Define array with given size
std::iota(std::begin(v1),std::end(v1),0); // Fill the array with consecutive nunbers
debugPrint (v1); // Print the result
std::cout << "\nSum = " << v1.sum() << "\n\n"; // Print the sum of all values in matrix
std::valarray<int> v2(v1); // Create a 2nd matrix as a copy to the first
v2 += 100; // Add 100 to each value in the matrix
debugPrint(v2);
std::valarray<int> v3(NCols); // Get one column
v3 = v1[std::slice(2,NRows,NCols)];
debugPrint(v3,NRows,1);
std::valarray<int> subV2(SubNRows*SubNCols); // So, now the sub array
subV2 = v2[std::gslice(12,{SubNRows, SubNCols},{NCols,1})]; // Slice it out
debugPrint(subV2, SubNRows, SubNCols);
v1[std::gslice(25,{SubNRows, SubNCols},{NCols,1})] = subV2; // And copy to the first array
debugPrint (v1);
return 0;
}
I have to solve a problem with two 2D arrays and calculated things like odds number, sum of even number and addition of the two array. I get multiple errors. Can someone help me?
It is how I define my arrays, and it also says display_odd is not a valid void function. Why?
#define DIM 50
#include <stdio.h>
#include <conio.h>
void display_odd(int[][DIM]);
int display_even_sum(int[][DIM], int[][DIM]);
int display_matrix_sum(int[DIM][DIM], int[DIM][DIM]);
void main(){
int x1, x2, y1, y2, x, y, arr1[DIM][DIM], arr2[DIM][DIM], arr[DIM][DIM];
printf("How large do you want the first matrix to be? ('x y') \n");
scanf("%d %d", &x1, &y1);
for (int i = 0; i < x1; i++){
for (int j = 0; j < y1; j++){
printf("A[%d][%d]= ", i + 1, j + 1);
scanf("%d", &arr1[i][j]);
}
}
printf("How large do you want the second matrix to be? ('x y') \n");
scanf("%d %d", &x2, &y2);
for (int i = 0; i < x2; i++){
for (int j = 0; j < y2; j++){
printf("B[%d][%d]= ", i + 1, j + 1);
scanf("%d", &arr2[i][j]);
}
}
if (x1 > x2)
x = x1;
else
x = x2;
if (y1 > y2)
y = y1;
else
y = y2;
//printf("\nThe odd numbers in matrix A are : \n");
//void display_odd(arr1[DIM][DIM]);
//printf("\nThe odd numbers in matrix B are : \n");
//void display_odd(arr2[DIM][DIM]);
printf("\nThe sum of all even elements is : ");
printf("\nThe sum of the initial matrixes is : \n");
arr = display_matrix_sum(arr1[DIM][DIM] ,arr2[DIM][DIM]);
for (int i = 0; i < DIM; i++){
printf("\n");
for (int j = 0; j < DIM; j++)
printf(" %d", arr[i][j]);
}
_getch(); //Wait for it
}
void display_odd(int arr[][DIM]){
for (int i = 0; i < DIM; i++)
for (int j = 0; j < DIM; j++)
if (arr[i][j] % 2 == 1)
printf("[%d][%d]", i, j);
}
int display_even_sum(int arr1[DIM][DIM],int arr2[DIM][DIM]){
int s = 0;
for (int i = 0; i < DIM; i++)
for (int j = 0; j < DIM; j++)
if (arr1[i][j] % 2 == 0)
s += arr1[i][j];
for (int i = 0; i < DIM; i++)
for (int j = 0; j < DIM; j++)
if (arr2[i][j] % 2 == 0)
s += arr2[i][j];
return(s);
}
int display_matrix_sum(int arr1[][DIM],int arr2[][DIM]){
int arr[DIM][DIM];
for (int i = 0; i < DIM; i++)
for (int j = 0; j < DIM; j++)
arr[i][j] = arr1[i][j] + arr2[i][j];
return(arr[DIM][DIM]);
}
arr = display_matrix_sum(arr1[DIM][DIM] ,arr2[DIM][DIM]);
A C function cannot return an array. You can pass the destination array as an additional argument.
void display_matrix_sum();
…
display_matrix_sum(arr1, arr2, arr);
…
void display_matrix_sum(int arr1[][DIM], int arr2[][DIM], int arr[][DIM])
{
…
// remove this: return(arr[DIM][DIM]);
}
When you declare an array, or when you reference a specific member in an array, you use the square brackets:
int array[2][3];
array[1][0] = 6;
int x = array[1][0]; // x is now 6
when you pass an array as an argument, you simply use the name of the array;
someFunction(array); // passes the array
anotherFunction(array[1][0]); // passes 6;
return array; // returns the array;
return array[1][0]; // returns 6;
It may also help to give the parameters and local variables in your functions different names than the global arrays you define, and to define those global arrays as local arrays in your main function.
The biggest problem is that you don't seem to understand that arrays are just pointers. you can't just pass them around unless they are heap allocated. Each function should be rewritten to show this. For example display_matrix_sum's signature should look like
int** display_matrix_sum(int** A1, int** A2, int rows, int cols);
and should be called by:
int cols = 4; // or whatever
int rows = 4; // or whatever
int** arr1 = new int*[rows]; // arr1 is now any an array of int arrays
int** arr2 = new int*[rows]; // arrays work by pointing to the first element
for(int i = 0; i < rows; i++)
{
arr1[i] = new int[cols]; // each element in arr1 becomes an int array
arr2[i] = new int[cols];
}
/* fill in the values of the arrays */
int** out = display_matrix_sum( arr1, arr2, rows, cols, out);
// output now contains the result of the function
/* when you are done with arr1 and arr2 and out*/
for(int i = 0; i < rows; i++)
{
delete[] arr1[i];
delete[] arr2[i];
delete[] out[i];
}
delete[] arr1;
delete[] arr2;
delete[] out;
I have a problem which includes pointers and two-dimensional arrays.
I've got a struct, which looks something like this:
typedef struct {
int row;
int col;
int **a;
} TEST;
Now I want to use an object of that type for other functions. But i'm having problems passing an two-dimensional array to an object of the type.
For example i tried this:
int main(int argc, char * argv[]){
//Just to fill an array with some integers
int rows = 3;
int cols = 3;
int a[rows][cols];
srand(time(NULL));
for (int x = 0; x < rows; x++){
for (int y = 0; y < cols; y++){
a[x][y] = rand() % 10 + 1;
}
}
TEST * t = (TEST *) calloc(1,sizeof(TEST));
t->row = rows;
t->col = cols;
t->a = a;
return 0;
}
How can I do this properly?
I'm thankful for any help.
If you need to allocate a TEST object dynamically then you can do this:
int main(int argc, char * argv[])
{
//Just to fill an array with some integers
int rows = 3;
int cols = 3;
TEST* t = new TEST;
t->row = rows;
t->col = cols;
t->a = new int*[rows];
for(int i = 0; i < rows; i++)
t->a[i] = new int[cols];
srand(time(NULL));
for (int x = 0; x < rows; x++){
for (int y = 0; y < cols; y++){
t->a[x][y] = rand() % 10 + 1;
}
}
return 0;
}