Print a square matrix using pointers - c

I've browsed to previously answered questions regarding pointers and matrices, but in these cases the matrices were seen as pointers to pointers. However, I am trying to create a function which read a matrix using a simple pointer and another function which prints it.
This is my code, the read functions seems to work properly, but the program crashes at the printing part. If I remove the "*" from the printf statement the program works(i.e. it prints numbers from 4 to 4- I suppose this is alright, since an int is stored on 4 bytes).
void readm(int *p,int n)
{
p=(int *)malloc(sizeof(int)*n*n);
for(int i=0;i<n*n;i++)
scanf("%d",p+i);
}
void printm(int *p,int n)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%d ",*(p+(i*n)+j));
printf("\n");
}
}

In the readm function you have a problem with this line:
p=(int *)malloc(sizeof(int)*n*n);
Here you assign only to your local copy of the pointer. The variable you use when calling readm will not be changed.
You need to pass the pointer "by reference":
void readm(int **p,int n) /* Note pointer-to-pointer for `p` */
{
*p=malloc(sizeof(int)*n*n); /* Note pointer-dereference of `p` */
for(int i=0;i<n*n;i++)
scanf("%d",*p+i); /* Note pointer-dereference of `p` */
}
You then have to call the function using the address-of operator:
int *p;
readm(&p, X); /* Note use of address-of operator */

A pointer to a 1D array is defined as such:
int *p1dArr;
A pointer to a 2D array is defined as such:
int **p2dArr;
You're using a 1D array as though it's a 2D array. This is probably the source of your troubles. Change you function definitions to the following:
void readm(int **p, int row, int col)
{
p = malloc(row * sizeof(*p));
for(int r = 0; r < row; r++)
p[r] = malloc(col * sizeof(**p))
for(int r = 0; r < row; r++)
for(int c = 0; c < col; c++)
scanf("%d", &p[r][c]);
}
void printm(int **p, int row, int col)
{
for(int r = 0; r < row; r++)
{
for(int c = 0; c < col; c++)
printf("%d ", p[r][c]);
printf("\n");
}
}

The problem is that the calling code that calls function readm doesn't know that inside the function variable p (defined as a parameter of the function) got a new value. p is a local variable of the function and its life ends after exiting the function.
You should define the function the following way
void readm( int **p, int n )
{
*p = (int *)malloc( sizeof(int ) * n * n);
for ( int i=0; i<n*n; i++ ) scanf( "%d", *p+i );
}
and call it as
int *p;
readm( &p, n );
As for function printmthen there is no any need to redeclare it as
void printm( int **p, int n )
because it does not change the pointer. The only thing I would change is adding qualifier const
void printm( const int *p, int n );

Related

Passing 2d array to function with pointer

