Input matrix in C using function - c

I am trying to input a matrix of order p*q using a function I got some errors. how to get the input using a pointer it gives me a segmentation fault .
#include<stdio.h>
int read_matrix(int *x,int p,int q){
for(int i=0;i<p;i++){
for(int j=0;j<q;j++){
scanf("%d",*(x+i)+j);
}
}
return 0;
}
int main(){
int p,q;
printf("enter the order of the matrix");
scanf("%d%d",&p,&q);
int a[p][q];
read_matrix(a[q],p,q);
for(int i=0;i<p;i++){
for(int j=0;j<q;j++)
printf("%d",a[i][j]);
}
}

You have multiple problems and seem to misunderstand how arrays and pointers work. To begin with a[q] will be out of bounds if p <= q.
a[q] (if q is valid) is an array of q elements, which decays to a pointer to its first element. It's not any kind of pointer to the matrix itself.
And inside the read_matrix function when you do *(x + i) + j that is actually equal to x[i] + j which is a single int value, and not a pointer to an element in any array.
You need to pass the matrix itself to the function, and let it decay to a pointer to an array, and use that as a proper "array of arrays":
// Use variable-length arrays for the matrix argument x
// Declare it as a pointer to an array of q integer elements
// Note the changed order of arguments, it's needed because q must be declared
// before its used for the VLA
void read_matrix(int p, int q, int (*x)[q]) {
for (int i = 0; i < p; ++i) {
for (int j = 0; j < q; ++j) {
scanf("%d", &x[i][j]); // Use normal array indexing and address-of operator
}
}
}
int main(void) {
int p, q;
scanf("%d %d", &p, &q);
int a[p][q];
// Here a will decay to a pointer to its first element, &a[0]
// Since a[0] is an array of q elements, the type will be
// int (*)[q], exactly as expected by the function
read_matrix(p, q, a);
for (int i = 0; i < p; ++i) {
for (int j = 0; j < q; ++j) {
printf("%d ", x[i][j]);
}
printf("\n");
}
}

You are making things needlessly complicated with the pointer arithmetic. *(x+i)+j means x[i] + j*sizeof(int) which is not what you want.
Just do something like this instead:
#include<stdio.h>
void read_matrix(int x, int y, int matrix[x][y])
{
int count=0;
for(int i=0;i<x;i++)
for(int j=0;j<y;j++)
matrix[i][j] = ++count;
}
int main (void)
{
int x=3, y=2;
int matrix[x][y];
read_matrix(x,y,matrix);
for(int i=0;i<x;i++)
{
for(int j=0;j<y;j++)
printf("%d ",matrix[i][j]);
printf("\n");
}
}

Related

main.c: warning: passing argument of ‘’ from incompatible pointer type

