c- Allocate and Free 2D Array - c

I am trying to write 2 functions, one to Dynamic allocation a 2D array,Other to free this 2D array:
int allocate(int **array, unsigned int rows, unsigned int columns){
int i;
for (i = 0; i < rows; i++) {
array[i] = malloc(columns * sizeof (int));
}
/* Code fo fill the array*/
return 1;
}
void de_allocate(int **v, unsigned int rows) {
int i;
for (i = 0; i < rows; i++) {
free(v[i]);
}
free(v);
}
int main(int argc, char **argv) {
int rows, columns;
rows = atoi(argv[1]);
columns = atoi(argv[2]);
int *ipp[rows];
allocate(ipp, rows, columns);
de_allocate(ipp,rows);
return 0;
}
I must respect the allocate function signature :
int allocate(int **array, unsigned int rows, unsigned int columns)
And at the end of allocate function ipp must have access to allocated 2D array.
Allocate function it's right but in de_allocate function i have a SIGABRT Signal

The problem is that you are trying to free a stack allocated var with code free(v);
You could do that if you mallocated the array of pointer, but you declare it locally in main function with int *ipp[rows];
Change it to int **ipp = malloc(sizeof(int*)*rows); if you want to leave de_allocate as is.
You could test it with
#include <stdio.h>
#include <stdlib.h>
int allocate(int **array, unsigned int rows, unsigned int columns){
int i;
for (i = 0; i < rows; i++)
{
array[i] = malloc(columns * sizeof (int));
}
/* Code fo fill the array*/
return 1;
}
void de_allocate(int **v, unsigned int rows) {
int i;
for (i = 0; i < rows; i++)
{
free(v[i]);
}
free(v);
}
int main(int argc, char **argv)
{
int rows, columns;
int temp = 0;
rows = atoi(argv[1]);
columns = atoi(argv[2]);
int **ipp = malloc(sizeof(int*)*rows);
allocate(ipp, rows, columns);
for (int i=0; i<rows; i++)
for (int j=0; j<columns; j++)
ipp[i][j] = temp++;
for (int i=0; i<rows; i++)
for (int j=0; j<columns; j++)
printf("ipp[%d][%d] = %d\n", i, j, ipp[i][j]);
de_allocate(ipp,rows);
return 0;
}

void de_allocate(int **v, unsigned int rows) {
int i;
for (i = 0; i < rows; i++) {
free(v[i]);
}
free(v);
-----^----
here you are attempting to free a variable for which you didn't dynamically allocate memory in the first place
}

Related

Improve the time complexity of my implementation of Counting Sort (C)

