How to increment value in a struct matrix in c? - c

I've calloc'd a correlation matrix in a struct but am unable to increment/set values in that matrix. The struct is
typedef struct matrixStruct{
char** word;
int numberOfWords;
int** matrix;
} matrix;
This is how i've allocated the structure using calloc. I've used calloc because i'd like all the values in the matrix to be 0.
//Allocate rows of matrix
wordStore->matrix = calloc(2000,sizeof(int*));
//Allocate columns of matrix
for(int j = 0; j< 2000; j++)
{
wordStore->matrix[j] = calloc(2000,sizeof(int*));
}
Assume i have an array which has values of
int reference [] = {20,400,5,1899};
And this is how i'm trying to assign/increment values within the matrix, but it doesn't seem to work.
for(int k = 0; k<lenReference; k++)
{
for(int l = 0; l<lenReference;l++)
{
wordStore->matrix[k][l] += 1;
if(k == l){
wordStore->matrix[k][l] = 0;
}
}
}
This is the print loop that i'm using, and when i run the file it has an error that says "subscripted value is not an array, pointer, or vector", but i thought that this was the correct way to print a 2d array. What is the issue with this print?
for(int i = 0; i<2000; i++)
{
for (int j = 0; j<2000; j++)
{
printf("%08d ", words.matrix[i][j]);
}
printf("\n");
}
Any help would be much appreciated!

Related

Why do I get a segmentation fault by declaring a 2d array in c?

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]);

Undefined behavior with 2d array of struct C

I have a 2d array of structs that I am assigning strings to, here is my struct.
struct node {
char* value;
};
Here is my allocation (I am new to C so I am not sure if it is right) but there will always be 35 columns but there could be millions of rows.( I just had it at 3 for now for testing)
const int rows=3;
struct node ** arrayofnodes[rows][35];
for(int i=0; i<rows; i++) {
array[i] = malloc(test * sizeof array[0]);
for(int j=0; j<35; j++) array[i][j] = malloc(sizeof array[0][0]);
}
I then read in character by character from a csv file and have a temp string, and assign the value of the temp to the position I want by using this below.
//int row and count are defined in my while loop I have for counting commas(or what col I am on) then new lines for the rows
arrayofnodes[row][count]->value=strdup(temp);
printf("%s \n", arrayofnodes[row][count]->value);
printf("%d %d \n",row, count );
When I assign like the way above it seems to work. I added these print statements in to make sure it was assigning the right values.
For example above would print out something like
Red
0 0
And this is correct for that position.
But then after I do all of my assigning. I placed a print statement printf("%s \n", arrayofnodes[0][0]->value); to test if I can retrieve the 1st value as shown above which should be "Red".
In my terminal it outputs "#`??" or "#Pz?" or just any random output. I have tried this for a bunch of different positions besides 0,0, but they all get the same outcome. I guess I am just confused why the print statements work right after I assign them, but not at the end of my code when I call them later.
This is what it looks like you're trying to do. You will need to scan your csv file and compute the number of rows required, then populate the values however you want.
#include <stdio.h>
#include <stdlib.h>
struct node {
char* value;
};
int main() {
const int rows = 3; // you will need to compute this beforehand
const int columns = 35;
struct node** arrayofnodes = malloc(rows * sizeof(struct node*));
for (int i = 0; i < rows; ++i) {
arrayofnodes[i] = malloc(columns * sizeof(struct node));
}
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
arrayofnodes[i][j].value = malloc(...);
strcpy(arrayofnodes[i][j].value, ...); // etc..
}
}
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
free(arrayofnodes[i][j].value);
}
}
for (int i = 0; i < rows; ++i) {
free(arrayofnodes[i]);
}
free(arrayofnodes);
}
You can avoid overcomplicated allocation by using constant size inside the structure:
struct OneRow
{
char Value[35];
}
const int Rows=3;
OneRow *MyArray=NULL;
MyArray = (OneRow*) malloc (Rows*sizeof(OneRow));
You can now access each element (character) or a whole string as
MyArray[rownumber].Value[colnumber] = …
strcpy (MyArray[rownumber].Value, "I'm_shorter_than_35"); //34 chars max + null-term

Allocating memory to a 2D array in C

Why can't I allocate each index of a 2D array individually.
Is there any correct and proper way to allocate memory if you want to use a dynamically allocated array in C?
I am getting a segmentation error for this code
here is my code:
typedef struct
{
char ***sheet;
int columns;
int rows;
} SPREADSHEET; // to access data sheet[COL][ROW]
SPREADSHEET *createSpreadSheet(int columns, int rows) {
if (columns <= 0 || rows <= 0){ // Disallow 0 or negative rows/columns
return NULL;
}
SPREADSHEET *sp = malloc(sizeof(SPREADSHEET));
sp->columns = columns;
sp->rows = rows;
for(int i=0; i<rows; i++){
for(int j=0; j<columns; j++){
printf("i: %i, j: %i\n", i, j);
sp->sheet[i][j] = malloc(sizeof(char(*))+2);
}
}
return sp;
}
I think that what you are looking for is this:
typedef struct
{
int columns;
int rows;
char sheet[];
} SPREADSHEET;
SPREADSHEET *sp = malloc( sizeof(SPREADSHEET) + sizeof(char[columns][rows]) );
sp->columns = columns;
sp->rows = rows;
for(size_t i=0; i<columns; i++)
{
for(size_t j=0; j<rows; j++)
{
sp->sheet[i*rows + j] = something;
}
}
...
free(sp);
Where sheet is a so-called flexible array member. It has to be declared last in the struct, and it's guaranteed to behave deterministically when you allocate trailing memory after the struct itself. The variable in itself does not add to the size of the struct.
Unfortunately C only allows single row flexible array members, so you have to use a "mangled 2D array" if you wish to use it as in your case. It means we calculate the array index manually in run-time, in order to access the array items.
Alternatively, you can access the items through a temporary array pointer, which is also well-defined:
char (*arr)[rows] = (void*) sp->sheet;
for(size_t i=0; i<columns; i++)
{
for(size_t j=0; j<rows; j++)
{
arr[i][j] = something;
}
}