I'm trying to pass and return a two-dimension dynamic array by parameter, however it always shows this warning I mentioned in the question. I know there's something wrong with the array parameter, but I couldn't find in any book or a website how to properly pass an array whose dimensions change. I've read similar questions to mine about the warning and it's mostly about adding a & in your pointer, which I haven't added in mine.
#include <stdio.h>
#include <stdlib.h>
void fun(int m, int n, int (*arr)[n]);
int main(void) {
int i, j, m, n, **arr;
printf("Enter the dimensions m, n\n");
scanf("%d %d", &m, &n);
arr = (int **)malloc(m * sizeof(int *));
for (i = 0; i < m; i++) {
arr[i] = (int *)malloc(n * sizeof(int));
}
fun(m, n, *arr);
printf("\n\n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
printf("%5d", arr[i][j]);
}
printf("\n");
}
if (arr == NULL) {
exit(1);
} else
if (arr != NULL) {
free(arr);
}
return 0;
}
void fun(int m, int n, int (*arr)[n]) {
int i, j, k = 0;
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
k = k + 1;
arr[i][j] = k;
}
}
}
int **arr;
In main, arr is a pointer to a pointer to integer and you populate it with a nested memory allocation, because there are two levels of pointers involved. The arr[i] can be fragmented and each could hold a different number of entries, making arr a "ragged" array.
int (*arr)[n]
The argument to your function is a pointer to an array of n integers. Here the entries of arr are contiguous in memory, so that arr[0] and arr[1] are sizeof(int[n]) bytes apart.
These are different types and the compiler tells you so. Pick one.
A You can stick with the pointer-to-pointer approach. Then your function signature must match the definition in main:
void fun(int m, int n, int **arr) ...
In that case, you must also free all arr[i] at the end, before free(arr).
B Alternatively, you can keep your curret function and create a contiguous array with a single allocation:
int (*arr)[n] = malloc(m * sizeof(*arr));
Then pass it to your function directly without dereferencing it:
fun(m, n, arr);
At the end, just free(arr).
You are passing pointer to int(that is *arr) but you have declared function that will get pointer to array of n integers.
So, just make the following changes:
void fun(int m, int n, int **arr); // also change where function definition begins
fun(m, n, arr);
By the way, freeing memory is incomplete.
for (i=0; i<m; i++)
free(arr[i]); // first free individual array elements
free(arr);
fun is defined as receiving a pointer to variable sized array or n int. This is a C99 specific syntax that some C compilers might not support. You could also have defined fun with a simpler and more readable prototype that is in fact equivalent:
void fun(int m, int n, int arr[m][n]);
Also equivalent to this one:
void fun(int m, int n, int arr[][n]);
The problem is you allocate a very different type of object: an array of m pointers to arrays of n int. You should instead allocate an array of m variable sized arrays of n int and store its address to a pointer with the appropriate type:
int (*arr)[n] = malloc(m * sizeof(*arr));
Or just define it as a 2D variable sized array with automatic storage:
int arr[m][n];
If allocated with malloc(), you would free the object with
free(arr);
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
void fun(int m, int n, int arr[m][n]);
int main(void) {
int i, j, m, n;
printf("Enter the dimensions m, n\n");
if (scanf("%d %d", &m, &n) != 2 || m <= 0 || n <= 0)
return 1;
int (*arr)[n] = malloc(m * sizeof(*arr));
if (arr == NULL)
return 1;
fun(m, n, arr);
printf("\n\n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
printf("%5d", arr[i][j]);
}
printf("\n");
}
free(arr);
return 0;
}
void fun(int m, int n, int arr[m][n]) {
int i, j, k = 0;
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
k = k + 1;
arr[i][j] = k;
}
}
}

Passing a 2d array to a function if I don't know the dimensions

I am trying to write a C function to add two arrays. The function should work with any array sizes and it should receive a reference to both arrays and the number of rows and the number of columns and it should return a pointer to the first element of the resulting array.
How would I do that? When I try to pass a two dimensional array to a function I get an error?
#include<stdio.h>
void function(int r, int c,int a[][]){
int i,j;
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
printf("%d, ",a[i][j]);
}
printf("\n");
}
}
int main(){
int array[2][2] = {{1,2},{4,5}};
function(2,2,array);
return 0;
}
Assuming C99, or C11 with an implementation that doesn't define __STDC_NO_VLA__, you could use the variable length array (VLA) notation and could write:
void function(int r, int c, int a[r][c])
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
printf("%d, ", a[i][j]);
putchar('\n');
}
}
Or something equivalent to that. The dimensions must be defined before they're used in the array specification.
If you don't have access to even a C99 compiler but only a C90 compiler, then you have to pass a pointer to the first element of the array and the sizes and you perform the array index calculation explicitly.
void function(int r, int c, int *a)
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
printf("%d, ", a[i * c + j]);
putchar('\n');
}
}
Now you call the function like this:
int main(void)
{
int array[2][2] = { { 1, 2 }, { 4, 5 } };
function(2, 2, &array[0][0]);
return 0;
}

Using a swap function to swap the address in pointers of a 2D-array

