Passing a two dimensional dynamic array to a function - c

I don't know the array size when compiling so I declared a variable count and created an array arr[count][count], I will incrase this count variable while program is running and I will reallocate it's memory before doing that. But I couldn't create a function that takes this arr[count][count]. How can i do that ? When i did this like:
void add_friend(int friends[][*count], int p1, int p2)
{
}
compiler gives an error: count undeclared here.

You can't do what you are asking directly at least not in C. But as #millimoose suggests, if you know the dimensions (which can be passed as ints), you can do a little arithmetic to figure out where friends[p1][p2] is. If there are C elements per row, then you know that friends[r][0] is C*r ints from the start of friends, and can treat that row as a simple int array.

Well, here is a way to do what you want with a 1 dimensional array in c/c++:
void ff(int *arr_2d, int s1, int s2)
{
for(int i=0;i<s1;i++ )
{
for(int j=0;j<s2;j++ )
printf("f[%d][%d] = %d\t",i,j, *(arr_2d+i*s2+j));
printf("\n");
}
}
And you can use this function as:
int *f = new int[100];
int s1,s2;
s1 = s2 = 10;
for(int i=0; i<s1; i++)
for(int j=0; j<s2; j++)
*(f+i*s2+j) = (i*s2+j);
ff(f,10,10);

In C 1999 and in C 2011 implementations that support variable-length arrays, you can declare a function this way:
void add_friend(int count, int friends[][count], int p1, int p2) …

The count should be accessible by friends, to do that you can either declare it as a global variable or as an argument of the function.
void add_friend(int count, int friends[][count], int p1, int p2)
{
// ...
}
int main(void)
{
int a[25][10];
count = 10;
add_friend(10, a);
// ...
return 0;
}

you can do it like:
1.void add_friend(int count, int friends[count][count], int p1, int p2)
2.void add_friend(int count, int friends[][count], int p1, int p2)
3.void add_friend(int count, int (*friends)[count], int p1, int p2)

Related

How do I print an actual number from this program that contains a function that returns a pointer?

#include <stdio.h>
int *max(int *, int *);
int main()
{
int *p, i, j;
p = max(&i, &j);
printf("%d\n", i);
return 0;
}
int *max(int *a, int *b)
{
if(*a > *b)
return a;
else
return b;
}
This is a program intended to return an integer that is bigger. A function "max" returns a pointer, as you can see. I want to print an actual integer here, but I'm stuck and cannot find a proper way to accomplish it. Can somebody help or give some hint to solve my problem?
Also, I would love to know that why there should be an asterisk in front of the function "max". Should there always be an asterisk when a function returns a pointer? The book that I am currently studying lacks information about this specific part, so can someone scratch my back? ;)
Last question first - max returns the value of either a or b. Since both a and b have type int * (pointer to int), then the return type of max also needs to be int *.
To access the integer value, you would need to dereference the result of max:
int main()
{
int *p, i, j;
/**
* The values of i and j are indeterminate at this point;
* you need to assign valid values to them before calling
* max.
*/
i = some_value();
j = some_other_value();
p = max(&i, &j);
printf("%d\n", *p); // Dereference p here to print the int value
return 0;
}
Another way to look at it is that the expressions *a, *b, *p, and *max( &i, &j ) all have type int.
If you want max to return an int rather than an int *, then you will need to dereference a and b in the return statements:
int max( int *a, int *b )
{
if ( *a > *b )
return *a;
else
return *b;
}
Although...
It's not clear why you're passing pointers as arguments to max; you're not attempting to modify the values of a or b, so there's really no need to use pointers at all. Just define max as
int max( int a, int b )
{
if ( a > b )
return a;
return b;
}
and call it as
int m = max( i, j );
or even
printf( "max( %d, %d ) = %d\n", i, j, max( i, j ) );

How to get a 2 dimensional array as output of a user defined function?

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);
}

Passing multidimensional array in another way?

