Is it possible to make a function that works with arrays of undefined length?
For example, I made this code to fill a matrix of 3x3 and I wonder if is there a way to do this but with a matrix of nxn.
void fillMatrix(double mat[][COLS])
{
int i,j;
printf("Enter the %d matrix elements:\n",COLS*ROWS);
for(i=0;i<ROWS;i++)
{
for(j=0;j<COLS;j++)
{
scanf("%lf",&mat[i][j]);
}
}
printf("\n");
}
In this code I defined ROWS=COLS=3.
Yes, if you know the number of columns in the 2D array at the time of passing it to the function. You do not have to define COL beforehand.
void foo(int col, int arr[][col]) {
//Do something
}
You can try this:
void func(void *data, int row, int col)
{
int (*a)[col] = (int(*)[col])data;
//now you can access a[i][j] with i<row and j<col
//data must be an continous array
//replace int with your data type
}
Working code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n = 5;
int (*a)[n];
int b[5][5];
a = (int(*)[n])b;
b[0][0]=0;
b[0][1]=1;
b[2][1]=111;
b[1][2]=666;
b[4][3]=222;
printf("%d\n", a[0][0]);
printf("%d\n", a[0][1]);
printf("%d\n", a[2][1]);
printf("%d\n", a[1][2]);
printf("%d\n", a[4][3]);
return 0;
}
may be you can add a new parameter row to your function fillMatrix(double mat[][COLS]), that is, fillMatrix(double mat[][col], int row)
another way:
double** matrix = (double**) malloc(sizeof(double*)*n);
for(int i = 0; i<n; i++){
matrix[i] = (double*) malloc(sizeof(double)*n);
}
then change the function to: fillMatrix(double** matrix, int n)
Is it possible to make a function that works with arrays of undefined length?
You'll better know the dimension of the array. If it is a function argument, you should in general pass the dimension in some other argument.
Remember that when passed as argument, an array is decayed into a pointer. Look also into some C reference site and later refer to the C11 standard n1570.
In your case, you want to define then have an abstract data type (probably some opaque pointer) for your matrixes. Using flexible array members could be useful. See this answer for details.
yes, you can do it using dinamic memory.
you will something like:
void fillMatrix(double** mat, int rows, int cols) {
int i,j;
printf("Enter the %d matrix elements:\n",rows*cols);
for(i=0;i<rows;i++)
{
for(j=0;j<cols;j++)
{
scanf("%lf",&mat[i][j]);
}
}
printf("\n");
}
where double** mat is a vector of vectors that you will have to ask for memory using malloc for the rows and the malloc for the columns.
Related
I am trying to write a user defined function that takes some matrices and variables as inputs and gives a matrix as output. So something like this:
cofactor(int A[100][100], n, r, c){
int B[100][100]
//B becomes the cofactor matrix of A after some operations//
return B;
}
and in my main function I just want to write :
C=cofactor(D, n, r, c);
to turn C into the cofactor matrix of D.
But for some reason c language does not support taking a whole 2D array as output of a function. How can I work around this?
I don't want to keep all the junk in the main function. I want to write a separate function that gives me the matrix as output, and simply call that function in my main function.
Currently in your code B will go out of scope and will be destroyed when control exits cofactor.
Thus use pointer to pointer as below.
int **cofactor(int A[100][100], int n, int r, int c){
int **B = malloc(sizeof(int *)*r);
for (int i =0;i<r;i++)
B[i] = malloc(sizeof(int)*c);
//B becomes the cofactor matrix of A after some operations//
return B;
}
And from main.
int **C=cofactor(D, n, r, c);
Note:: NULL checks are not added and allocated memory needs to be freed once done with the processing.
You are correct in that C doesn't allow us to return arrays from functions. This is one area where C is simply plain bad and you'll find yourself choosing between various evils.
The most obvious alternatives are to return an array pointer, or a void pointer.
void pointers should be avoided since they have non-existent type safety.
// bad code
void* cofactor (int A[100][100], int n, size_t r, size_t c)
The array pointer option is rather ugly-looking, hard to read and enforces fixed-size dimensions:
// bad code
int ( *cofactor (int A[100][100], int n, size_t r, size_t c) )[100][100];
Alternatively, also ugly and bad practice, is to hide the array type behind a typedef:
// bad code
typedef int arr_t [100][100];
arr_t* cofactor(int A[100][100], int n, size_t r, size_t c)
The array pointer versions also have the limit that you can't use variable dimensions. But r and c here seem to be rows and columns, so you probably do want the array to have variable size.
This is where some start to use int** out of confusion. But int** cannot be used to point at a 2D array, nor to the first element of a 2D array. It can be used to point at the first element of a 1D array of int* pointers, and then emulate something that looks like an array, but doesn't behave like one. That's not what you want here either, because it is both slow and dangerous. See Correctly allocating multi-dimensional arrays.
Sigh. So what to use!
If you drop the requirement of "function return ing array" (with emphasis on using return), it turns easier and more flexible. Parameter passing to/from functions in C is most often done through the parameters, and most sound APIs reserve the return value for an error type describing the outcome of the function.
The big advantage here is that when passing an array as parameter, we can use variable dimensions:
void func (size_t r, size_t c, int A[r][c])
Suddenly you can have a function accepting any array size, and somewhat type safe as long as r and c have correct values.
The cleanest is to leave allocation to the caller. Then you get
void func (size_t r, size_t c, int A[r][c], int B[r][c])
Out of all options discussed, this is the only pretty one. But it won't work if the function must do the allocation. Then we must return an array through the parameter. And to that with this syntax, turns a bit ugly too:
void copy (size_t r, size_t c, int (**B)[r][c], int A[r][c])
But if we can live with this strange-looking "pointer to array pointer to an array of int[r][c]", then it solves all problems. It can return an array of variable size from a function to the caller.
A function making a copy of any array and returning it would look like this:
void copy (size_t r, size_t c, int (**B)[r][c], int A[r][c])
{
*B = malloc( sizeof(int[r][c]) );
int (*b)[c] = **B; // pointer to the first row in an array int[r][c]
for(size_t i=0; i<r; i++)
{
for(size_t j=0; j<c; j++)
{
b[i][j] = A[i][j];
}
}
}
Or if you will:
#include <string.h>
void copy (size_t r, size_t c, int (**B)[r][c], int A[r][c])
{
*B = malloc( sizeof(int[r][c]) );
memcpy( *B, A, sizeof(int[r][c]) );
}
Full example:
#include <stdlib.h>
#include <stdio.h>
void copy (size_t r, size_t c, int (**B)[r][c], int A[r][c])
{
*B = malloc( sizeof(int[r][c]) );
int (*b)[c] = **B; // pointer to the first row in an array int[r][c]
for(size_t i=0; i<r; i++)
{
for(size_t j=0; j<c; j++)
{
b[i][j] = A[i][j];
}
}
}
int main (void)
{
int array1[2][3] = { {1,2,3}, {4,5,6} };
int (*array2)[2][3];
copy(2, 3, &array2, array1);
int (*arr)[3] = *array2;
for(size_t i=0; i<2; i++)
{
for(size_t j=0; j<3; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
free(array2);
}
This question already has answers here:
How to return matrix (2D array) from function? (C)
(3 answers)
Closed 6 years ago.
Maybe my question is easy but I am newby in C.
I create a function which read some data from a file and then pass them to a another function which parse them given number of rows and columns and create a 2D array.
I want to return this array in order to perform some operantions in its rows. How can I return a 2D array in C
Can someone give me an example or what may I did wrong?
Regards
Beware, returning arrays in C is a beginner's trap, because it is highly dependant on the storage duration:
static or global: no problem, but content will be overwritten by next call
automatic : never do that! What is actually returned is a dangling pointer, because the array's life ends at the end of the return statement
dynamic (malloc-ed): fine, but caller must free it later.
An more idiomatic way is that the caller passes an array that it owns, along with its size(s).
You can not return an array as a result of a function no matter whether it has one dimension or two. You can return a pointer to the first element of the array. Also, strictly speaking, there are no two dimensional arrays in C. What is closest to this, is an array containing another array as elements. I.e. a definition like:
int twoDimArray[2][3];
If dimensions of such array are determined dynamically you can not define it on file scope. You can define it locally withing some function only. Such an array will be a local variable, will be stored in system stack and will disappear when control leaves the function. Personally, I'd use such a pattern. I.e. a code like:
int main() {
int rows, cols;
...
getDimensions(&rows, &cols);
// definition with dynamic dimensions in function scope is O.K.
int a[rows][cols];
init(rows, cols, a);
proceed(rows, cols, a);
...
}
where init function can be defined like:
void init(int rows, int cols, int a[rows][cols]) {
int i,j;
for(i=0; i<rows; i++) {
for(j=0; j<cols; j++) {
a[i][j] = i*100+j;
}
}
}
If such a pattern can not be used (the array is too big and your system stack too small for example), I'd use:
int main() {
int rows, cols;
getDimensions(&rows, &cols);
int (*a)[cols] = malloc(sizeof(int [rows][cols]));
init(rows, cols, a);
proceed(rows, cols, a);
free(a);
}
If you insist on functions returning such an array I'd use void pointers:
void *allocate2DintArray(int rows, int cols) {
return(malloc(sizeof(int [rows][cols])));
}
void *allocateAndInit(int rows, int cols) {
int i,j;
int (*a)[cols] = allocate2DintArray(rows, cols);
for(i=0; i<rows; i++) {
for(j=0; j<cols; j++) {
a[i][j] = i*100+j;
}
}
return(&a[0][0]);
}
int main() {
int rows, cols;
...
getDimensions(&rows, &cols);
int (*a)[cols] = allocateAndInit(rows, cols);
proceed(rows, cols, a);
...
free(a);
}
I was given an assignment to create a program that gets a 2d array, number of rows and number of columns, and then return the transposed matrix and print it, using only pointer arithmetic, no [] allowed.
My code is working perfectly. It does indeed print the transposed matrix, but after that, i get the following message:
Windows has triggered a breakpoint in First Assignment.exe.
This may be due to a corruption of the heap, which indicates a bug in First Assignment.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while First Assignment.exe has focus.
The output window may have more diagnostic information.
Can anyone help me with this? I have no idea what's wrong. This is my code:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
int** allocate_matrix(int rows,int columns);
void print_matrix(int** mat1,int rows, int columns);
void scan_matrix(int** mat1,int rows, int columns);
int** transpose_matrix(int** mat1, int rows, int columns);
void main()
{
int** mat1;
int** trans_mat1;
int rows,columns;
printf("Enter the number of rows and columns you wish to see\n");
printf("Rows:");
scanf("%d",&rows);
printf("Columns:");
scanf("%d",&columns);
mat1 = allocate_matrix(rows,columns);
scan_matrix(mat1,rows,columns);
printf("the matrix you entered is: \n");
print_matrix(mat1,rows,columns);
printf("The transposed matrix is:\n");
trans_mat1 = transpose_matrix(mat1,rows,columns);
print_matrix(trans_mat1,columns,rows);
getch();
free(mat1);
free(trans_mat1);
}
int** allocate_matrix(int rows,int columns)
{
int i;
int** ptrmatrix;
ptrmatrix = (int**)malloc(rows*sizeof(int*));
for(i=0;i<rows;i++)
*(ptrmatrix+i) = (int*)malloc(columns*sizeof(int));
return ptrmatrix;
}
void print_matrix(int** mat1,int rows, int columns)
{
int i,j;
for(i=0;i<rows;i++)
{
for(j=0;j<columns;j++)
printf("%d ",*(mat1+i*columns+j));
printf("\n");
}
}
void scan_matrix(int** mat1,int rows, int columns)
{
int i,j;
for(i=0;i<rows;i++)
{
printf("Enter %d values for row number %d\n",columns,i+1);
for(j=0;j<columns;j++)
scanf("%d",(mat1+i*columns+j));
}
}
int** transpose_matrix(int** mat1,int rows,int columns)
{
int i,j;
int** trans_mat1;
trans_mat1 = allocate_matrix(columns,rows);
for(i=0;i<rows;i++)
for(j=0;j<columns;j++)
*(trans_mat1+(j*rows)+i)=*(mat1+(i*columns)+j);
return trans_mat1;
}
There seems to be an error in your pointer arithmetic that is causing the problem.
printf("%d ",*(mat1+i*columns+j));
Should be:
printf("%d ",*(*(mat1+i)+j));
It seems that you misunderstood how you are allocating your matrix. Normally in these kinds of assignments you would allocate your matrix as a single array of NxM integers and then use the formula that you initially used.
Example:
int rows = 7, cols = 9;
int* matrix = (int*) malloc(rows * cols * sizeof(int));
// Get 3rd row and 5th column value
int value = *(matrix + 3 * rows + 5);
But what you are doing is allocating an array of pointers to arrays of integers. Each integer array is a row in your code. So what you need to do is first access the correct pointer in the array of pointers (mat + i) (which signifies a pointer to the ith row array) , get the pointer value *(mat+i) and then access the correct column value. Here's a play by play for your example:
int rows = 9, cols = 21;
// Allocate the array of pointers to rows
int** matrix = (int**) malloc(rows * sizeof(int*));
// Allocate each row as an array of values
for (int j = 0; j < rows; ++j)
{
*(matrix + j) = (int*) malloc(cols * sizeof(int));
}
// Access the value at row 5, column 7
int* rowPtr = *(matrix + 5);
int value = *(rowPtr + 7);
Edit:
Other suggestions
Dealocation:
#mikyra's answer has also advised to deallocate your array's after use. I also recommend this but won't include it in my answer since he has already done the work in his. Please give him credit for it.
Memory efficiency:
Allocating the extra array of pointers uses more memory than using a single array of NxM size, provided that all rows are allocated. If you have some logic that tries to leave empty rows unallocated you could get better memory performance but it would only be beneficial for large, sparse matrices which I believe is beyond the scope of your assignment.
I personally prefer the single array approach as it is simpler to allocate/deallocate and index.
You really didn't do yourself a favor in deciding on not just allocating a row x column memory block for your matrix operations. Especially if this is intended as a beginners exercise in pointer-arithmetic.
The right expression to access the value of the cell in row i and column j is in fact this one:
*((*(mat1 + i))+j)
Using the following corrected versions everything should work as expected:
void print_matrix(int** mat1,int rows, int columns)
{
int i,j;
for(i=0;i<rows;i++)
{
for(j=0;j<columns;j++)
/* this line has been changed */
printf("%d ", *((*(mat1 + i))+j));
printf("\n");
}
}
void scan_matrix(int** mat1,int rows, int columns)
{
int i,j;
for(i=0;i<rows;i++)
{
printf("Enter %d values for row number %d\n",columns,i+1);
for(j=0;j<columns;j++)
/* this line has been changed */
scanf("%d",(*(mat1+i))+j);
}
}
int** transpose_matrix(int** mat1,int rows,int columns)
{
int i,j;
int** trans_mat1;
trans_mat1 = allocate_matrix(columns,rows);
for(i=0;i<rows;i++)
for(j=0;j<columns;j++)
/* this line has been changed */
*((*(trans_mat1 + j))+i) = *((*(mat1 + i))+j);
return trans_mat1;
}
Nevertheless you still lack a method to free all the memory consumed by your matrices. You'd need something like this:
void deallocate_matrix (void* mat, int rows) {
while (rows--)
free (*(mat + rows));
free (mat);
}
To really free all the allocated memory.
I am writing a n x n matrix multiplication program in C where a[][] and b[][] are the inputs and x[][] is the output. a, b and x are malloc'd but I am unsure how to pass the pointers to the multiplication function correctly. below is an outline of what i am trying to do
void multiplication(float a, float b, float x, int n);
void main() {
float **a, **b, **x;
int n; // size of arrays (n x n)
multiplication(a, b, x, n);
}
void multiplication(float a, float b, float x, int n) {
// function
}
You want void multiplication(float *a, float *b, float *x, int n);. Note that generally you should use size_t for indexes and array sizes, and double as your preferred floating point type unless you have specific reason to use float.
Each of a, b and x point to contiguous float values, you will want to dereference these using a[n * x + y].
C99 introduces all kinds of interesting optimization possibilities on top of this, all of which you pretty much can't rely upon in any compiler I know of:
Variable Length Arrays in GCC
Arrays in XL C/C++ V7.0 (for AIX)
With those, something like this should be possible:
void multiplication(size_t len; // <- semicolon not a mistake
double a[len][restrict const len],
double b[len][restrict const len],
double c[len][restrict const len]);
This pedantic construction would indicate to the compiler that the length of the arrays are are the same, they're 2D, and the sizes are indicated from the calling code at runtime. Furthermore all the arrays are cacheable as they don't alias one another.
One can only dream that C continues to be advanced, C99 still isn't fully supported, and many other improvements haven't become mainstream.
you have to pass the address of first element of both matrix in multiplication method
actually the thing is that the elements of an array is arranged like queue means one element after another. so if you know the address of first element then you just increase the index number and you easily get all member of that array.
check this
it might be help you
Well, you must understand pointers for doing this kind of things in C. Here's a simple code:
int n = 10;
float * multiply ( float *a, float *b ) {
float *ans;
int i, j, k;
ans = malloc(sizeof(float)*n*n);
for (i=0; i<n; ++i)
for (j=0; j<n; ++j) {
ans[i*n+j] = 0.0;
for (k=0; k<n; ++k)
ans[i*n+j] += a[i*n+k] * b[k*n+j];
}
return ans;
}
int main() {
float *a, *b, *ans;
a = malloc(sizeof(float)*n*n);
input(&a);
b = malloc(sizeof(float)*n*n);
input(&b);
ans = multiply(a,b);
output(ans);
return 0;
}
If you have trouble understanding the code, please try to brush up your pointer skills. And you can always ask us.
Here is a nice easy way to pass dynamically allocated arrays to a function.
#include <stdio.h>
#include <stdlib.h>
void Function(int ***Array);
int main()
{
int i, j, k, n=10;
//Declare array, and allocate memory using malloc. ( Dimensions will be 10 x 10 x 10)
int ***Array=(int***)malloc(n*sizeof(int**));
for (i=0; i<n; i++)
{
Array[i]=(int**)malloc(n*sizeof(int*));
for (j=0; j<n; j++)
{
Array[i][j]=(int*)malloc(n*sizeof(int));
}
}
//Initialize array in a way that allows us to check it easily (i*j+k).
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
{
for (k=0; k<n; k++)
{
Array[i][j][k]=i*j+k;
}
}
}
//Check array is initialized correctly.
printf("%d\n", Array[4][5][6]);
//Pass array to Function.
Function(Array);
//Check that Function has correctly changed the element.
printf("%d\n", Array[4][5][6]);
return 0;
}
void Function(int ***Array)
{
//Check that Function can access values correctly.
printf("%d\n", Array[4][5][6]);
//Change an element.
Array[4][5][6]=1000;
}
I know this is not specific to your matrix multiplication, but it should demonstrate how to pass the array to the function. It is quite likely that your function would need to know the dimensions of the array, so pass those to it as well... void Function(int ***Array, int n) and call the function as Function(Array, n);
Consider this code:
#include <stdio.h>
#define N 5
void printMatrix(int (*matrix)[N],int n)
{
int i,j;
for(i=0;i<n;i++){
for(j=0;j<n;j++)
printf("%d",matrix[i][j]);
printf("\n");
}
}
int main()
{
int R[N][N]={{1,2,3},{4,5,6},{7,8,9}};
printMatrix(R,3);
}
This works fine as expected.
Now, I thought to write the functions handling 2D-matrices in a separate source file and link them wherever required.
But then I ran into a problem as in the function printMatrix, the size of array of int to which matrix points (i.e N) is required at compile-time. So, my functions would not work in other cases when the size is different.
So,How can I handle this?
Dynamic Arrays are a solution but i want to know if it can be done with static arrays.
You can't use the built-in 2D array type if both sizes are not known at compile time. A built-in 2D array must have at least one of the two sizes known at compile time.
If both sizes are run-time values, then you have no other choice but to use a "manual" implementation of 2D array, like an array of pointers to arrays, for example. In that case the function declaration might look as follows (two alternative equivalent forms)
void printMatrix(int *const *matrix, int n, int m);
void printMatrix(int *const matrix[], int n, int m);
To access to the array elements you can still use the "traditional" syntax
matrix[i][j]
The array itself would be created as follows (a simple example)
int row0[] = { 1, 2, 3 };
int row1[] = { 4, 5, 6 };
int *matrix[2];
matrix[0] = row0;
matrix[1] = row1;
printMatrix(matrix, 2, 3);
But if you already have a matrix implemented as a built-in 2d array
int matrix[2][3] = { ... };
then just to be able to pass it to the above function you can "convert" it into the above form by using an additional temporary "row pointer" array
int *rows[2];
rows[0] = matrix[0];
rows[1] = matrix[1];
printMatrix(rows, 2, 3);
Write yourself a macro:
#define MAT(i,j) matrix[i*n + j];
and declare "matrix" as a simple pointer to an "int".
Calculate the array index yourself. This will handle an arbitrary two dimensional array, for example:
void printMatrix(int *matrix,int n, int m)
{
int i,j;
for(i=0;i<n;i++){
for(j=0;j<m;j++)
printf("%d",matrix[m * i + j]);
printf("\n");
}
}
Don't try to pass it as a 2-D array; pass a pointer to the first element, then compute offsets manually:
void printMatrix(int *a, size_t m, size_t n)
{
size_t i,j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("a[%lu][%lu] = %d\n",
(unsigned long) i,
(unsigned long) j,
a[i*n+j]); // treat a as 1-d array, compute offset manually
}
}
}
int main(void)
{
int arr[5][4];
...
printMatrix(&arr[0][0], 5, 4);
...
}
Granted, this will only work for contiguously allocated arrays.
Although the syntax is not exactly the same, but this also happens to work a bit:
#include <stdio.h>
#define N 5
void printMatrix(int* row,int n,int sz)
{
int i,j;
int *currRow;
for(i=0;i<n;i++){
currRow = row+i*sz;
for(j=0;j<n;j++)
printf("%d",currRow[j]);
printf("\n");
}
}
int main()
{
int R[N][N]={{1,2,3},{4,5,6},{7,8,9}};
printMatrix(R[0],3,sizeof(R[0])/sizeof(int));
}