For an assignment I need to make a sorting algorithm for n amount of vector arrays. The assignment specifically tells me to not swap the value of what the pointers are pointing to, but the address that is stored in those pointers. The result will then be printed using those pointers.
My problem is that I can't seem to accomplish the swapping of the addresses that the pointers contain. I have searched SO for related questions but they almost all change the values of where the pointers are referring to.
So far I have this:
Swap function
void swap(double **p, double **q, int i, int j){
double* tmp;
tmp = &p;
*p= &q;
*q = tmp;
printf("\tSwapped [%d][%d] and [%d][%d]\n", i,j, (i-1), j);}
And my main function
int main (void){
int dim, num, *tmp;
int i, j, a;
double **w;
scanf("%d %d", &dim, &num); /* read the dimension and amount of array*/
w = calloc(num, sizeof(double *)); /* allocate array of num pointers */
for (i = 0; i<num; i++)
{
/*allocate space for a dim-dimensional vector */
w[i] = calloc(dim, sizeof(double));
/* read the vector */
for (j = 0; j < dim; j++)
{
scanf("%le", &w[i][j]);
}
}
a = 0;
while (a <= num)
{
/*sort num times*/
i = (num -1);
while(i != 0)
{
if ((argument1) > (argument2) )
{ /*swap each columns of the rows individually*/
printf("\tSwapping..\n");
for(j = 0; j<dim; j++)
{
swap(&w[i][j], &w[i-1][j], i, j);
}
}
i--;
}
a++;
}
for(i=0; i<num; i++)
{
for(j=0; j<dim; j++)
{
printf("%e ",w[i][j]);
}
printf("\n");
}
return 0;
}
When i test this program, it does enter the swap function correctly but the printed result is the same as the input (so not swapped). Can anyone help me why this isn't working?
The swap function can look like
void swap( double **p, double **q )
{
double *tmp = *p;
*p = *q;
*q = tmp;
}
As for the code that is used to sort arrays then it is invalid and does not make sense. At least the variables argument1 and argument2 are not declared.

Adding 2 matrices using pointers

