I want to use this code in a more complex problem, but I didn't get it to work. Why isn't my matrix getting printed?
#include <stdio.h>
#include <stdlib.h>
void print_mat(int **a, int n)
{
printf("\n");
int k,t;
for (k=1;k<=n;k++)
{
for (t=1;t<=n;t++)
printf("%d ", a[k][t]);
printf("\n");
}
}
int main()
{
int i,j,n,**a;
printf("Chess board size=");
scanf("%d", &n);
a=(int **)malloc(n*sizeof(int));
for (i=1;i<=n;i++)
a[i]=(int*)malloc(n*sizeof(int));
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
a[i][j]=-1;
print_mat(a,n);
return 0;
}
You should first malloc for size of int * not int , change
a = ( int ** )malloc( n * sizeof( int ) );
to
a = malloc( n * sizeof( int* ) ); //also no need to cast.
Also, as #Russell Borogove suggested, change loop as for( i = 0; i < n; i++ ) instead of from 1 to n.
You will want to get in the habit of using zero-based indexes with C arrays, and display them as if they were 1-based only when presenting things to users.
Change your for (i=1;i<=n;i++) loops to for (i=0;i<n;i++). Likewise with j, k, and t.
As currently written, a[n] isn't an allocated pointer, and a[0][n] isn't within the a[0] buffer allocation. The result (gcc 4.2.1 on OSX 10.7.5) is a program crash.
The line
a=(int **)malloc(n*sizeof(int));
should read
a=malloc(n*sizeof(int *));
a=(int **)malloc(n*sizeof(int));
change to a= mallo(n*sizeof(int*))
On some systems int and int* (pointers) can have same size but here may be this is creating the problem.
Also
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
a[i][j]=-1;
change it to
for (i=0;i<n;i++)
for (j=0;j<n;j++)
a[i][j]=-1;
Related
I want my array to be global but i get my variables with scanf().
#include <stdio.h>
int m, n;
int main (void){
scanf("%d", &m);
scanf("%d", &n);
int array[m][n];
make_arr(array); //initializes array with random numbers
}
So what is the solution?
Edit: i use the solution of Farbod Shahinfar but i can't use it with my function:
void make_arr (int array[m][n] ){
int i , j ;
srand(time(NULL));
for(i=0;i<m;i++)
for(j=0;j<n;j++)
array[i][j] = rand() % 2;
What should i do?
You can declare a global pointer to an array and set it when you have scanned the input.
#include <stdio.h>
#include <stdlib.h>
int **array;
int m,n;
int main(void)
{
scanf("%d", &m);
scanf("%d", &n);
array = malloc(sizeof(int *) * m);
for (int i = 0; i < m; i++)
array[i] = malloc(sizeof(int) * n);
make_array(array);
// your other codes
// ....
for (int i = 0; i < m; i++)
free(array[i]);
free(array);
}
Memory allocated using malloc must be freed otherwise your program will have memory leakage problem.
Answer to the edit section:
You have declared a parameter for your make_arr function with the same name of the global variable this parameter will hide the global variable.
For clarification, if you declare a global variable you do not need to pass it as argument to a function.
void make_arr ()
{
int i , j ;
srand(time(NULL));
for(i=0;i<m;i++)
for(j=0;j<n;j++)
array[i][j] = rand() % 2;
// ....
}
Another approach is to pass the array to your function. This way you do not need the global variable at all. A possible function signature can be as below
void make_arr (int **array)
{
int i , j ;
srand(time(NULL));
for(i=0;i<m;i++)
for(j=0;j<n;j++)
array[i][j] = rand() % 2;
// ....
}
As Andrew Henle pointed out there is an awesome post on StackOverflow showing the right way of allocating multi-dimensional arrays. I have to confess that I did not knew about it.
Correctly allocating multi-dimensional arrays
Thanks to Andrew Henle for his constructive and useful comment
A note about malloc (Do read man page)
Malloc allocates memory from heap. You should check the man page of malloc for more information.
The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.
First, given the variable-length array
int array[m][n];
your void make_arr( int array[m][n] ) won't work with int **array because int **array is not an actual 2-dimensional array. int **array is a pointer to an array of pointers to multiple and completely separate one-dimensional arrays. Such a construct is simply incompatible with being treated as an actual array.
And you can't give int array[m][n]; global scope because it's variable-length, and global variables are static (unchanging, not necessarily C's static) and have to be fixed-size.
And you can't use something like a typedef to create an "array type", because that's a compile-time definition and the array is "sized" at run time.
So you need to allocate the array dynamically, but the global variable use to access the array won't have sizing information associated with it.
The global variable pretty much has to be a void *.
To access the array, you have to create a pointer at run-time to a VLA and assign the global void * to that pointer.
This would work (note that the local pointer has to be dereferenced to access the array):
#include <stdlib.h>
void *array;
int m;
int n;
// create the array, assumes both
// m and n are already set
void createArray()
{
int ( *localArrayPtr )[m][n] = malloc( sizeof( *localArrayPtr ) );
array = localArrayPtr;
}
void fillArray( void )
{
int ( *localArrayPtr )[m][n] = array;
for ( int ii = 0; ii < m; ii++ )
{
for ( int jj = 0; jj < n; jj++ )
{
( *localArrayPtr )[ ii ][ jj ] = rand();
}
}
}
void someOtherFunc( void )
{
int ( *localArrayPtr )[m][n] = array;
( *localArrayPtr )[ x ][ y ] = ...;
}
As an exercise, it works. Forcing a VLA to have global scope, though, causes accessing the array to be more complex than necessary, adding to existing problems with using globally-scoped variables.
It's probably a lot better from both a scope and code complexity perspective to just pass the array to functions via arguments, such as void someFunc( int m, int n, int array[ m ][ n ] ) { ... }. Accessing elements would then just be in the form array[ x ][ y ].
You could create "getter" and "setter" functions to hide the complexity:
int getElement( int x, int y )
{
int ( *localArrayPtr )[m][n] = array;
return( ( *localArrayPtr )[ x ][ y ] );
}
void setElement( int x, int y, int value )
{
int ( *localArrayPtr )[m][n] = array;
( *localArrayPtr )[ x ][ y ] = value;
}
A good optimizing compiler would likely inline those.
As mentioned by Nate you can create a global pointer and then allocate memory to it using "malloc()"
#include<stdio.h>
#include<stdlib.h>
int *array;
int main() {
int m, n;
scanf("%d", &m);
scanf("%d", &n);
array = malloc(sizeOf(int) * m * n);
return 0;
}
And you can also ref this blog here:
I'm trying to code a function that would ask the user to enter matrix. It prompts the number of lines, the number of columns and then prompts the value for each element of the matrix:
#include <stdio.h>
#include <stdlib.h>
void enterMatrix(float ** matrix, int nbLines, int nbColumns){
for (int i = 0; i < nbLines * nbColumns; i++){
printf("i = %d? ", i);
scanf("%f", matrix[i]);
}
}
int main(void){
int nbLines, nbColumns;
printf("nbLines? "); scanf("%d", &nbLines);
printf("nbColumns? "); scanf("%d", &nbColumns);
float *matrix[nbL * nbCol];
enterMatrix(matrix, nbLines, nbColumns);
}
Everything works fine until I enter a value for i = 0 and then press enter, which leads to a segmentation fault.
Any idea as to what could be wrong?
Your problem is because
float *matrice[nbL * nbCol];
defines an array of uninitialised pointers (i.e. an array of float *), not an array of float. This is then passed to enterMatrix() as a pointer to pointer to float (i.e. a float **). The scanf() calls then read to matrix[i] which is an uninitialised pointer. The result is undefined behaviour.
One fix would be to change the definition of matrice in main() to
float matrice[nbL * nbCol];
and change the function to (I've used comment to highlight changes)
void enterMatrix(float *matrix, int nbLines, int nbColumns) /* note type of matrix */
{
for (int i = 0; i < nbLines * nbColumns; i++)
{
printf("i = %d? ", i);
scanf("%f", &matrix[i]); /* note what the second argument is */
}
}
You need to allocate memory dinamically since you do not know at compile time which values the variables nbLines and nbColumns will hold.
So you need to first declare the pointer to the matrix:
float **matrix;
Then start allocate memory according to user input:
matrix = (float **)malloc(nbLines * sizeof(float *));
for (int i = 0; i < nbLines; i++)
{
matrix[i] = (float *)malloc(nbColums * sizeof(float ));
}
The segmentation fault error happens becouse you are not allocating memory for your matrix, but just a [nbL * nbCol] pointers to float
You don't allocate enough memory for your array, thus you invoke Undefined Behavior, since you go out of bounds, causing a Segmentation fault.
You could declare it like a 2D array, like this:
/* TODO: Check if allocation succeeded. (check for NULL pointer) */
float** matrix;
matrix = malloc(nbLines * sizeof(float*));
for(int i = 0 ; i < N ; i++)
matrix[i] = malloc(nbColumns * sizeof(float));
I have other approaches for allocating a 2D array dynamically here.
Please note: Do I cast the result of malloc? No!
Also do not forget to free().
You could emulate a 2D array with an 1D array, like this:
void enterMatrix(float* matrix, int nbLines, int nbColumns){
for (int i = 0; i < nbLines ; i++) {
for (int j = 0; j < nbColumns; j++) {
scanf("%f", matrix[i + nbColumns * j]);
}
}
float matrix[nbLines * nbColumns];
You're creating a variable length array, and, of pointers.
While other answers are perfectly valid, if you really want a 2D array, you just need to change the declaration:
float matrix[nbLines][nbColumns];
to declare a 2D variable length array of floats.
Now the hard point is to pass this VLA to a function and preserve dimensions.
For that you could use C99 way of passing VLAs (note that dimensions must be located before the VLA itself). Reference: Passing a multidimensional variable length array to a function:
void enterMatrix(int nbLines, int nbColumns, float matrix[][nbColumns] ){
for (int i = 0; i < nbLines; i++){
for (int j = 0; j < nbColumns; j++)
{
scanf("%f", &matrix[i][j]);
}
}
}
call as follows:
enterMatrix(nbLines, nbColumns, matrix);
So I have a program in C structured in 3 files: main.c, alloc.h and alloc.c. In the main.c function, I have the declaration of a pointer to another pointer to which I intend to alloc an n * m array:
#include <stdio.h>
#include <stdlib.h>
#include "alloc.h"
int main() {
int **mat, n, m;
alloc_matrix(&mat, int &n, int &m);
return 0;
}
In alloc.c I have the following declarations:
#ifndef ALLOC_H_INCLUDED
#define ALLOC_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
void alloc_matrix(int***, int*, int*);
#endif
In alloc.c I have the function:
void alloc_matrix(int ***mat, int *n, int *m) {
printf("\nn = "); scanf("%d", n);
printf("\nm = "); scanf("%d", m);
*mat = (int**)calloc(*n, sizeof(int*));
int i;
for (i = 0; i < *n; i++)
*(mat + i) = (int*)calloc(*m, sizeof(int));
}
But the program doesn't work. It enters some kind of loop and doesn't end.
If I allocate it in main it would work but I have no idea what I am doing wrong in the alloc function.
Here is the correct code. Your error was that in the definition of alloc_matrix, you used *(mat+i) in the allocation loop, which should be *(*mat+i) as, mat is a int*** so the base address for the 2D array would be in *mat. Then you need to move by offset i and then de-reference that memory location for the 1D array.
Main:
#include <stdio.h>
#include <stdlib.h>
#include "alloc.h"
int main()
{
int **mat,n,m;
alloc_matrix(&mat,&n,&m);
return 0;
}
alloc.h
#ifndef ALLOC_H_INCLUDED
#define ALLOC_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
void alloc_matrix(int***,int*,int*);
#endif
alloc.c :
void alloc_matrix(int ***mat,int *n,int *m)
{
printf("\nn = "); scanf("%d", n);
printf("\nm = "); scanf("%d", m);
*mat = (int**)calloc(*n,sizeof(int*));
int i;
for(i = 0; i < *n; i++)
*(*mat+i) = (int*)calloc(*m,sizeof(int));
}
The code for the read function :
void read_matrix(int ***mat,int n,int m)
{
int i,j;
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
{
printf("mat[%d][%d] = ", i, j);
scanf("%d", (*(*mat+i))+j);
}
}
The problem with it is that it only reads the first row and the it freezes.
void alloc_matrix(int ***mat,int *n,int *m)
There are two problems in this line. Neither is fatal but both are worth fixing.
First problem: A matrix in this program is represented as an int**. Why does alloc_matrix accept an int***? All standard functions that allocate something (malloc and friends) return a pointer to that something. This is an idiomatic way of doing things in C. It reduces your star count (being a three-star C programmer is not an achievement to be proud of) and simplifies the code. The function should be changed to
int** alloc_matrix( // but what's inside the () ?
The second problem is, why should a function called alloc_matrix prompt the user and read values? These things are not related to allocation. A function should do one thing and do it well. Does malloc prompts you to enter the size? Does fopen prompt you to enter the filename? These things would be regarded as nonsense of the first degree, and rightly so. It is advised to read the sizes elsewhere and pass them to alloc_matrix as input arguments. Hence,
int** alloc_matrix(int n, int m) { // but what's inside the {}?
What remains of alloc_matrix is simple:
int** alloc_matrix(int n, int m) {
int** mat; // that's what we will return
int i;
mat = (int**)calloc(n, sizeof(int*));
for(i = 0; i < n; i++)
// here comes the important part.
Since we have simplified alloc_matrixand reduced the star count in mat, what should we do with the old body of the loop? It was:
*(mat+i) = (int*)calloc(...);
but if we remove a star, it becomes
(mat+i) = (int*)calloc(...);
which is an obvious nonsense. Perhaps the old line was a problem. The fact that it provoked a compiler warning certainly doesn't speak for its correctness. So how to correct it? There aren't too many options. It turns out that in order to restore sanity, we must leave the old left-hand side (written for the three-star mat) intact. Or, better still, use an equivalent but more idiomatic notation:
mat[i] = (int*)calloc(m, sizeof(int));
So the entire function now becomes
int** alloc_matrix(int n, int m) {
int **mat;
int i;
mat = (int**)calloc(n, sizeof(int*));
for(i = 0; i < n; i++)
mat[i] = (int*)calloc(m, sizeof(int));
return mat;
}
and it should be called like
mat = alloc_matrix(n, m);
It is often said that one should not cast the result of calloc and friends. But in this case the cast has enabled a warning which helped to find a bug. I'm leaving the casts in place for now.
There is another idiom for the allocation that does not require the cast, but also avoids the problem of types not matching.
Instead of using the type for the sizeof, you can use the dereferenced pointer as the type information is available in the variable:
mat = (int**)calloc(n, sizeof(int*));
can be changed to
mat = calloc(n, sizeof *mat); //sizeof is an operator not a function
I'm working on this quite simple C program, wich builds an histogram from an array. What it does in particular, is writing on a second array the ciphres of the first array, followed by the number of their occurences. For instance: if the array A is {2,3,2,5,6,6,6} the array histogram of A, will be {2,2,3,1,5,1,6,3}. Ok, so my program compiles well and there aren't any warnings or errors. But the program stops working after i' ve inserted the values of array A. Where am i failing??? Thank you!!
typedef unsigned short int boolean;
#define TRUE 1
#define FALSE 0
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <conio.h>
boolean Array_Histogram(int *A, int N, int **H, int *count){
int i,j;
boolean found;
*H = (int *) malloc( sizeof(int)*2*N );
if(*H==NULL)
return FALSE;
(*count)=0;
for(i=0;i<N;i++){
found=FALSE;
j=0;
while(found==FALSE && j<(*count)*2){
if(A[i]==(*H[j]))
found=TRUE;
else j+=2;
}
if(found==TRUE){
(*H)[j+1]++;
}
else{
(*H)[j] = A[i];
(*H)[j+1] = 1;
(*count) ++;
}
}
return TRUE;
}
int main(){
int N;
int count;
int *A;
int **H;
int *i;
i=0;
printf("Inserisci N, dimensione dell'array A:");
scanf("%d", &N);
if(N<=0){
return 0;
}
A= (int*) malloc (sizeof(int)*N);
*H = (int *) malloc( sizeof(int)*2*N );
for(count=0;count<N;count++){
printf("\n Inserisci il valore %d di A:", count);
scanf("%d", &A[count]);
}
Array_Histogram(A,N,H,i);
printf("\nI valori dell'istogramma sono:");
for(count=0;count<2*N;count++)
printf("\n %d", (*H)[count]);
return 0;
}
The variable H in main is of the wrong type. It should be declared:
int *H;
You need to change 2 more lines in main with regards to this:
H = malloc( sizeof(int)*2*N );
and
Array_Histogram(A,N,&H,i);
Also, you need to allocate H only once.
I am not really sure what are you trying to achieve but your problem is de-referencing null pointer.
H is double pointer to integer. so you have to allocate memory to H using malloc before using *H
int **H;
*H = malloc( sizeof(int)*2*N );
Edit:
Suggest you to read some basics about pointer here
You are allocating memory for H twice(once in main, once in the func).
H is declared as int **, memory is being allocated to 2*N elements of integer pointers each, which is probably not what you wanted to do.
If you just want output as {2,2, 3,1..}, then probably you just want a int *H;
Consider this code:
#include <stdio.h>
#define N 5
void printMatrix(int (*matrix)[N],int n)
{
int i,j;
for(i=0;i<n;i++){
for(j=0;j<n;j++)
printf("%d",matrix[i][j]);
printf("\n");
}
}
int main()
{
int R[N][N]={{1,2,3},{4,5,6},{7,8,9}};
printMatrix(R,3);
}
This works fine as expected.
Now, I thought to write the functions handling 2D-matrices in a separate source file and link them wherever required.
But then I ran into a problem as in the function printMatrix, the size of array of int to which matrix points (i.e N) is required at compile-time. So, my functions would not work in other cases when the size is different.
So,How can I handle this?
Dynamic Arrays are a solution but i want to know if it can be done with static arrays.
You can't use the built-in 2D array type if both sizes are not known at compile time. A built-in 2D array must have at least one of the two sizes known at compile time.
If both sizes are run-time values, then you have no other choice but to use a "manual" implementation of 2D array, like an array of pointers to arrays, for example. In that case the function declaration might look as follows (two alternative equivalent forms)
void printMatrix(int *const *matrix, int n, int m);
void printMatrix(int *const matrix[], int n, int m);
To access to the array elements you can still use the "traditional" syntax
matrix[i][j]
The array itself would be created as follows (a simple example)
int row0[] = { 1, 2, 3 };
int row1[] = { 4, 5, 6 };
int *matrix[2];
matrix[0] = row0;
matrix[1] = row1;
printMatrix(matrix, 2, 3);
But if you already have a matrix implemented as a built-in 2d array
int matrix[2][3] = { ... };
then just to be able to pass it to the above function you can "convert" it into the above form by using an additional temporary "row pointer" array
int *rows[2];
rows[0] = matrix[0];
rows[1] = matrix[1];
printMatrix(rows, 2, 3);
Write yourself a macro:
#define MAT(i,j) matrix[i*n + j];
and declare "matrix" as a simple pointer to an "int".
Calculate the array index yourself. This will handle an arbitrary two dimensional array, for example:
void printMatrix(int *matrix,int n, int m)
{
int i,j;
for(i=0;i<n;i++){
for(j=0;j<m;j++)
printf("%d",matrix[m * i + j]);
printf("\n");
}
}
Don't try to pass it as a 2-D array; pass a pointer to the first element, then compute offsets manually:
void printMatrix(int *a, size_t m, size_t n)
{
size_t i,j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("a[%lu][%lu] = %d\n",
(unsigned long) i,
(unsigned long) j,
a[i*n+j]); // treat a as 1-d array, compute offset manually
}
}
}
int main(void)
{
int arr[5][4];
...
printMatrix(&arr[0][0], 5, 4);
...
}
Granted, this will only work for contiguously allocated arrays.
Although the syntax is not exactly the same, but this also happens to work a bit:
#include <stdio.h>
#define N 5
void printMatrix(int* row,int n,int sz)
{
int i,j;
int *currRow;
for(i=0;i<n;i++){
currRow = row+i*sz;
for(j=0;j<n;j++)
printf("%d",currRow[j]);
printf("\n");
}
}
int main()
{
int R[N][N]={{1,2,3},{4,5,6},{7,8,9}};
printMatrix(R[0],3,sizeof(R[0])/sizeof(int));
}