Can anyone explain what is the wrong of print() function ?
printf("Control") never works, output is segmentation fault-11
int main(int argc, char **argv){
int m=5,n=4; // matrix[5][4]
int a=50,b=20; // range: 20-50
int **matrix;
imatrix(matrix,m,n,a,b);
print(matrix,m,n);
first step: filling address with value
void imatrix(int **matrix,int m,int n,int max, int min){
srand(time(NULL));
int i=0,j=0;
matrix = (int **)malloc( m * sizeof(int*) );
if( matrix == NULL ){
printf( "memory req.!" );
}
for( i = 0; i < m; i++ ) {
matrix[i] = (int *)malloc( n * sizeof(int) );
if( matrix[i] == NULL ){
printf( "memory req.!" );
}
}
for(i=0;i<m;i++){
for(j=0;j<n;j++){
matrix[i][j]=(rand()%(max-min))+min;
printf("%2d ",matrix[i][j]);
}
printf("\n\n");
}
}
Anything is okey till here.
I get Segmentation fault: 11 after below code and line of "Control" never works
void print(int **matrix, int m, int n){
int i,j;
for(i=0; i < m; i++){
for(j=0; j < n; j++){
printf("%d",*(*(matrix + i) + j));
}
printf("\n");
}
printf("control");
}
It's not the printf("control") which segfaults (although you'd be a lot better off not using printf for that: consider changing it to puts("control"), which also outputs a newline character.) It's the previous attempt to print the matrix, which is dereferencing an uninitialised value.
That happens because your imatrix function does not return the matrix it created, and the matrix in your main is not given any value.
In fact, imatrix doesn't return anything, since it is defined as returning void. It takes a matrix argument, which I suppose was intended to be an output parameter, but:
that parameter has the wrong type to be an output parameter (an output parameter needs to be a pointer to the object to be returned;)
it never attempts to use the pointer to the object to be returned in order to return the object.
In order to comply with those requirements, you'd need the prototype
void imatrix(int*** matrix, int m, int n, int max, int min);
And you would have to add an additional level of indirection for each usage of matrix [Note 1]:
*matrix = malloc(m * sizeof(**matrix));
if (*matrix == NULL) {
printf( "memory req.!" );
/* NOTE: You shouldn't attempt to continue after the malloc fails.
* Return immediately and let the caller deal with the malloc failure.
*/
}
for( i = 0; i < m; i++ ) {
(*matrix)[i] = malloc( n * sizeof(*(*matrix)[i])) );
if( (*matrix)[i] == NULL ){
// etc.
I think we can agree that that is a major PITA and not worth the trouble unless necessary.
Personally, I find it less confusing to not use output parameters at all unless strictly necessary. In this case it isn't necessary at all because you can just return the pointer to allocate memory:
/* CHANGE: Prototype */
int** imatrix(int m, int n, int max, int min){
srand(time(NULL)); /* TODO: This initialisation should really be done in main */
int i=0, j=0;
/* CHANGE: matrix is a local variable */
int** matrix = malloc( m * sizeof(*matrix) );
/* CHANGE: Immediate return on malloc failure */
if( matrix == NULL ) {
return matrix;
}
for( i = 0; i < m; i++ ) {
matrix[i] = malloc( n * sizeof(*matrix[i]) );
if( matrix[i] == NULL ){
printf( "memory req.!" );
}
}
for(i=0;i<m;i++){
for(j=0;j<n;j++){
matrix[i][j]=(rand()%(max-min))+min;
printf("%2d ",matrix[i][j]);
}
printf("\n\n");
}
/* CHANGE: matrix is returned */
return matrix;
}
That has a slightly different usage pattern:
int main(int argc, char **argv){
int m=5, n=4; // matrix[5][4]
int a=50, b=20; // range: 20-50
/* CHANGE: imatrix returns the new matrix */
int **matrix = imatrix(m, n, a, b);
/* CHANGE: check for failure */
if (matrix == NULL) {
fprintf(stderr, "%s\n", "imatrix failed to allocate memory.");
exit(1);
}
print(matrix, m, n);
/* TODO: Free the storage allocated for matrix */
}
Notes
Throughout this code, I changed the usage of malloc from:
lvalue = (RedundantCast*)malloc(count * sizeof(FixedType));
to idiomatic C:
lvalue = malloc(count * sizeof(*lvalue));
The explicit cast of the return value of malloc is at best pointless in C, since malloc returns a void* and C is happy to automatically convert a void* into a pointer of any type. Using the type of the object pointed to by the target (sizeof(*lvalue)) rather than inserting a specific type protects you against the possibility that the type will change in a future edit, and you forget to make that change in all calls to malloc. (Consider what would happen if you decided to make matrix a matrix of long long instead of int, for example.)

Can someone explain me what is going on in this statement?

Basically i understand pointers. But when it comes to dynamic allocation for matrices which also involve pointers, i'm getting lost in the process. I wanna know how can i translate this segment of code in order to understand it.
(*a)[i] = (int*)malloc((*m) * sizeof(int));
The function for reading the matrix looks like this:
void reading(int *n, int *m, int ***a) {
int i, j;
printf("n=");
scanf("%d", &*n);
printf("m=");
scanf("%d", &*m);
(*a) = (int**)malloc((*n) * sizeof(int*));
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
for (i = 0; i < *n; i++) {
for (j = 0; j < *m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", &(*a)[i][j]);
}
}
}
And also what is the meaning of ***a in the declaration. I was told at college that te first asterisk stands for dynamic allocation and the other two's from the fact that is a matrix involved. For vectors dynamic allocation is **v and so on... but i can't naturally explain it in my mind in order understand what is happening in it.
First let me answer your question about this specific line:
(*a)[i] = (int*)malloc((*m) * sizeof(int));
What this is doing is allocating an array of exactly *m integers and saving a pointer to it into the array *a of pointers to int, which was previously allocated as:
(*a) = (int**)malloc((*n) * sizeof(int*));
Now, if it still isn't clear what is going on, re-writing the code in a more meaningful way will help. To make things easier, you can use temporary variables to work, and assign the values to the pointers passed as arguments only at the end of the function. Using more meaningful names also helps a lot.
void read_matrix(int *rows, int *columns, int ***matrix) {
int i, j, r, c;
int **mat;
printf("n = ");
scanf("%d", &r);
printf("m = ");
scanf("%d", &c);
// Allocate space for a matrix (i.e. an array of r integer pointers).
mat = malloc(r * sizeof(int*));
// Allocate space for each row of the matrix (i.e. r arrays of c integers).
for (i = 0; i < r; i++)
mat[i] = malloc(c * sizeof(int));
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
printf("a[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
}
}
*rows = r;
*columns = c;
*matrix = mat;
}
Since we now moved the assignment of the values to the arguments at the end of the function, we got rid of all the annoying pointer dereference operators (*), and the code looks way cleaner.
You can see that what previously was:
(*a)[i] = (int*)malloc((*m) * sizeof(int));
now became:
mat[i] = malloc(c * sizeof(int));
Which is much easier to understand. This is allocating space for an array (a row of the matrix) holding c integers.
What previously was:
(*a) = (int**)malloc((*n) * sizeof(int*));
now became:
mat = malloc(r * sizeof(int*));
This is allocating an array of r integer pointers (which means a matrix of r rows, if each pointer points to a row).
You don't show how this function is called, but presumably it looks something like this:
int n, m;
int **matrix;
reading(&n, &m, &matrix);
So in this context, matrix is defined as a pointer-to-pointer. It can hold the address of the first element of an array of int *, each of which can hold the address of the first element of an array of int.
When &matrix is then passed to this function, you have a pointer-to-pointer-to-pointer, which is what the argument a of reading is. In this context, a contains a pointer to a single int **, specifically matrix in the calling function. By dereferecing a in reading, you're actually accessing matrix in the calling function.
So now getting to this line:
(*a) = (int**)malloc((*n) * sizeof(int*));
This allocates space for an array of *n int * and assigns that to *a, (i.e. matrix in the calling funtion. So now you have an array of int *. Now for this:
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
This loops through the elements of the int * array and assigns to each one a pointer to a memory block big enough for *m int.
So you now effectively have a 2D array of int. Note however that this is not the same as an actual 2D array of int which would be declared as int arr[n][m].
First, you are doing too many different things in a single function, which is making it a bit messy. I suggest that you separate out the logic to get the matrix size from the logic to create the matrix:
void get_size(int *n, int *m) {
printf("n=");
scanf("%d", n);
printf("m=");
scanf("%d", m);
}
int **create_matrix(int n, int m) {
int **matrix = malloc(n * sizeof(int*));
for (int i = 0; i < n; i++)
matrix[i] = malloc(m * sizeof(int));
return matrix;
}
void fill_matrix(int **matrix, int n, int m) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", [i][j]);
}
}
}
From here it is a lot easier to see what is going on, with fewer *s and &s.
Your matrix is implemented as an array of arrays, so
int **matrix = malloc(n * sizeof(int*));
allocates memory for the outer array, while
matrix[i] = malloc(m * sizeof(int));
allocates memory for each of the inner arrays.
int ***a declares a to be a pointer to a pointer to pointer to an int. The caller is required to have their own int ** and to pass its address to this function. For example, the caller might define int **x; and pass &x to this function for the parameter a. I will use x to refer to the caller’s int **.
(*a) = (int**)malloc((*n) * sizeof(int*)); sets the caller‘s pointer (x) to point to space for *n pointers to int. This is preparation for fabricating a matrix of *n rows—memory will be allocated for each row, and we will have a pointer to that memory, so we need n pointers.
Then these lines:
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
allocate memory for *n rows. The second line allocates memory for an array of m int and sets x[i] to point to the first element of that memory. Note that since a is an int ***, *a is an int **, and (*a)[i] is an int *. Thus, *a points to an array of int * elements.
Finally, these lines:
for (i = 0; i < *n; i++) {
for (j = 0; j < *m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", &(*a)[i][j]);
}
}
set each element of the *n by *m array: For each element x[i][j] (referred to as (*a)[i][j], it passes the address of the element (&(*a)[i][j]) to scanf to be set from the input stream.

Why does a pointer to a multidimensional array return segmentation fault when accessed after passing the pointer to a function?

So I don't really know what this problem is really called so searching and googling leads to different answers which does not answer my question.
This is the code:
#include <stdio.h>
#include <stdlib.h>
void gen_matrix(int **array, int rm, int cm) {
// int ** array;
int r, c;
array = (int **) malloc(sizeof(int *) * rm);
for (int r = 0; r < rm; ++r) {
array[r] = (int *) malloc(sizeof(int) * cm);
for (int c = 0; c < cm; ++c) {
array[r][c] = 1;
} // c
} // r
}// gen_matrix
int main() {
int **a;
gen_matrix(a, 2, 2);
printf("%d", a[0][0]);
return 0;
}
The problem is that printf() in main() returns Segmentation Fault. What I found out is that the address that the pointer a in main() points to does not change when malloc() is used inside gen_matrix().
In gen_matrix(), I can access the array just fine, but after I return to main(), the pointer a does not point to the array malloc() created.
Thank you.
You are losing the update to array when gen_matrix() returns, because you are not passing it the address of a. You could add an extra indirection level by passing in the address of a to gen_matrix(), but it would be cleaner to just have gen_matrix() return the malloced address and assign it to a in main():
int **gen_matrix(int rm, int cm) {
int ** array;
array = malloc(sizeof(*array) * rm);
for (int r = 0; r < rm; ++r) {
array[r] = malloc(sizeof(*(array[r])) * cm);
for (int c = 0; c < cm; ++c) {
array[r][c] = 1;
} // c
} // r
return array;
}// gen_matrix
int main() {
int **a;
a = gen_matrix(2, 2);
printf("%d", a[0][0]);
return 0;
}
Also, it's not a good idea to cast the return from malloc() and it is preferable to dereference the pointer the memory is being assigned to to get the proper size for sizeof().
And you should of course free() the memory before exiting.
When you call your function the parameter int ** array is the "array itself". What you need is a reference to it, either with one more level of pointer indirection or a C++-style reference. So, what you do is you modify the function to accept a triple-pointer:
void gen_matrix(int ** * array, int rm, int cm) {
and when you call it you also get the address of the "pointer to the matrix":
gen_matrix(&a, 2, 2);
of course you have to modify the code in the function to take care of that extra indirection:
*array = (int **) malloc(sizeof(int *) * rm);
and in the other two places as well.

Scanf Segfaults Outside of main()

I'm trying to generate a matrix of some arbitrary dimensions. I can do it just fine by calling scanf in main and then assigning matrix elements on a row by row basis, but trying to do it in a single function, outside of main, (and only if scanf() is called outside of main) gives me a segfault error:
int **genmat(int nrow, int ncol){
int i,j;
int **mat = (int**) malloc(sizeof(int)*ncol*nrow);
char rowbuff[16];
for(i=0; i < nrow; i++){
INPUT: scanf("%[^\n]%*c",rowbuff);
if(strlen(rowbuff) != ncol){
printf("Error: Input must be string of length %d\n", ncol);
goto INPUT;
}
else{
for(j=0; j < ncol; j++){
if(rowbuff[j] == '1'){
mat[i][j] = 1;
}
else{
mat[i][j] = 0;
}
}
}
}
return(mat);
}
The following works just fine:
int *genrow(int ncol, char *rowbuff){
int i;
int *row = malloc(sizeof(int)*ncol);
for(i=0;i<ncol;i++){
row[i] = rowbuff[i]%2;
}
return(row);
}
with the following in my main function to call genrow() for each row of the matrix:
for(i=0; i < row; i++){
INPUT: scanf("%[^\n]%*c",rowbuff);
if(strlen(rowbuff) != col){
printf("Error: Input must be string of length %d\n", col);
goto INPUT;
}
else{
int *newrow = genrow(col, rowbuff);
for(j=0; j < col; j++){
matrix[i][j] = newrow[j];
}
free(newrow);
newrow = NULL;
}
}
Why is the behavior different in these two contexts?
Dynamically allocated 2D arrays are unfortunately burdensome and ugly in C. To properly allocate one, it is very important that you do so with a single call to malloc, just as you tried to do. Otherwise it won't be a 2D array, but instead some segmented, slow look-up table.
However, the result of that malloc call will be a pointer to a 2D array, not a pointer-to-pointer. In fact, pointer-pointers have nothing to do with 2D arrays whatsoever - this is a widespread but incorrect belief.
What you should have done is this:
int (*mat)[nrow][ncol] = malloc( sizeof(int[nrow][ncol] );
This is an array pointer to a 2D array. This syntax is already a bit burdensome, but to make things worse, it is not easy to pass this array pointer back to main, because it is a local pointer variable. So you would need to use a pointer to an array pointer... and there's no pretty way to do that. It goes like this:
void genmat (size_t nrow, size_t ncol, int (**mat)[nrow][ncol] )
{
*mat = malloc( sizeof(int[nrow][ncol]) );
To ease usage a bit, you can create a temporary pointer to rows, which doesn't require multiple levels of indirection and is therefore much easier to work with:
int (*matrix)[ncol] = *mat[0]; // in the pointed-at 2D array, point at first row
for(size_t r=0; r<nrow; r++) // whatever you want to do with this matrix:
{
for(size_t c=0; c<ncol; c++)
{
matrix[r][c] = 1; // much more convenient syntax than (**mat)[r][c]
}
}
From main, you'll have to call the code like this:
size_t row = 3;
size_t col = 4;
int (*mat)[row][col];
genmat(row, col, &mat);
Example:
#include <stdio.h>
#include <stdlib.h>
void genmat (size_t nrow, size_t ncol, int (**mat)[nrow][ncol] )
{
*mat = malloc( sizeof(int[nrow][ncol]) );
int (*matrix)[ncol] = *mat[0];
for(size_t r=0; r<nrow; r++)
{
for(size_t c=0; c<ncol; c++)
{
matrix[r][c] = 1;
}
}
}
void printmat (size_t nrow, size_t ncol, int mat[nrow][ncol])
{
for(size_t r=0; r<nrow; r++)
{
for(size_t c=0; c<ncol; c++)
{
printf("%d ", mat[r][c]);
}
printf("\n");
}
}
int main (void)
{
size_t row = 3;
size_t col = 4;
int (*mat)[row][col];
genmat(row, col, &mat);
printmat(row, col, *mat);
free(mat);
return 0;
}
Please note that real code needs to address the case where malloc returns NULL.
I assume the problems is withint **mat = (int**) malloc(sizeof(int)*ncol*nrow);
You are trying to allocate the a 2D array right? But this isn't the correct method to allocate the memory. You can't allocate the whole chunk of memory one short.
What you should be doing here is, allocate the memory for all the rows(basically pointer to store the column address) and then for columns
int **mat= (int **)malloc(nrow * sizeof(int *));
for (i=0; i<nrow; i++)
mat[i] = (int *)malloc(ncol * sizeof(int));
Refer this link for more info http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/

Array of pointers as function argument

How do I feed an array of pointers as an argument to a function?
In the code below, if I want my function f to take an array of pointers int *x[], how should I declare x in main() and feed it as argument to f?
void f(int *x[]){
int data[5] = {1,2,3,4,5};
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}
int main(){
int *(x[]), k, l=5;
f(x); // this does not work
for(k=0; k<l; k++){
printf("x[%d] = %d\n", k, *x[k]);
}
}
return 0;
}
Writing f(x) does not work, and neither does f(x[]) or f(x[5]).
In fact, the declaration int *(x[]) is already not recognized by my compiler, while I thought that one could declare an array of pointers without specifying the length of the array.
In main, change
int *(x[])
to
int *x[SIZE]; // SIZE is array size
Note that, you can't declare a zero size array in C except when it is a last member of a structure.
After all, your code will invoke undefined behavior because the variable data is an automatic local variable and will not exist after function returns.
You may want this:
void f(int *x[]){
int *data = malloc(5*sizeof(int);
int temp[5] = {1,2,3,4,5};
memcpy(data, temp, 5*sizeof(int));
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}
First of all your code has no sense because you are trying to fill an array of pointers that will point to local variables. That is after exiti8ng the function all pointers will be invalid because original objects will be already destroyed.
The code could have a sense if the array in the function would have static storage duration
void f(int *x[]){
static int data[5] = {1,2,3,4,5};
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}
In main array x should be defined at least as
int * x[5];
int main(){
int * x[5], k;
f(x);
for ( k=0; k < 5; k++ ){
printf("x[%d] = %d\n", k, *x[k]);
}
}
return 0;
}
An alternate way to declare an array of pointer as a parameter is to use a pointer of pointer
void f(int **x, int size){
//code
}
However, you'll have to pass the size as a second argument if you want to avoid an overflow.
To call the code you'll just have to do something like this :
int *a[] = { NULL, NULL, NULL};
f(a, 3);

Resources