I can acheive it by passing (c,a,b) to add_mat function, where result of a,b is stored in c like,
void add_mat(int c[][3], int a[][3], int b[][3], int m, int n)
What should be the return type of add_mat if I want to construct the funtion in this way
?? add_mat(int a[][3], int b[][3], int m, int n)
Below is a sample code
#include<stdio.h>
void read_mat(int a[][3], int m, int n){
//scan data
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
printf("[%d][%d] : ",i,j);
a[i][j]=i+j;
}
}
}
int* add_mat(int a[][3], int b[][3], int m, int n){
int c[3][3];
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
c[i][j]=a[i][j]+b[i][j];
}
}
return c;
}
int main(){
int a[3][3];
int m=2,n=2; //mxn of a matrix
read_mat(a, m, n);
//add
int b[3][3];
read_mat(b, m, n);
int* c[3][3];
c = add_mat(a,b,m,n);
return 0;
}
Like passing or pointing the calculated value c inside add_mat function to variable in main function.
You cannot do that, since the memory of the c matrix will be gone when the function terminates.
You need to dynamically allocate it with malloc(), in order for the memory not to be free'd, unless you call free(). I have some examples for that in 2D dynamic array (C), if you want to take a look.
With your previous function, you would create the matrix c outside the function (in main()), that's why dynamic memory allocation was not required.
PS: You should compile with warnings enabled:
prog.c: In function 'add_mat':
prog.c:19:12: warning: returning 'int (*)[3]' from a function with incompatible return type 'int *' [-Wincompatible-pointer-types]
return c;
^
prog.c:19:12: warning: function returns address of local variable [-Wreturn-local-addr]
prog.c: In function 'main':
prog.c:32:7: error: assignment to expression with array type
c = add_mat(a,b,m,n);
^
prog.c:31:10: warning: variable 'c' set but not used [-Wunused-but-set-variable]
int* c[3][3];
^
Here is a working example, which is just for demonstrative purposes:
#include <stdio.h>
#include <stdlib.h>
void read_mat(int a[][2], int n, int m){
//scan data
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
a[i][j] = i + j ;
}
}
}
int **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i, **table;
table = malloc(N*sizeof(int *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(int) );
return table;
}
void print(int** p, int N, int M) {
int i, j;
for(i = 0 ; i < N ; i++)
for(j = 0 ; j < M ; j++)
printf("array[%d][%d] = %d\n", i, j, p[i][j]);
}
void free2Darray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
int** add_mat(int a[][2], int b[][2], int m, int n){
int** c = get(n, m);
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
c[i][j]=a[i][j]+b[i][j];
}
}
return c;
}
int main(){
int n = 2, m = 2; //nxm of a matrix
int a[n][m];
read_mat(a, n, m);
//add
int b[n][m];
read_mat(b, n, m);
int** c;
c = add_mat(a, b, n, m);
print(c, n, m);
free2Darray(c ,n);
return 0;
}
Output:
array[0][0] = 0
array[0][1] = 2
array[1][0] = 2
array[1][1] = 4
PPS: If you really want to use static arrays, then I recommend using int c[3][3]; add_mat(c, a, b, m, n);
Oh yes, the pointers ...
In C, locally declared arrays usually are allocated on the stack (not on the heap) which means they are not valid outside the respective scope.
In other words, in your function add_mat(), c technically can be returned, but the address it points to will only contain meaningful matrix data as long as the function is executed.
After having returned from the function, the return value of the function is a pointer which still contains (points to) the address where the matrix was stored during execution of the function, but the contents of that location, i.e. the matrix data, can contain arbitrary garbage now.
So what you are doing is technically possible (i.e. throws no compile errors), but is definitely not what you want.
Secondly, your line int* c[3][3]; probably is not what you intend it to be. You are declaring c to be a two-dimensional array (matrix) of pointer to int here. This is not correct since you want to process int values, but not pointers to int values (which are addresses).
To solve both problems, just write int c[3][3]; instead of int* c[3][3]; and change your add_mat() function as follows:
void add_mat(int a[][3], int b[][3], int c[][3], int m, int n){
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
c[i][j]=a[i][j]+b[i][j];
}
}
}
Then call that function like that:
add_mat(a,b,c,m,n);
In your code add_mat returns the pointer to the variable which lives while the function executes only. You can accomplish your goal with dynamically allocated matrix.
In C it is common to pass a dynamically allocated matrix via pointer to pointers to the rows of matrix as a first parameter:
void foo(int** matrix, size_t m, size_t n);
Here matrix is a pointer to the array of pointers. Every pointer in this array points to the row of matrix. So, matrix[0] points to the array containing the first row of matrix.
And it is common to use size_t type for any sizes of arrays.
If you need create matrix dynamically, be careful with memory. Every dynamically allocated block should be released. Otherwise you will get memory leaks, that may cause the program crash. Therefore, when you allocate rows of matrix, you should check if allocation of current row was successfull. If not, you should release all previously allocated rows.
There is a working code for your question:
#include <stdio.h>
#include <stddef.h>
#include <malloc.h>
void free_mat(int** a, size_t m) {
if (!a) {
return;
}
for (size_t i = 0; i < m; ++i) {
free(a[i]);
}
free(a);
}
int** create_mat(size_t m, size_t n) {
int** rows = calloc(m, sizeof(int*));
if (!rows) {
return NULL;
}
for (size_t i = 0; i < m; i++) {
rows[i] = malloc(n * sizeof(int));
if (!rows[i]) {
free_mat(rows, m);
return NULL;
}
}
return rows;
}
void read_mat(int** a, size_t m, size_t n) {
for (size_t i = 0; i < m; i++) {
for (size_t j = 0; j < n; j++) {
printf("[%d][%d]: ", i, j);
scanf("%d", a[i] + j);
}
}
}
void print_mat(const int* const* a, size_t m, size_t n) {
for (size_t i = 0; i < m; ++i) {
for (size_t j = 0; j < n; ++j) {
printf("[%d][%d]: %d\n", i, j, a[i][j]);
}
}
}
int** add_mat(const int* const* a, const int* const* b, size_t m, size_t n) {
int** c = create_mat(m, n);
if (c) {
for (size_t i = 0; i < m; ++i) {
for (size_t j = 0; j < n; ++j) {
c[i][j] = a[i][j] + b[i][j];
}
}
}
return c;
}
int main() {
size_t m = 3;
size_t n = 3;
int** a = create_mat(m, n);
int** b = create_mat(m, n);
if (!a || !b) {
printf("error when allocating matrix\n");
}
else {
read_mat(a, m, n);
read_mat(b, m, n);
int** c = add_mat(a, b, m, n);
if (!c) {
printf("error when allocating matrix\n");
}
else {
print_mat(c, m, n);
free_mat(c, m);
}
}
free_mat(a, m);
free_mat(b, m);
return 0;
}
But you would be more flexible, if add_mat didn't create a new matrix.
It is common to pass a pointer to the result matrix as a function parameter:
void add_mat(int** c, const int* const* a, const int* const* b, size_t m, size_t n);