2D arrays using arrays of pointers or pointers to pointers in C?

I'm writing a C for which I need to create a 2D array. I've found a solution to my problem using double pointers (pointers to pointers) in the following way:
#include <stdio.h>
#include <stdlib.h>
int d = 3;
#define DIM_MAX 9
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int **array = malloc(d*sizeof(int *));
for(int count = 0; count < d; count++)
{
array[count] = malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
The code above works pretty well (it seems), but I've read in the web that using pointer to pointer is not the correct way to create 2D arrays. So I've come up with the following code, which also works:
#include <stdio.h>
#include <stdlib.h>
#define DIM_MAX 9
int d = 3;
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int *array[DIM_MAX] = {0};
for(int count = 0; count < d; count++)
{
array[count] = (int *)malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
What is the difference in using any of the two ways above to write this code?
[Not an answer, but an alternative approach to achieve the desired result, namely defining a user-defined 2D array.]
Assuming the compiler in use supports VLAs you could do this:
#include <stddef.h> /* for size_t */
void init_a(size_t x, size_t y, int a[x][y]); /* Order matters here!
1st give the dimensions, then the array. */
{
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
a[i][j] = (int) (i * j); /* or whatever values you need ... */
}
}
}
int main(void)
{
size_t x, y;
/* Read in x and y from where ever ... */
{
int a[x][y]; /* Define array of user specified size. */
init_a(x, y, a); /* "Initialise" the array's elements. */
...
}
}
It is actually pretty simple. All you have to do is this:
int i[][];
You are overthinking it. Same as a normal array, but has two indexes.
Let's say you want to create a "table" of 4 x 4. You will need to malloc space for 4 pointers, first. Each of those index points will contain a pointer which references the location in memory where your [sub] array begins (in this case, let's say the first pointer points to the location in memory where your first of four arrays is). Now this array needs to be malloc for 4 "spaces" (in this case, let's assume of type INT). (so array[0] = the first array) If you wanted to set the values 1, 2, 3, 4 within that array, you'd be specifying array[0][0], array[0][1], array[0][2], array[0][3]. This would then be repeated for the other 3 arrays that create this table.
Hope this helps!

How to allocate a 2D array of pointers to a struct [duplicate]

This question already has answers here:
How do I correctly set up, access, and free a multidimensional array in C?
(5 answers)
Closed 6 years ago.
This is were I got so far,but I don't know if it's right.
This function receives the dimensions of the 2D array (nxn),and allocates it.
flightInfo is the name of the struct.
Will this work?
thanks in advanced
after allocating the array(ignore the method ,since we are not allowed to use the method you proposed) I would like to initialize the struct (I built a function to do it but it didn't work),I tried to do it right after the allocation and kept getting the" Unhandled exception" warning, does it has to do
with the syntax, am I forgetting a '*'?
void flightMatrix()
{
FILE * fpf;
int checkScan,Origin,Dest;
float time,cost;
char flightName[3];
flightInfo *** matrix;
if(!(fpf=fopen("flights.txt","r")))exit(1);
while((checkScan=fscanf(fpf,"%*10c%3d%3d%3c%5f%7f%*",&Origin,&Dest,flightName,&time,&cost))!=EOF)
{
matrix=allocateMatrix(Dest);
matrix[Origin-1][Dest-1]->o=Origin;
}
}
flightInfo*** allocateMatrix(int n)
{ int i,j;
flightInfo*** matrix;
matrix=(flightInfo***)malloc(sizeof(flightInfo **)*n);
for(i=0;i<n;i++)
matrix[i]=(flightInfo **)malloc(sizeof(flightInfo*)*n);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
matrix[i][j] = NULL;
}
return matrix;
}
[http://i.stack.imgur.com/MFC7V.png]
this is what happens when I try to initialize
Technically speaking, this won't create 2D array. The result will be array of pointers, where each one points to different array of pointers to a struct.
The difference is that, memory will be fragmented, so every element will point to some memory location, instead of single continuous memory block.
The common approach for this is to create flatten 2D array:
flightInfo** allocateMatrix(int n)
{
flightInfo** matrix = malloc(n*n * sizeof(*matrix));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
matrix[i*n + j] = NULL;
return matrix;
}
If you are forced to use two indices, then you could place matrix as function argument:
void allocateMatrix(int n, flightInfo* (**matrix)[n])
{
*matrix = malloc(n * sizeof(**matrix));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
(*matrix)[i][j] = NULL;
}
The second asterisk is required, because pointers are passed by value, otherwise you would end up with modified local copy of the pointer, that does nothing to matrix from main function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct flightInfo {
char airport[30];
int altitude;
} flightInfo;
void allocateMatrix(int n, flightInfo* (**matrix)[n])
{
*matrix = malloc(n * sizeof(**matrix));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
(*matrix)[i][j] = NULL;
}
int main()
{
int n = 10;
flightInfo* (*matrix)[n];
allocateMatrix(n, &matrix);
matrix[0][0] = malloc(sizeof(flightInfo));
strcpy(matrix[0][0]->airport, "Heathrow");
matrix[0][0]->altitude = 10000;
printf("%s, %d\n", matrix[0][0]->airport, matrix[0][0]->altitude);
}
The another way would be to encapsulate the array within a struct.

Resources