Consider the following code:
#define SIZE 12
void randomize(int* array, int array_size);
void print(int* array, int array_size);
void counting_sort(int* array, int array_size);
int get_max(int* array, int array_size);
void construct(int* sorted, int sorted_array_size, int* values);
int main(void)
{
srand(time(NULL));
int* array = (int*)malloc(sizeof(int) * SIZE);
randomize(array, SIZE);
print(array, SIZE);
counting_sort(array, SIZE);
free(array);
return 0;
}
void randomize(int* array, int array_size) {...}
void print(int* array, int array_size) {...}
void counting_sort(int* array, int array_size) {
int minVal, maxVal;
int* sorted = (int*)malloc(sizeof(int) * SIZE);
maxVal = get_max(array, array_size);
int* values = (int*)malloc(maxVal * sizeof(int));
memset(values, 0, maxVal * sizeof(int));
for (int i = 0; i < array_size; i++) {
values[array[i]]++;
}
construct(sorted, SIZE, values);
free(values);
free(sorted);
}
int get_max(int* array, int array_size) {...}
void construct(int* sorted, int array_size, int* values) {
for (int i = 0, j = 0; i < array_size; i++) {
while (!values[++j]);
sorted[i] = j;
--values[j];
}
print(sorted, SIZE);
}
main() declares an array, the size of which is controlled by the macro SIZE. Then there are a few functions to randomize, print and find the max value of that array. After that is the implementation of Counting Sort itself, which uses the construct(..) function to create the sorted array. I've tested it a few times and couldn't find any bugs. However this bit right here is what I'm concerned about.
for (int i = 0, j = 0; i < array_size; i++) {
while (!values[++j]);...
We have 2 inner loops, and the variables in these loops are incremented. This means that the time complexity of the construct(...) function becomes quadratic, and not linear. The issue is that I can't figure out a good way to discard all of the 0 in values[]. Linear solutions are most welcome.
Added full code:
#include <stdlib.h>
#include <cassert>
#include <time.h>
#include <limits.h>
#include <string.h>
#define SIZE 160
void randomize(int* array, int array_size);
void print(int* array, int array_size);
void counting_sort(int* array, int array_size);
int get_max(int* array, int array_size);
void construct(int* sorted, int sorted_array_size, int* values);
int main(void)
{
srand(time(NULL));
int* array = (int*)malloc(sizeof(int) * SIZE);
randomize(array, SIZE);
print(array, SIZE);
counting_sort(array, SIZE);
free(array);
return 0;
}
void randomize(int* array, int array_size) {
for (int i = 0; i < array_size; i++) {
array[i] = rand() % array_size;
}
}
void print(int* array, int array_size) {
for (int i = 0; i < array_size; i++) {
printf("%4d ", array[i]);
}
putchar('\n');
}
void counting_sort(int* array, int array_size) {
int minVal, maxVal;
int* sorted = (int*)malloc(sizeof(int) * SIZE);
maxVal = get_max(array, array_size);
int* values = (int*)malloc(maxVal * sizeof(int));
memset(values, 0, maxVal * sizeof(int));
for (int i = 0; i < array_size; i++) {
values[array[i]]++;
}
construct(sorted, SIZE, values);
free(values);
free(sorted);
}
int get_max(int* array, int array_size) {
int max = INT_MIN;
for (int i = 0; i < array_size; i++) {
if (max < array[i]) {
max = array[i];
}
}
return max;
}
void construct(int* sorted, int array_size, int* values) {
for (int i = 0, j = 0; i < array_size; i++) {
while (!values[j]) {
++j;
}
sorted[i] = j;
--values[j];
}
print(sorted, SIZE);
}
Your implementation is linear. You have an inner while loop, but the value of j is never reset to 0, it keeps growing in each iteration of the for loop. Overall i will count from 0 to size and j will count from 0 to n.

How to change the content of a 2d array in C?

I am working on a problem where I have to transpose a matrix. I am passing the address of the original matrix, but once I execute the function it does not change!
I have tried to add a * infront of matrix in the transpose function, thinking that it will be pointing to the whole 2d array, but it did not work.
#include<stdio.h>
#include <stdlib.h>
void transpose(int *r,int *c, int **matrix);
void printMatrix(int r,int c, int **matrix){
for(int i=0;i<r;i++){
for(int j=0;j<c;j++)
printf("%2d ",matrix[i][j]);
printf("\n");
}
}
int main() {
int **matrix;
int r =3;
int c =2;
matrix = (int**) malloc(r*sizeof(int*));
for(int i=0;i<r;i++)
matrix[i] = (int*) malloc(c*sizeof(int));
for(int i=0;i<r;i++){
for(int j=0;j<c;j++)
matrix[i][j] = (3*i+2*j)%8+1;
}
printf("Before transpose:\n");
printMatrix(r,c,matrix);
transpose(&r, &c ,matrix);
printMatrix(r,c,matrix);
return 0;
}
void transpose(int *r,int *c, int **matrix){
int newR = *c;
int newC = *r;
int **newMatrix;
newMatrix = (int**) malloc(newR*(sizeof(int*)));
for(int i=0; i<newR;i++)
newMatrix[i] = (int*) malloc(newC*(sizeof(int)));
for(int i=0; i<newR; i++)
for(int j=0;j<newC;j++)
newMatrix[i][j] = matrix[j][i];
*c = newC;
*r = newR;
matrix = (int**) malloc((*r)*sizeof(int*));
for(int i=0;i<*r;i++)
matrix[i] = (int*) malloc((*c)*sizeof(int));
for(int i=0; i<newR; i++){
for(int j=0;j<newC;j++){
matrix[i][j] = newMatrix[i][j];
}
printf("\n");
}
}
I have this matrix
1 3
4 6
7 1
and want to get
1 4 7
3 6 1
however I am getting
1 3 0
1 4 0
It looks like all you forgot to do was actually use the transposed matrix. All I did was change the function signature and return the matrix you had already allocated and manipulated, and I got the output you were looking for.
#include <stdio.h>
#include <stdlib.h>
int** transpose(int *r,int *c, int **matrix);
void printMatrix(int r, int c, int **matrix) {
for (size_t i = 0; i < r; ++i){
for (size_t j = 0; j < c; ++j) {
printf("%2d ",matrix[i][j]);
}
printf("\n");
}
}
int main()
{
int r = 3;
int c = 2;
int **matrix = calloc(sizeof(int*), r);
for (size_t i = 0; i < r; ++i) {
matrix[i] = calloc(sizeof(int), c);
}
for (size_t i = 0; i < r; ++i) {
for (size_t j = 0; j < c; ++j) {
matrix[i][j] = (3 * i + 2 * j) % 8 + 1;
}
}
printf("Before transpose:\n");
printMatrix(r, c, matrix);
int** newMatrix = transpose(&r, &c ,matrix);
printMatrix(r, c, newMatrix);
return EXIT_SUCCESS;
}
int** transpose(int *r, int *c, int **matrix) {
int newR = *c;
int newC = *r;
int **newMatrix = calloc((sizeof(int*)), newR);
for (size_t i = 0; i < newR; ++i) {
newMatrix[i] = (int*) malloc(newC*(sizeof(int)));
}
for (size_t i = 0; i < newR; ++i) {
for (size_t j = 0; j < newC; ++j) {
newMatrix[i][j] = matrix[j][i];
}
}
*c = newC;
*r = newR;
matrix = calloc(sizeof(int*), *r);
for (size_t i = 0; i < *r; ++i) {
matrix[i] = calloc(sizeof(int), *c);
}
for (size_t i = 0; i < newR; ++i) {
for (size_t j = 0; j < newC; ++j) {
matrix[i][j] = newMatrix[i][j];
}
printf("\n");
}
return newMatrix;
}
Output:
1 4 7
3 6 1
I changed a few things, especially because I prefer using calloc over malloc, since it zeroes out the newly-allocated memory, and there is a dedicated parameter for the size of the requested memory, which I think semantically is a better idea.
As a side note, you don't have to cast the result of malloc in C. I tend to feel more strongly about that than other people, I think, because code noise, especially when you're working in C is one of the worst things you can do to yourself. This is a pretty good example of that, since all I did was reformat your code and the answer was right there. Don't be stingy with the whitespace, either; it really does make a difference.
Anyways, I hope this helped somewhat, even if you literally had basically everything done.
#include<stdio.h>
#include <stdlib.h>
void transpose(int *r,int *c, int ***matrix);
void printMatrix(int r,int c, int **matrix){
int i=0,j=0;
for(i=0;i<r;i++){
for(j=0;j<c;j++)
printf("%2d ",matrix[i][j]);
printf("\n");
}
}
int main() {
int **matrix;
int r =3;
int c =2;
int i=0,j=0;
matrix = (int**) malloc(r*sizeof(int*));
for(i=0;i<r;i++)
matrix[i] = (int*) malloc(c*sizeof(int));
for(i=0;i<r;i++){
for(j=0;j<c;j++)
matrix[i][j] = (3*i+2*j)%8+1;
}
printf("Before transpose:\n");
printMatrix(r,c,matrix);
transpose(&r, &c, &matrix);
printMatrix(r,c,matrix);
return 0;
}
void transpose(int *r,int *c, int ***matrix){
int newR = *c;
int newC = *r;
int **newMatrix;
int i=0,j=0;
newMatrix = (int**) malloc(newR*(sizeof(int*)));
for(i=0; i<newR;i++)
newMatrix[i] = (int*) malloc(newC*(sizeof(int)));
for(i=0; i<newR; i++)
for(j=0;j<newC;j++) {
newMatrix[i][j] = (*matrix)[j][i];
}
*c = newC;
*r = newR;
// free matrix..
*matrix = newMatrix;
/*matrix = (int**) malloc((*r)*sizeof(int*));
for(i=0;i<*r;i++)
matrix[i] = (int*) malloc((*c)*sizeof(int));
for(i=0; i<newR; i++){
for(j=0;j<newC;j++){
matrix[i][j] = newMatrix[i][j];
}
printf("\n");
}*/
}

pass matrix by reference and scan values

I'm trying to scan values into a matrix that is passed by reference to a function and that's not compiled.
What's wrong?
I think the problem is in line of scanf but I don't know how to fix it.
#include <stdio.h>
#include <stdlib.h>
int** initMatrix(int lines, int columns) {
int i;
int** matrix;
matrix = (int**) calloc(lines, sizeof(int*));
for (i = 0; i < lines; i++) {
matrix[i] = (int*) calloc(columns, sizeof(int));
}
return matrix;
}
void fillMatrixValues(int*** matrixA, int lines, int columns) {
int i, j;
for (i = 0; i < lines; i++) {
for (j = 0; j < columns; j++) {
scanf("%d", matrixA[i][j]);
}
}
}
void printMatrix(int** matrix, int lines, int columns) {
int i, j;
for (i = 0; i < lines; i++) {
for (j = 0; j < columns; j++) {
printf("%d\t", matrix[i][j]);
}
printf("\n");
}
}
void main() {
int** matrixA;
int lines = 2, columns = 2;
matrixA = initMatrix(lines, columns);
fillMatrixValues(&matrixA, lines, columns);
printMatrix(matrixA, lines, columns);
}
void main -> undefined behaviour
Use
int main(void)
or
int main(int argc, char ** argv)
You should check return value of scanf
if (scanf("%d", matrixA[i][j]) != 1)
{
// failed
}
Next problem
void fillMatrixValues(int ***matrixA, int lines, int columns)
fillMatrixValues(&matrixA, lines, columns)
to
void fillMatrixValues(int **matrixA, int lines, int columns)
fillMatrixValues(matrixA, lines, columns)

Function pointer in argument in C

I have to do an exercise where I have a certain numbers of functions and every function do a different thing like sort all the negative numbers from the array.
Moreover I have to create a function display with 3 argument pointers to an array, size of it and a name of a function which receives int and that the issue is int (Function pointer). I try to do this but this don't work and I don't know what to do in order to do correctly this exercise with a function pointer, because I don't understand that.
This is my code
int main (int argc, char **argv)
{
srand (time (NULL));
int arr[MAX_SIZE], second_arr[MAX_SIZE], i;
random_arr (arr);
display (arr, 20, negative_number (arr, second_arr));
system ("PAUSE");
return 0;
}
void random_arr (int *my_arr)
{
int i;
for (i = 0; i < MAX_SIZE; i++) {
*(my_arr + i) = i - 10;
}
}
int negative_number (int *arr, int *sort_arr)
{
int i;
for (i = 0; i < 20; i++) {
if (arr[i] < 0) {
sort_arr[i] = arr[i];
}
}
return sort_arr;
}
void diplay (int *arr, int size, int (*a_function) (int, int))
{
int i = 0;
for (i = 0; i < size; i++) {
printf ("%d\n", a_function);
}
}
It might be different from your intentions because your intentions is not clear.
but I think this would be helpful
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_SIZE 20
void random_arr (int size, int *my_arr);
int negative_number (int size, int *arr, int *sort_arr);
void display (int *arr, int size, int (*filter_function) (int in_size, int *in_array, int *out_array));
int main (void){
int arr[MAX_SIZE], second_arr[MAX_SIZE], i;
srand(time(NULL));
random_arr(MAX_SIZE, arr);
for(i = 0; i < MAX_SIZE; ++i)
printf("%d ", arr[i]);
puts("");
display (arr, MAX_SIZE, negative_number);
system ("PAUSE");
return 0;
}
void random_arr (int size, int *my_arr){
int i;
for (i = 0; i < size; i++) {
my_arr[i] = rand()%MAX_SIZE - MAX_SIZE/2;
}
}
int negative_number (int size, int *arr, int *sort_arr){
int i, j = 0;
for (i = 0; i < size; i++) {
if (arr[i] < 0) {
sort_arr[j++] = arr[i];
}
}
return j;//new array size
}
void display (int *arr, int size, int (*filter)(int in_size, int *in_array, int *out_array)){
int i = 0;
int *out = malloc(size * sizeof(*out));
int out_size = filter(size, arr, out);
for (i = 0; i < out_size; i++) {
printf ("%d\n", out[i]);
}
free(out);
}

crash on trying to reallocate a pointer using pointer to this pointer

I have a pointer to a pointer ("paths") and I want to reallocate each pointer (each "path"). But I get a crash. Generally I am trying to find all possible powers of a number, which one can compute for some amount of operations (e.g for two operations we can get power of three and four (one operation for square of a number, then another one either for power of three or four)). I figured out how to do it on paper, now I am trying to implement it in code. Here is my try:
#include <stdio.h>
#include <stdlib.h>
void print_path(const int *path, int path_length);
int main(void)
{
fputs("Enter number of operations? ", stdout);
int operations;
scanf("%i", &operations);
int **paths, *path, npaths, npath;
npaths = npath = 2;
path = (int*)malloc(npath * sizeof(int));
paths = (int**)malloc(npaths * sizeof(path));
int i;
for (i = 0; i < npaths; ++i) // paths initialization
{
int j;
for (j = 0; j < npath; ++j)
paths[i][j] = j+1;
}
for (i = 0; i < npaths; ++i) // prints the paths, all of them are displayed correctly
print_path(paths[i], npath);
for (i = 1; i < operations; ++i)
{
int j;
for (j = 0; j < npaths; ++j) // here I am trying to do it
{
puts("trying to reallocate");
int *ptemp = (int*)realloc(paths[j], (npath + 1) * sizeof(int));
puts("reallocated"); // tried to write paths[j] = (int*)realloc...
paths[j] = ptemp; // then tried to make it with temp pointer
}
puts("memory reallocated");
++npath;
npaths *= npath; // not sure about the end of the loop
paths = (int**)realloc(paths, npaths * sizeof(path));
for (j = 0; j < npaths; ++j)
paths[j][npath-1] = paths[j][npath-2] + paths[j][j];
for (j = 0; j < npaths; ++j)
print_path(paths[j], npath);
puts("\n");
}
int c;
puts("Enter e to continue");
while ((c = getchar()) != 'e');
return 0;
}
void print_path(const int *p, int pl)
{
int i;
for (i = 0; i < pl; ++i)
printf(" A^%i -> ", p[i]);
puts(" over");
}
I am not sure the problem resides with the call to realloc(), rather you are attempting to write to locations for which you have not created space...
Although you create memory for the pointers, no space is created (allocate memory) for the actual storage locations.
Here is an example of a function to allocate memory for a 2D array of int:
int ** Create2D(int **arr, int cols, int rows)
{
int space = cols*rows;
int y;
arr = calloc(space, sizeof(int));
for(y=0;y<cols;y++)
{
arr[y] = calloc(rows, sizeof(int));
}
return arr;
}
void free2DInt(int **arr, int cols)
{
int i;
for(i=0;i<cols; i++)
if(arr[i]) free(arr[i]);
free(arr);
}
Use example:
#include <ansi_c.h>
int main(void)
{
int **array=0, i, j;
array = Create2D(array, 5, 4);
for(i=0;i<5;i++)
for(j=0;j<4;j++)
array[i][j]=i*j; //example values for illustration
free2DInt(array, 5);
return 0;
}
Another point here is that it is rarely a good idea to cast the return of [m][c][re]alloc() functions
EDIT
This illustration shows my run of your code, just as you have presented it:
At the time of error, i==0 & j==0. The pointer at location paths[0][0] is uninitialized.
EDIT 2
To reallocate a 2 dimension array of int, you could use something like:
int ** Realloc2D(int **arr, int cols, int rows)
{
int space = cols*rows;
int y;
arr = realloc(arr, space*sizeof(int));
for(y=0;y<cols;y++)
{
arr[y] = calloc(rows, sizeof(int));
}
return arr;
}
And here is a test function demonstrating how it works:
#include <stdio.h>
#include <stdlib.h>
int ** Create2D(int **arr, int cols, int rows);
void free2DInt(int **arr, int cols);
int ** Realloc2D(int **arr, int cols, int rows);
int main(void)
{
int **paths = {0};
int i, j;
int col = 5;
int row = 8;
paths = Create2D(paths, col, row);
for(i=0;i<5;i++)
{
for(j=0;j<8;j++)
{
paths[i][j]=i*j;
}
}
j=0;
for(i=0;i<5;i++)
{
for(j=0;j<8;j++)
{
printf("%d ", paths[i][j]);
}
printf("\n");
}
//reallocation:
col = 20;
row = 25;
paths = Realloc2D(paths, col, row);
for(i=0;i<20;i++)
{
for(j=0;j<25;j++)
{
paths[i][j]=i*j;
}
}
j=0;
for(i=0;i<20;i++)
{
for(j=0;j<25;j++)
{
printf("%d ", paths[i][j]);
}
printf("\n");
}
free2DInt(paths, col);
getchar();
return 0;
}
The realloc() does not fail. What fails is that you haven't allocated memory for the new pointers between paths[previous_npaths] and paths[new_npaths-1], before writing to these arrays in the loop for (j = 0; j < npaths; ++j).

Resources