#include <stdio.h>
void arraypass(int from, int to, int a[][2]);
int main()
{
setbuf(stdout, NULL);
int t1 = 0, t2 = 0;
int testArray[10][2];
for (t1 = 0; t1 < 10; t1++)
{
testArray[t1][t2] = t1 + 1;
}
t2++;
for (t1 = 0; t1 < 10; t1++)
{
testArray[t1][t2] = t1 + 10;
}
arraypass(1,5,testArray);
return 0;
}
void arraypass(int from, int to, int a[][2])
{
int b;
for (b = from; b <= to; b++)
{
printf("%d ",a[b][0]);
printf("%d\n",a[b][1]);
}
}
Why is it that
int a[][2]
works, but not
int a[][]
for the argument definitions in this?
void arraypass(int from, int to, int a[][2]);
And, is there a way to possibly pass an entire multidimensional array at once, or do I need to perform some kind of loop?
For the compiler, a vector is a hidden pointer to its first item.
For example:
int a[2];
a[0]=0;
a[1]=1;
is the same of:
int a[2];
*(a+0)=0;
*(a+1)=1;
When you pass a multidimensional array (o a simple array) you should use pointers instead of a vector:
void arraypass(int from, int to, int **a);
and then if you want to use it you could do something like this:
void arraypass(int from, int to, int **a){
int i,j;
for(i=from; i<end; i++) {
for(j=0; j<2; j++) {
printf("%d",a[i][j]);
}
}
You have to remember that arrays decays to pointers. That means, when they are (for example) passed as arguments to functions the function receives a pointer.
What int a[][2] does, is the same as int (*a)[2], which means that a is a pointer to an array of two int. That is different from a pointer to an array of any other dimension, which is why you don't have to specify the primary "dimension" (as that to the compiler is the same as a pointer) but you do have to specify the other "dimension(s)".
This is related to this answer in the C FAQ.
Because the function receives a pointer when an array is passed to a function, the compiler needs to know the dimensionality of the array that the pointer will be to (in this case, two), but doesn't care how long the sequence of pointers to two-element arrays is going to be.

Passing an array created from fscanf into a new function

I have successfully fscanf a text file and saved in to an array E2N1. I am trying to pass this into a function as a pointer but it is not working. Whenever I try to call E2N1[0][0], it says that E2N is neither an array or a pointer. I've been looking all over for a solution on this.
(Sorry E2N was meant to be E2N1)
I use fscanf as:
int E2N1[noz.rowE2N][Q.N];
FILE* f = fopen("E2N.txt", "r");
for(i=0; i<noz.rowE2N; i++){
for (j=0; j<Q.N; j++){
fscanf(f,"%d",&E2N1[i][j]);
}
fscanf(f,"\n");
}
fclose(f);
and again I can't pass E2N1 into function.
Your help will be greatly appreciated.
The function is:
double *dudtF = stiffness(&U, &massM, &noz, &newV, &E2N1, &I2E, &B2E, &PP, &QQ);
and I write the function header as:
double *stiffness(double *U, double *massM, MESH *meshN, double *V1, int *E2N1, int *I2E, int *B2E, ordApprox *pp, ordApprox *qq)
V1, I2E, B2E are three arrays and I'm trying to do the same with them as I am trying to do with E2N1.
The funny thing about arrays is that they actually act as pointers.
if you have array char a[3] the variable is equivalent to char* p the same way if you have array char b[3][4] the variable b is equivalent to char** q. In other words, you should consider changing the handling in the method to take reference to reference (and possibly once more to reference) to integer.
Try google... here are some results I've got.
http://www.dailyfreecode.com/code/illustrate-2d-array-int-pointers-929.aspx
http://www.cs.cmu.edu/~ab/15-123S09/lectures/Lecture%2006%20-%20%20Pointer%20to%20a%20pointer.pdf
You don't need to pass as &E2N1, just pass as E2N1 no & as array name itself translates to pointer.
double *dudtF = stiffness(&U, &massM, &noz, &newV, E2N1, &I2E, &B2E, &PP, &QQ);
Also, you need to take it as int ** as its 2-dimensional array.
double *stiffness(double *U, double *massM, MESH *meshN, double *V1, int **E2N1, int *I2E, int *B2E, ordApprox *pp, ordApprox *qq)
Here is the example how to transfer matrix from one function to another ...
void foo (int **a_matrix)
{
int value = a_matrix[9][8];
a_matrix[9][8] = 15;
}
void main ()
{
#define ROWS 10
#define COLUMNS 10
int **matrix = 0;
matrix = new int *[ROWS] ;
for( int i = 0 ; i < ROWS ; i++ )
matrix[i] = new int[COLUMNS];
matrix[9][8] = 5;
int z = matrix[9][8] ;
foo (matrix);
z = matrix[9][8] ;
}
You cannot reference a multi-dimensional array passed to a function by point referencing as in the following:
int iVals[10][10];
foo(iVals);
void foo(int** pvals)
{
// accessing the array as follows will cause an access violation
cout << pvals[0][1]; // access violation or unpredictable results
}
You will need to specify the second dimension to the array in the function prototype
for example:
foo(int ivals[][10])
{
cout << ivals[0][1]; // works fine
}
If do not know the dimensions, then I would suggest you follow the principles outlined here:
void foo(int *p, int r, int c)
{
for(int i=0; i<r; i++)
{
for(int j=0; j<c; j++)
{
printf("%d\n", p[i*c+j]);
}
}
}
int c[6][6];
// pointer to the first element
foo(&c[0][0], 6, 6);
// cast
foo((int*)c, 6, 6);
// dereferencing
foo(c[0], 6, 6);
// dereferencing
foo(*c, 6, 6);
I hope this helps.
Alternatively you could use SAFEARRAY - see:
http://limbioliong.wordpress.com/2011/06/22/passing-multi-dimensional-managed-array-to-c-part-2/

Please help with passing multidimensional arrays

I'm writing a simple test program to pass multidimensional arrays. I've been struggling to get the signature of the callee function.
The code I have:
void p(int (*s)[100], int n) { ... }
...
{
int s1[10][100], s2[10][1000];
p(s1, 100);
}
This code appears to work, but is not what I intended. I want the function p to be oblivious whether the range of values is either 100 or 1000, but should know there are 10 pointers (by use of function signature).
As a first attempt:
void p(int (*s)[10], int n) // n = # elements in the range of the array
and as a second:
void p(int **s, int n) // n = # of elements in the range of the array
But to no avail can I seem to get these to work correctly. I don't want to hardcode the 100 or 1000 in the signature, but instead pass it in, keeping in mind there will always be 10 arrays.
Obviously, I want to avoid having to declare the function:
void p(int *s1, int *s2, int *s3, ..., int *s10, int n)
FYI, I'm looking at the answers to a similar question but still confused.
You need to transpose your arrays for this to work. Declare
int s1[100][10];
int s2[1000][10];
Now, you can pass these to a function like this:
void foo(int (*s)[10], int n) {
/* various declarations */
for (i = 0; i < n; i++)
for (j = 0; j < 10; j++)
s[i][j] += 1
}
Because of the way the C type system works, an array argument can only be "flexible" in the sense you want in its left-most index.
You could also create a struct for the matrix and pass it to the function p
struct Matrix{
int **array;
int n;
int m;
};
void p(Matrix *k){
length=k->m;
width=k->n;
firstElement=k->array[0][0];
}

Resources