Double pointer to traverse and find 5 max elem in 2D array. C

So am trying to do a question that aims to find 5 max elements in int 2D array.
I had no issues with dynamically allocating the array and inputting the elements into it.
printf("Your 2-d order of choice?\n");
scanf ("%d %d", &i ,&j);
int array[i][j];
//Taking 2d array input
for (int c = 0; c < i; c++)
{
for (int d = 0; d < j; d++)
{
scanf("%d", &array[c][d]);
}
}
However, to find the 5 max elements and store them in an array it asks for a function with prototype.
int * max5(int **, int ,int)
I don’t know how to use double pointer to traverse the 2D array, even though I read a few other posts regarding int**, and what will int* (return type) exactly be and how to incorporate it.
There are the many ways to pass array as pointers
As per you said that if you take array like int array[10][10];.
Using single pointer you can do like
int *arr = max5 ((int *)array, 10, 10);
And traverse array as
int * max5 (int *arr, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", *((arr+i*n) + j));
//.........
}
OR using double pointer you can also do like
int *arr = max5 ((int **)array, 10, 10);
And traverse like
int * max5 (int **arr, int m, int n)// Same as int * max5 (int *arr[], int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", *((arr+i*n) + j));
//.........
}
Now other way also possible it just for your information
From C99, C language supports variable sized arrays to be passed simply by specifying the variable dimensions.
int *arr = max5 (array, 10, 10);
And traverse like
int * max5 (int arr[][10],int m,int n) //Same as int * max5 ( int (*arr)[10], int m,int n))
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", arr[i][j]);
//.........
}
This is the max5 function.
It gets 5 elements in res (allocated by malloc), then for the remaining elements of a, it finds the smallest elements of res and compare it with that a element - if the res element is maller than the a element, that res element is replaced with the a one.
Note that I wouldn't usually use a magic number (5) in the function, but since it's called max5 ..
#include <limits.h>
int *max5(int **a, int rows, int cols) {
int *res = malloc(5 * sizeof(int));
int i,j,k,n=0; // n, number of elements in res
for (i=0 ; i<rows ; i++) {
for (j=0 ; j<cols ; j++) {
if (n < 5) res[n++] = a[i][j];
else {
// find lowest res element
int lowest=0;
for(k=1 ; k<5 ; k++) { // start from 1!
if (res[k] < res[lowest]) {
lowest = k;
}
}
// if lowest res is < a[i][j], replace it
if (res[lowest] < a[i][j]) res[lowest] = a[i][j];
}
}
}
return res;
}
For the sake of demo, this is not optimized (looking for the min all the time). One way would be to sort the res array after 5 elements have been inserted, and after one of its element is replaced (which should statistically happen less and less over the iterations). Another way would be to build a tree when the elements are input initially.
As mentioned by #haccks, array is to be declared as a int **, then i rows must be int * allocated (ie, i pointers to int), then each of the row is to be allocated the size of j int.
With the given prototype, you have to declare array as int ** and dynamically allocate memory to it.
int **array = malloc(i*sizeof(int*));
for(int row = 0; row < i; row++)
array[row] = malloc(j*sizeof(int));
Now you can call your max5 function as
int *a = max5(array, i, j);
Then dynamically allocate an array inside max5 and return it from max5.

Resources