I'm having some trouble creating a user-input matrix through a function I create. The function is as follows:
int create(int l, int c, int one[MAX][MAX])
{
for(int i = 0; i < l; ++i)
for(int j = 0; j < c; ++j)
scanf("%d", &one[i][j]);
}
I then proceed to call my function from main :
int main()
{
int mat[MAX][MAX];
int lines, collumns;
printf("Input # of lines, columns:\n");
scanf("%d %d", &lines, &collumns);
create(lines, collumns, mat[MAX][MAX]);
}
Oddly, if I copy the function to main and just run it as so, it works fine. But it just won't work if I try doing so through function calling, as my program crashes. What am I doing wrong guys?
Change
create(lines, collumns, mat[MAX][MAX]);
to
create(lines, collumns, mat);
and try again.
Well, when passing multidimensional arrays into a function in C, the basic rule is
You should specify the value for each of the dimension other than the first one.
So when you are passing a 2D array, define like this.
int create( int l, int c, int one[][MAX] ){...}
And when passing 3D array, define like this.
int create3D( int x, int y, int z, int mat[][MAX_Y][MAX_Z] ){...}
And when invoking the function, you only need to specify the name of the array variable. No need to specify the dimensions.
create( l, c, one );
create3D( x, y, z, mat );
You can see these errors/warnings if you compile with -Wall switch in gcc.
Good Luck!
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);
}
I have this exercise to make a transpose of a matrix in C. I made a function to check for type n*n but when I'm trying to ask the user for the matrix I don't know how I should declare the array. And I'm getting this compile error "type of formal parameter 1 is incomplete" in the function on the [n2] part.
The parameters of the functions for multi dimensional arrays shouldn't be like this -> int matrix[][n2]. or is cause i'm using a variable and not a constant or a pre defined size. ?
#include <stdio.h>
#define prompt "Dimenção da matriz (nxn) >>"
#define prompt_1 "Introduza os valores : "
void getType( int *n1, int *n2 );
void getMatrix( int matrix[][n2], int lim1, int lim2);
//void trans(int matrix[][n2]);
int main(int argc, char const *argv[]) {
int n1, n2;
getType(&n1, &n2);
int matrix[n1][n2];
//printf("%dx%d\n", n1, n2);
getMatrix(matrix, n1, n2);
//trans(matrix);
return 0;
}
void getType(int *n1, int *n2){
printf("%s", prompt );
scanf("%dx%d", &(*n1), &(*n2));
}
void getMatrix( int matrix[][n2], int lim1, int lim2){
printf("%s\n", prompt_1 );
for(int line = 0; line < lim1; line++ ){
for(int column = 0; column < lim2; column++){
printf("Linha %d coluna %d ->", line, column );
scanf("%d", &matrix[line][column]);
}
}
}
The signature should be:
void getMatrix( int lim1, int lim2, int matrix[lim1][lim2] )
You are allowed omit the lim1 inside square brackets but it is good documentation to include it.
The main point is that the variable inside the square brackets must either be a parameter from earlier in the parameter list, or some other variable in scope (which can only be a global variable, but that's usually a bad idea).
Also it would be good to check scanf return value otherwise you may create matrix with garbage dimension.
I'm working on some C homework for class and I've been running into issues using arrays. Here is a sample of one of my functions that's having an error.
void multiply(int a, int size)
{
int i;
for(i = 0; i < size; i++){
a[i] = a[i] * 5;
printf("%d, ", a[i]);
}
printf("\n");
}
It returns the error: subscripted value is neither array nor pointer nor vector on lines 5 & 6 when I call for a[i]. I have a as an array with size 10, but each time I try and call an individual value in the array it doesn't want to work. I've tried searching it but none of the solutions really seems to work.
You should change your function to:
void multiply(int * a, int size)
Change your function header to:
void multiply(int* a, int size)
Othewise the function thinks a is an int not an int array
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);
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];
}