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).
Related
I have a problem returning dynamic array pointer with function parameter. I get segfault
#include <stdio.h>
#include <stdlib.h>
void createArray(int *ptr, int n)
{
ptr = malloc(n * sizeof(int));
for(int i = 1; i <= n; ++i)
{
*(ptr + (i - 1)) = i*i;
}
}
int main() {
int *array = NULL;
int n = 5;
createArray(array, n);
for(int i = 0; i < n; ++i)
{
printf("%d", array[i]);
}
return 0;
}
I have to fill my array with i*i, when I is from 1 to n.
I don't get any errors or warnings. Just message about segmentation fault. Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
Memory must be allocate in the calling function, but not in called.
This variant works:
#include <stdio.h>
#include <stdlib.h>
void createArray(int *ptr, int n){
int i;
for(i = 1; i <= n; i++) {
*(ptr + (i - 1)) = i*i;
// fprintf(stdout,"%d %d\n", i, *(ptr + (i -1)));fflush(stdout);
}
}
int main() {
int i, n, *array = NULL;
void *pvc;
n = 5;
array = (int *)malloc(n * sizeof(int));
createArray(array, n);
for(i = 0; i < n; i++) {
fprintf(stdout,"%d %d\n", i, array[i]);fflush(stdout);
}
pvc = (void *)array;
free(pvc);
return 0;
}
You can change pointer through function parameters like this:
void createArray(int **ptr, int n)
{
*ptr = malloc(n * sizeof(int));
for(int i = 1; i <= n; ++i)
{
(*ptr)[i - 1] = i*i;
}
}
int main() {
int *array = NULL;
int n = 5;
createArray(&array, n);
Remember to call function like this: createArray(&array, n);
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");
}*/
}
I need to implement a matrix_create function that receives a triple pointer.
It compiles well, but when I run it I get the Segmentation Fault error, probably because I messed up somewhere in the memory allocation.
But I cannot find my mistake.
The code
#include <stdio.h>
#include <stdlib.h>
int matrix_create(int ***m, int ze, int sp);
void matrix_init(int **m, int ze, int sp);
int main (void)
{
int ze = 3;
int sp = 3;
int i,j;
int ***m = malloc(sizeof(int**));
*m = malloc(ze * sizeof(int*));
matrix_create(m, ze, sp);
matrix_init(*m, ze, sp);
for(i = 0; i < ze; ++i) {
for(j = 0; j < sp; ++j)
printf("%i\n", *m[i][j]);
}
return 0;
}
int matrix_create(int ***m, int ze, int sp)
{
int i, k;
if (!*m)
return 0;
for (i = 0; i < ze; ++i) {
*m[i] = malloc(sp * sizeof(int));
if (!*m[i]) {
for (k = 0; k < i; ++k)
free(*m[k]);
free(*m);
return 0;
}
}
return 1;
}
void matrix_init(int **m, int ze, int sp)
{
int i,j;
for(i = 0; i < ze; ++i) {
for(j = 0; j < sp; ++j)
m[i][j] = rand() % 1000;
}
}
The index operator [] takes precedence over the indirection operator *. See C Operator Precedence.
This means you have to change
*m[i]
to
(*m)[i]
in the function matrix_create:
(*m)[i] = malloc(sp * sizeof(int));
if (!(*m)[i]) {
.....
}
and in the main program:
printf("%i\n", (*m)[i][j]);
So I read dozens of examples of passing an 2D array pointer to function to get/change values of that array in function. But is it possible to create (allocate memory) inside the function. Something like this:
#include <stdio.h>
void createArr(int** arrPtr, int x, int y);
int main() {
int x, y; //Dimension
int i, j; //Loop indexes
int** arr; //2D array pointer
arr = NULL;
x=3;
y=4;
createArr(arr, x, y);
for (i = 0; i < x; ++i) {
for (j = 0; j < y; ++j) {
printf("%d\n", arr[i][j]);
}
printf("\n");
}
_getch();
}
void createArr(int** arrPtr, int x, int y) {
int i, j; //Loop indexes
arrPtr = malloc(x*sizeof(int*));
for (i = 0; i < x; ++i)
arrPtr[i] = malloc(y*sizeof(int));
for (i = 0; i < x; ++i) {
for (j = 0; j < y; ++j) {
arrPtr[i][j] = i + j;
}
}
}
Forget about pointer-to-pointers. They have nothing to do with 2D arrays.
How to do it correctly: How do I correctly set up, access, and free a multidimensional array in C?.
One of many reasons why it is wrong to use pointer-to-pointer: Why do I need to use type** to point to type*?.
Example of how you could do it properly:
#include <stdio.h>
#include <stdlib.h>
void* create_2D_array (size_t x, size_t y)
{
int (*array)[y] = malloc( sizeof(int[x][y]) );
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
array[i][j] = (int)(i + j);
}
}
return array;
}
void print_2D_array (size_t x, size_t y, int array[x][y])
{
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
}
int main (void)
{
size_t x = 5;
size_t y = 3;
int (*arr_2D)[y];
arr_2D = create_2D_array(x, y);
print_2D_array(x, y, arr_2D);
free(arr_2D);
return 0;
}
Yes, passing a pointer to int ** (but 3 stars is considered bad style), I suggest to return an allocated variable from your function:
int **createArr(int x, int y)
{
int **arrPtr;
int i, j; //Loop indexes
arrPtr = malloc(x*sizeof(int*));
if (arrPtr == NULL) { /* always check the return of malloc */
perror("malloc");
exit(EXIT_FAILURE);
}
for (i = 0; i < x; ++i) {
arrPtr[i] = malloc(y*sizeof(int));
if (arrPtr[i] == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < x; ++i) {
for (j = 0; j < y; ++j) {
arrPtr[i][j] = i + j;
}
}
return arrPtr;
}
Call it using:
arr = createArr(x, y);
Yes, an array can be initialized this way. As long as you pass a pointer, the memory address should remain the same. So, if you assign anything to the pointer it will valid.
Think of an a[] as a* pointer to the first element
a [][] will be a** pointer to a pointer of the first element or a pointer to the first array (first row of a table)
I want to a fill a small 2 d array with arbitrary values before moving onto a bigger array. However, when I compile and run my program, I get some weird output. It is not perfectly square. if someone could point out what im doing wrong that would be great.
void startarray(char (*arr)[10], int y_length, int x_length);
void printarray(char (*arr)[10], int y_length);
int main()
{
char arr[10][10];
startarray(arr, 10,10);
printarray(arr, 10);
return 0;
}
void startarray(char (*arr)[10], int y_length, int x_length)
{
int i;
int j;
for(i = 0; i <= y_length; i++)
{
for(j = 0; j < x_length; j++)
{
arr[i][j] = 'a';
}//end for
arr[i][j] = '\0';
}//end for
}
void printarray(char (*arr)[10], int y_length)
{
int i = 0;
while(i < y_length)
{
printf("\n%s", arr[i]);
i++;
}//end while
}