Reputation: 55
I want to create a function that
takes the row and column as arguments.
takes inputs according to the given size and
returns the 2D matrix/array.
I've gone through lots of solutions online, but everything I try, gives me some new errors.
int* input_taker(int row, int col)
{
int mat[row][col];
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
scanf("%d", &mat[i][j]);
}
}
return mat;
}
Upvotes: 1
Views: 558
Reputation:
2D array of user-given size
and
pointer to an array of
col
integers.
both seem to avoid the term VLA
. 4386's answer gives the "C90 forbids VLA" warning with -Wvla
.
This
int mat[row][col];
dose not work because it is auto storage.
But
int (*mat)[col];
is only a pointer to a VLA; it can be malloced and returned.
To (over-)simplify 4386's function type and to split the definition of mat
this can be done:
void *array_maker(int row, int col) // just a pointer; no dimensions, no type
{
int (*mat)[col]; // declare runtime inner dim.: ptr to VLA
mat = malloc(row * sizeof *mat); // mallocate both dims
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
mat[i][j] = i*col + j; // fill the array[][]
return mat;
}
The call from main is:
int col, row;
int (*p)[col=8]; // ptr. to VLA
p = array_maker(row=5, col); // implicit cast from void-ptr
Since a VLA is involved anyway, one might turn it around and put the array pointer into a param. This turns the function from array-maker to array-filler:
void array_filler(int row, int col, int mat[][col])
{
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
mat[i][j] = i*col + j; // fill the array[][]
}
Now the array has to be allocated by the caller - either as auto-VLA or malloced VLA-pointer or fixed-size array:
col=row=9;
int mat[row][col];
//int (*mat)[col] = malloc(row * sizeof*mat);
//int mat[9][9];
array_filler(row, col, mat);
int mat[row][col];
wrong storage duration
int* input_taker(int row, int col)
-> incompatible type warning
Upvotes: 2
Reputation: 44340
The function return type is int*
but you are trying to return mat
which has a different type (i.e int* (*)[col]
) so that's a bug.
mat
is a function local variable so it doesn't exists once the function returns. In other words - returning mat
makes no sense at all. You are returning a reference to a "dead" object.
Instead you need to use dynamic allocation in the function so that the returned object still exist after function return.
For this you can define mat
as a pointer to an array of col
integers. Further, the function shall return a pointer to an array of integers.
Like:
#include <stdio.h>
#include <stdlib.h>
int (* input_taker(int row, int col))[]
{
int (*mat)[col] = malloc(row * sizeof *mat);
if (mat == NULL) exit(1);
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
mat[i][j] = i*col + j; // Here you can read user input
}
}
return mat;
}
int main ()
{
int col = 8;
int row = 5;
int (* p)[col] = input_taker(row, col);
for (int i=0; i<row; ++i)
{
for (int j=0; j<col; ++j)
{
printf("%5d ", p[i][j]);
}
puts("");
}
free(p);
return 0;
}
Output
0 1 2 3 4 5 6 7
8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
32 33 34 35 36 37 38 39
Upvotes: 4
Reputation: 3468
Other answers used VLAs as in your original question. The point is that I don't think VLAs are the way to go for matrices, since it's not unlikely to have the same variable change size during execution, and this requires a murky design with VLAs.
If you renounce to the double square brackets syntax, using a simple pointer is pretty straigthforward (I'm adapting 4386427 code for this):
#include <stdio.h>
#include <stdlib.h>
int *input_taker(int row, int col)
{
int *mat = malloc(row * col * sizeof *mat);
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
mat[i * col + j] = i * col + j; // Here you can read user input
}
}
return mat;
}
int main ()
{
int col = 8;
int row = 5;
int *p = input_taker(row, col);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
printf("%5d ", p[i * col + j]);
}
puts("");
}
free(p);
return 0;
}
Even better pack everything in a struct:
struct mat {
int rows, cols;
int *data;
};
and provide functions to use it.
Upvotes: 2
Reputation: 310
Your problem appears to be a dangling pointer. You have to allocate memory before calling input_taker.
#include <cstdio>
#include <cstdlib>
int* input_taker(int *ptr, int row, int col)
{
for (int i = 0; i < row; i++)
{
int *arr = &ptr[i*col];
for (int j = 0; j < col; j++)
{
scanf("%d", &arr[j]);
}
}
return ptr;
}
int main() {
int n_rows, n_cols;
n_rows = 2;
n_cols = 3;
// int *matrix = (int*)malloc(n_rows*n_cols*sizeof(int));
int matrix [n_rows][n_cols];
input_taker(&matrix[0][0], n_rows, n_cols);
for (int i = 0; i < n_rows; i++)
{
printf("[");
for (int j = 0; j < n_cols; j++)
{
j==n_cols-1?printf("%d]\n", matrix[i][j]):printf("%d, ", matrix[i][j]);
}
}
return 0;
}
I changed the function parameters but kept the return value. You may, however, return void.
Upvotes: 1