I have a quadratic matrix(two-dimensional dynamic array of pointers) and need to change rows/columns order. The matrix is very big that's why I have decided just to change pointers instead of copying all of elements. I also have another array which specifies a computation.
Rows permutation specifies this way:
4,3,2,1 - it means that the first row must be on the fourth place, the second row must be on the third place, etc.
The same situation is with the columns.
How to implement such algorithm of changing of rows order(permutation of of pointers)? Here it is my version, but it doesn't work. I want to copy pointers but element is copied instead of it and then appears a segmentation fault.
When I add '&' to get address, the compiler says that it is a syntax error:
orderOfRows[i] = &auxMatrix[computation[i]];
Here it is my code:
static int N = 6;
static int **orderOfRows;
int **sourceMatrix;
int **auxMatrix;
int main() {
int* computation = (int*)malloc(N*sizeof(int));
computation[0] = 1;
computation[1] = 6;
computation[2] = 3;
computation[3] = 7;
computation[4] = 4;
computation[5] = 2;
}
printf("After computation has been done: \n");
changeRowOrder(computation);
void changeRowOrder(int *computation) {
int i;
// change rows order and dopy them into a temp array
for(i = 0; i < N; ++i) {
// static arrays
orderOfRows[i] = auxMatrix[computation[i]];
}
// recover matrix
for(i = 0; i < N; ++i) {
auxMatrix[i] = orderOfRows[i];
}
void allocate2dMemory() {
int i = 0;
sourceMatrix = (int**)malloc(N * sizeof(int *));
if(sourceMatrix == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
for(i = 0; i < N; i++) {
sourceMatrix[i] = (int*)malloc(N * sizeof(int));
if(sourceMatrix[i] == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
}
auxMatrix = (int**)malloc(N * sizeof(int *));
if(auxMatrix == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
for(i = 0; i < N; i++) {
auxMatrix[i] = (int*)malloc(N * sizeof(int));
if(auxMatrix[i] == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
}
orderOfRows = (int**)malloc(N * sizeof(int *));
if(orderOfRows == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
for(i = 0; i < N; i++) {
orderOfRows[i] = (int*)malloc(N * sizeof(int));
if(orderOfRows[i] == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
}
}
}
I will spend 2*N(copy pointers and then recover) operations instead of N*N.
And I have another question: how I can do the permutation of columns using this idea? If it isn't possible how can I do the permutation of columns but not to copy all elements of the matrix? The programming language is only C.
Instead of
orderOfRows[i] = &auxMatrix[computation[i]];
you should have
for (int j = 0; j < N; ++j)
{
orderOfRows[i][j] = auxMatrix[computation[i]][j];
}
And one more thing:
if you havecomputation[1] = 6, it means that by doing auxMatrix[computation[i]] you try to access auxMatrix[6], which you can't do because auxMatrix's size is 6x6.
If you want to be able to swap both rows and columns without copying, you are going to need to have two auxiliary indices:
int *row_index;
int *col_index;
and access the elements of your matrix using these:
element = matrix[row_index[row]][col_index[col]];
To swap a row or column, you simply swap the corresponding elements of row_index or col_index.
Related
Having trouble understanding and getting to work String operations in the following code.
Please help, me and my study colleagues are losing our minds over this. ty.
This is a simple method to fill a multi dimensional array with custom strings - which for some reason we cannot figure out for the life of us does simply not work - spits out random junk from the memory instead. Also allocation amounts don't seem to be quite right.
#include <stdio.h>
#include <malloc.h>
#include <string.h>
char*** createKeyPad(int rows, int cols, int num_chars) {
if(num_chars <= 0) return NULL;
char needed = 'a';
char** aptr = NULL;
char*** rptr = NULL;
aptr = (char**) malloc(rows * cols * sizeof(char*));
if(aptr == NULL) {
return NULL;
}
rptr = (char***) malloc(rows * sizeof(char**));
if(rptr == NULL) {
free(aptr);
return NULL;
}
for(int row = 0; row < rows; row++) {
rptr[row] = aptr + (row * cols);
}
for(int row = 0; row < rows; row++) {
for(int col = 0; col < cols; col++) {
char* string;
for(int i = 0; i < num_chars; i++) {
string[i] = needed;
}
string[num_chars] = '\0';
rptr[row][col] = string;
printf("%s", string);
}
}
printf("%s", "hallo");
return rptr;
}
int main() {
printf("Hello, World!\n");
char*** keypad = createKeyPad(5, 5, 3);
for(int row = 0; row < 5; row++) {
for(int col = 0; col < 5; col++) {
printf("%s", keypad[row][col]);
}
printf("\n");
}
}
You have plenty problems in this code.
string is a dangling pointer - ie it was not initialized and does not reference a valid char array
even if string was referencing a valid object you assign the same pointer to all (pseudo)array elements.
Do not use *** pointers.
use the correct type for sizes
Use positive checks and try to minimize function returns.
arrays are indexed from 0 in C and even if the string was referencing an array of num_chars elements, string[num_chars] = '\0'; is accessing an element outside the array bounds.
I would use array pointers and use only one allocation to allocate the space for the whole 3D array.
Use objects instead of types in sizeofs
int createKeyPad(size_t rows, size_t cols, size_t numChars, char (**pad)[cols][numChars])
{
int result = 0;
if(numChars > 1)
{
*pad = malloc(rows * sizeof(**pad));
if(*pad)
{
result = 1;
for(size_t row = 0; row < rows; row++)
{
for(size_t col = 0; col < cols; col++)
{
for(size_t i = 0; i < numChars - 1; i++)
{
(*pad)[row][col][i] = row * cols + col + '0';
}
(*pad)[row][col][numChars - 1] = 0;
}
}
}
}
return result;
}
int main(void)
{
printf("Hello, World!\n");
char (*keypad)[5][3];
if(createKeyPad(5, 5, 3, &keypad))
{
for(size_t row = 0; row < 5; row++)
{
for(size_t col = 0; col < 5; col++)
{
printf("%s ", keypad[row][col]);
}
printf("\n");
}
}
free(keypad);
}
https://godbolt.org/z/6zY4zbGW3
The main problem is that char* string; followed by string[i] = needed; is dereferencing an invalid pointer because string is not pointing to anything valid.
In the code's current style of allocating one block for each level and dividing the block up, the memory for all the strings could be allocated in one big block:
char* sptr = (char*) malloc(rows * cols * (num_chars + 1) * sizeof(char));
(Note: The (char*) typecast is not required. Also the * sizeof(char) is not required since sizeof(char) is 1 by definition, but I put it in there in case the code is changed to use something other than char at a later date.)
Then the string variable in the nested loop can be initialized as follows:
char* string = sptr + (row * cols + col) * (num_chars + 1);
I am new to threads and I have a program that uses threads to find the minimum number out of a 2d array and later on, it finds the distance that the other elements of the array have from the minimum number and stores them in another array.
The user should enter the size of the array and the number of threads he wants to use.
I tried the program below for 1d array and it worked just fine. When I converted it to work for a 2d array it started crashing and throwing a segmentation fault. I, however, cannot find which part of the 2d declaration is wrong.
Any help is really appreciated.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <pthread.h>
struct Parameters
{
// input
int s,p; //n is size of array, p is number of threads
int** array; //array with elements
int start;
int end;
// output
int smallest;
int pos; //position if minimum
int** B; //array that holds the distances
};
void* min(void* args)
{
struct Parameters* p = (struct Parameters*)args;
int **array = p->array;
int **B1 = p->B;
int start = p->start;
int end = p->end;
int smallest = array[start][start];
int pos = p->pos;
int distance;
//find the smallest
for (int i = start; i < end; i++)
{
for(int j = start; j < end; j++)
{
if (array[i][j] < smallest)
{
smallest = array[i][j];
pos = i;
}
}
}
//find the distances
for(int i = 0; i < ((struct Parameters*)args) -> s; i++)
{
for(int j = 0; j < ((struct Parameters*)args) -> s; j++)
{
distance = abs(pos - i);
B1[i][j] = distance;
}
}
params->smallest = smallest;
params->B = B1;
return NULL;
}
int main()
{
int smallest,pos;
int s,p;
struct Parameters *ptr = (struct Parameters *)malloc(sizeof(struct Parameters));
if(ptr == NULL)
{
printf("Not enough. Try again \n");
exit(0);
}
printf("Type s\n");
scanf("%d",&(ptr->s));
printf("Type p\n");
scanf("%d", &(ptr->p));
// declare an array of threads and associated parameter instances
pthread_t threads[(ptr->p)];
struct Parameters thread_parameters[(ptr->p)] ;
int arr[ptr->s][ptr->s];
int B2[ptr->s][ptr->s];
// intialize the array
for(int i=0; i< ptr->s; i++)
{
for(int j=0; j< ptr->s; j++)
{
printf("Type a \n");
scanf("%d",&arr[i][j]);
}
}
// smallest needs to be set to something
smallest = arr[0][0];
// start all the threads
for (int i = 0; i < ptr->p; i++)
{
memcpy(arr, thread_parameters[i].array, sizeof(arr));
thread_parameters[i].s = ptr->s;
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
thread_parameters[i].start = i * (ptr->s / ptr->p);
thread_parameters[i].end = (i+1) * (ptr->s / ptr->p);
pthread_create(&threads[i], NULL, min, &thread_parameters[i]);
}
// wait for all the threads to complete
for (int i = 0; i < ptr->p; i++)
{
pthread_join(threads[i], NULL);
}
// Now aggregate the "smallest" and "largest" results from all thread runs
for (int i = 0; i < ptr->p; i++)
{
if (thread_parameters[i].smallest < smallest)
{
smallest = thread_parameters[i].smallest;
}
}
printf("Smallest is %d\n", smallest);
thread_parameters[ptr->p].B[ptr->s][ptr->s];
for (int i = 0; i < 1; i++)
{
for(int j = 0; j < ptr->s;j++)
{
for(int k = 0; k < ptr->s; k++)
{
printf("Element %d is %d away from min\n",j,thread_parameters[i].B[j][k]);
}
}
}
return 0;
}
Thank you!!
The issue with your code might also come from :
memcpy(arr, thread_parameters[i].array, sizeof(arr));
...
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
as thread_parameters[i].array and thread_parameters[i].B are not allocated, if you are only reading the array it might b fine to only pass them by address
thread_parameters[i].array = arr
but for thread_parameters[i].B you would need to allocate the arrays and perform a deep copy (memcpy would not work)
The below text does not answer the question but does provide some insight on VLA usage
One reason for causing the segmentation with a declaration of a Variable Length Array is that the value is to large to allocate the array on the stack (some compiler choose this option, this choice might have performance reason).
The is not much option to recover cleanly from failure to allocate memory on the stack as there is little way to clean up stack memory during runtime within the same stack context.
You can mitigate the issue by allocating your 2D arrays on the heap instead, some of the strategies are available here(thanks #Lundin) and here.
int** alloc_2d_int_array(size_t rows, size_t cols) {
int **result = malloc(rows * sizeof(int *));
if(result == NULL) {
// could not allocate more memory
return NULL;
}
size_t row_size = cols * sizeof(int);
for(int i=0; i < rows; ++i) {
result[i] = malloc(row_size);
if(result[i] == NULL) {
// could not allocate more memory
// cleanup
return NULL;
}
}
return result;
}
the above implementation have not been tested, but does compile, there are still risk of integer overflow.
Then use the above define function as following:
int **arr = alloc_2d_int_array(ptr->s, ptr->s);
int **B2 = alloc_2d_int_array(ptr->s, ptr->s);
easier implementation (see here(thanks #Lundin))
int **arr = malloc(sizeof(int[ptr->s][ptr->s]);
int **B2 = malloc(sizeof(int[ptr->s][ptr->s]);
Hi, I'm a newbie in C (and in programming) and I'm trying to make a function that returns dynamically allocated array. It looks like:
int *returnArray(void)
{
int i, *p[4];
for (i = 0; i < 4; i++)
if ((p[i]=(int *)malloc(sizeof(int)*(4-i))) == NULL)
return NULL;
return &p[0][0];
}
And calling to this function:
int *ar;
if ((ar = returnArray()) == NULL) {
/* ERROR */
return 1;
}
But it doesn't work at all. After calling the function I wish to use *ar like a normal 2D array + unallocate the memory at the end of programme. Even if I've looked at similar topics I don't know how to fix it.
Thank you all for your help. I understand it much better now.
You're close. What you are missing is that you need to allocate both dimensions, like this:
int** CreateTwoDimensionalArray(int rows, int cols)
{
int row, prevrow;
int** result = (int**) calloc(rows, sizeof(int*));
if (result == NULL) {
return NULL;
}
for (row = 0; row < rows; ++row) {
int* current_row = (int*) calloc(cols, sizeof(int));
if (current_row == NULL) {
for (prevrow = 0; prevrow < row; ++prevrow) {
free(result[prevrow]);
}
free(result);
return NULL;
}
result[row] = current_row;
}
return result;
}
void FreeTwoDimensionalArray(int** array, int rows, int cols)
{
int row;
for (row = 0; row < rows; ++row) {
free(array[row]);
}
free(array);
}
In function returnArray, variable p is a local variable, so you should not return its address.
You can return one of the values in it (for example - p[2]), but you will obviously lose all the others.
So instead of returning this array, pass it to the function and initialize the entries inside:
void initArray(int* p[])
{
int i;
for (i=0; i<SIZE; i++)
p[i] = (int*)malloc(sizeof(int)*(SIZE-i));
}
Then, you can call this function and check if all allocations have completed successfully:
int i;
int* p[SIZE];
initArray(p);
for (i=0; i<SIZE; i++)
{
if (p[i] == NULL)
break;
}
if (i < SIZE)
{
//Error - not all allocations have completed successfully
}
else
{
// Example #1
scanf("%d",&p[3][0]);
printf("%d",p[3][0]);
// Example #2
scanf("%d" , p[3]);
printf("%d",*p[3]);
}
And of course, you will need to release the allocated memory at a later point in execution:
void freeArray(int* p[])
{
int i;
for (i=0; i<SIZE; i++)
{
if (p[i])
free(p[i]);
}
}
I want to define a 2D array of very big size. But it is giving me segmentation fault?
#include <stdio.h>
int main () {
int i;
int temp[4000][5000];
for (i = 0; i < 5; i++)
{
printf ("Hello World\n");
}
}
Can anyone please suggest me some other way? Is there some problem with memory initialization? Thanks in advance
You can allocate the whole table in only one array but you won't be able to access array data with indices using two square brackets:
int * temp = malloc(4000*5000*sizeof(int));
to access the element (i,j) where previously you wrote temp[i][j], now you should now compute the index the following way:
temp[i*5000+j];
and do not forget to free the memory allocated for your table afterward:
free(temp);
int temp[4000][5000];
That's a VERY BIG array, way bigger than the normal size of stack, you get a segmentation fault because of stack overflow. Consider using dynamic allocation instead.
You need to use dynamic allocated arrays for such big arrays.
Try:
int* temp[4000];
for(i = 0; i < 4000; ++i) temp[i] = malloc(5000 * sizeof(int));
...
for(i = 0; i < 4000; ++i) free(temp[i]).
Whole program with error checking:
int main () {
int i, j;
int* temp[4000];
for (i = 0; i < 4000; ++i)
{
temp[i] = malloc(5000 * sizeof(int));
if (temp[i] == NULL)
{
for (j = 0; j < i; ++j) free(temp[i]);
exit(1);
}
}
for (i = 0; i < 5; i++)
{
printf ("Hello World\n");
}
for (i = 0; i < 4000; ++i) free(temp[i]);
}
Here you can find function which would use single malloc call to allocate two dimension array.
And simpler version of my own:
int main () {
int i, j;
int* temp[4000];
int* array = malloc(4000 * 5000 * sizeof(int));
if (malloc_tmp == NULL) exit(1);
for (i = 0; i < 4000; ++i)
{
temp[i] = array + (i * 5000);
}
for (i = 0; i < 5; i++)
{
printf ("Hello World\n");
}
free(temp[0]);
}
I'm currently working on a school (matrix multiplier) project and I have a problem.
I reprensent a matrix with a 2d array and I allocate it this way :
typedef struct matrix
{
int** matrix;
unsigned int l;
unsigned int c;
} matrix;
int matrix_alloc(matrix** matr, unsigned int l, unsigned int c)
{
unsigned int i, j;
*matr = malloc(sizeof(matrix)); /* Allocate memory for the structure */
if (*matr == NULL) /* Check if malloc succeeded */
{
fprintf(stderr, "malloc error"); /* If not print error */
return -1;
}
(*matr)->matrix = malloc(l*sizeof(int*)); /* Allocate memory for columns of the matrix*/
if ((*matr)->matrix == NULL)
{
fprintf(stderr, "malloc error");
free(*matr);
return -1;
}
for (i = 0; i < l; i++)
{
(*matr)->matrix[i] = malloc(c*sizeof(int));
if ((*matr)->matrix[i] == NULL)
{
fprintf(stderr, "malloc error");
for (j = 0; j < i; j++)
{
free((*matr)->matrix[j]);
}
free(*matr);
return -1;
}
for (j = 0; j < c; j++)
{
(*matr)->matrix[i][j] = 2; // Matrix should be filled with 2 for tests
printf("Element added : %d\n", (*matr)->matrix[i][j]);
}
}
(*matr)->l = l;
(*matr)->c = c;
printf("will print matrix----------------------\n");
matrix_print(*matr);
return 0;
}
And this is how I print the matrix
void matrix_print(matrix* m)
{
unsigned int i, j;
int v;
printf("********************************************************************************\n");
printf("Lines:\t %i\n", m->l);
printf("Cols:\t %i\n", m->c);
printf("Matrix::\n");
for (i = 0; i < m->l; i++)
{
for (j = 0; j < m->c; j++)
{
matrix_get_elem_at(v, i, j, m);
printf("\t%d", v);
/*printf("\t%ld", mpz_get_si(v)); */
}
printf("\n");
}
printf("********************************************************************************\n");
}
When I do
matrix* matr;
/* alloc matrix */
assert(matrix_alloc(&matr, 10, 10) == 0);
printf("----------------------------will print test matrix\n");
matrix_print(matr);
My matrix is filled with 32767 instead of 2
Can someone help me get rid of this bug?
Thank you
Ben
You should show us more code (for example, how did you declare typedef matrix?) But I bet that the problem is in matrix_get_elem_at - it should get int* for the first parameter. not int.
If I may give you an advice, it would be better to represent your matrix as one contiguous array.In this case rows are positionned one after another, like Row1| Row1| ... |Row(col). For example
[1, 2, 3]
[4, 5, 6]
will be
[1, 2, 3, 4, 5, 6]
To create the matrix you use
int** matrix = (int**)malloc(sizeof(rowCount*colCount))
To access element at [i][j] you use matrix[ i*colCount + j ].
Most of your functions will be much simpler to write.