Getting the values of linked list with loops - c

I have to create a function who can get the value of a matrix wich take the form of a double linked list. Here is the structures of the matrix
typedef struct row {
unsigned int indiceRow;
struct row * next;
struct col * data;
} row;
typedef struct col{
double value;
unsigned int indiceColumn;
struct col * next;
} col;
typedef struct matrix{
int nRows;
int nCols;
struct row * rowFirst;
}matrix;
the structure matrix represent the top of the linked list and contain the total number of rows and columns and a variable row wich point to the first node of the list of row nodes. the row nodes contain the number of the row of the matrice, a variable row called next wich represent the next line of the matrix and a variable data point to another list of col nodes. Those col nodes contains the number of the column, the value at those coordonates(row,column) and the a col next. only the values different of zero have to be in the col linked list.
To get the value of a precise point of the matrix I created the function sp_get. It take a structure matrix, the line and column I'm looking for and a double variable as argument. It returns 0 when it works and update the variable double *val with the value I'm looking for.
int sp_get( struct matrix *mat, unsigned int rows, unsigned int col, double *val){
row * temps = (row*)malloc(sizeof(row));
temps = mat->rowFirst;
while(temps->indiceRow!= rows){
temps = temps->next;
}
while(temps->data!= NULL && temps->data->indiceColumn!= col && temps->data->next!=NULL){
temps->data = temps->data->next;
}
if(temps->data->indiceColumn == col){
*(val) = temps->data->value;
}
else{
*(val) = 0.0;
}
return 0;
First I create a row variable to run through the matrix, then I look for the good row and then for the good column. If I can't find the good column it means that the value is 0.
When I use the function to look for one value, it works well, and always return the good value.(tempMatrix is a matrix variable and contain the linked list)
double * vall =(double*)malloc(sizeof(double));
sp_get(tempMatrix, 2, 3, vall);
but when I'm using the function with a double loop for I don't have the same results and I can't not explain why...
double * vall =(double*)malloc(sizeof(double));
int i;
int j;
for(i=1;i<=tempMatrix->nRows;i++){
for(j=1; j<=tempMatrix->nCols;j++){
sp_get(tempMatrix,i,j,vall);
printf(" %f ", *(vall));
}
printf("\n");
}
Here are the result I get with the loops
and here are the results I should get
It might be a proble of memory leak, I don't know where it comes from.
Thanks in advance for your help!

Just in sp_get alone the following problems abound:
Memory the first two lines.
Anytime you see something like this in successive lines in C:
ptr = malloc(...)
ptr = <something else>
it is always a memory leak.
Updating the column header rather than simply enumerating it
Once you find the row you seek, you then do this:
while(temps->data!= NULL &&
temps->data->indiceColumn!= col &&
temps->data->next!=NULL)
{
temps->data = temps->data->next;
}
Ask yourself, what is temps->data = ... actually updating? It is changing the temps->data pointer to point to its own next, which means what temps->data pointed to prior is gone. That's fine if temps->data is a temporary pointer, but it isn't. It is the data member in the row struct you worked so hard to find in the prior loop.
Potential NULL pointer dereference
You may think having this:
while(temps->data!= NULL &&
temps->data->indiceColumn!= col &&
temps->data->next!=NULL)
for the while-condition in your loop will harbor safety from temp-data being NULL for the code that follows:
if(temps->data->indiceColumn == col)
{
*(val) = temps->data->value;
}
but if it did, then why bother with the first clause (which is correct, btw). It appears the addition of the last clause (temps->data->next!=NULL) was an effort to stave off crashes. That isn't the way to do it.
Minor: Hiding type col with parameter col
Needs little explanation. See your var names.
Minor: There is no need to dynamically allocate the out-parameter as you're using it.
Your code do to this:
double * vall =(double*)malloc(sizeof(double));
int i, j;
for(i=1;i<=tempMatrix->nRows;i++)
{
for(j=1; j<=tempMatrix->nCols;j++)
{
sp_get(tempMatrix,i,j,vall);
printf(" %f ", *(vall));
}
printf("\n");
}
Can just as easily do this:
double val = 0.0;
int i, j;
for(i=1;i<=tempMatrix->nRows;i++)
{
for(j=1; j<=tempMatrix->nCols;j++)
{
sp_get(tempMatrix,i,j,&val); // note address-of operator
printf(" %f ", val);
}
printf("\n");
}
Updated sp_get
I'm pretty sure this is what you're trying to do. The following will return 0 if the indexed values found and retrieved, otherwise it returns -1 and the out-parameter is set to 0.0.
int sp_get( struct matrix const *mat, unsigned int rows, unsigned int cols, double *val)
{
// prime to 0.0
*val = 0.0;
if (!mats)
return -1;
// walk the row table
struct row const *row_ptr = mat->rowFirst;
while (row_ptr && row_ptr->indiceRow != rows)
row_ptr = row_ptr->next;
// leave now if we didn't find the row.
if (!row_ptr)
return -1;
struct col const *col_ptr = row_ptr->data;
while (col_ptr && col_ptr->indiceColumn != cols)
col_ptr = col_ptr->next;
if (!col_ptr)
return -1;
*val = col_ptr->value;
return 0;
}
Note we modify nothing in the actual matrix, so the entire thing, including all pointers we use to index within it, can be const (and should be).
Best of luck.

Related

Linking two structures in C

I am trying to link 2 structures, one is a matrix and one is a single node. The connection should be a matrix that holds size and an array of rows with nodes connected between each other:
so a 3X3 matrix should look like this:
|Node|->|Node|->|Node|-> NULL
|Node|->|Node|->|Node|-> NULL
|Node|->|Node|->|Node|-> NULL
The question is how do I connect it properly?
Do I need to allocate the memory for the rows only or should I allocate the memory for all elemets and then connect them?
typedef struct cellNode {
int cell;
struct cellNode* next;
} Node;
typedef struct {
int numRows;
int numColumns;
Node** rows;
} Matrix;
Matrix* MatrixAdder(int row, int col, char mat)
{
Matrix temp=NULL;
int i,j;
if(!(temp=(Matrix*)malloc(sizeof(Matrix)));
exit(1);
temp->numRows=row;
temp->numColumns=col;
if (!(temp.rows[i]=(Node*)malloc((row)*sizeof(Node))));
exit (1);
printf("Please insert values for matrix %c:\n",mat);
for (i=0;i<row;i++)
{
if(!(temp->rows[i]=(Node*)malloc(sizeof(Node))))
exit (1);
printf("Enter row %d data\n",i);
for(j=0;j<col;j++)
{
scanf("%d",&temp->rows->cell);
temp->rows=temp->rows->next;
if(!(temp->rows=(Node*)malloc(sizeof(Node))))
exit (1);
}
temp->rows=NULL;
}
}
If you know how many nodes you need to allocate, then you can of course allocate them all in a single call to malloc (as a normal plain "dynamic array" of nodes) and then link them all together. All you need is to keep track of the pointer returned by malloc.
But you still need to allocate the array of pointers used for rows. So no matter what you need at least two allocations.
It could be dome something like this (using normal variables and not your structures):
int numRows = 3;
int numColumns = 3;
// Allocate all the nodes
Node *allNodes = malloc(sizeof *allNodes * numRows * numColumns);
// Allocate the array of pointers needed
Node **rows = malloc(sizeof *rows * numRows);
// Initialize the rows
for (int row = 0; row < numRows; ++row)
{
// if numColums == 3 then for
// row == 0 get a pointer to allNodes[0]
// row == 1 get a pointer to allNodes[3]
// row == 2 get a pointer to allNodes[6]
rows[row] = &allNodes[row * numColumns];
}
// Now create the linked lists
for (int row = 0; i < numRows; ++row)
{
// For numRows == 3, this will make node point to, in turn:
// allNodes[0]
// allNodes[3]
// allNodes[6]
Node **node = &rows[row];
// node will be pointing to a pointer to the *previous* node
// So start with 1 because that's then the *next* node in the list
for (int col = 1; col < numColumns; ++col)
{
// When row == 0 then:
// When col == 1 then link allNodes[0]->next to allNodes[1]
// When col == 2 then link allNodes[1]->next to allNodes[2]
// When row == 1 then:
// When col == 1 then link allNodes[3]->next to allNodes[4]
// When col == 2 then link allNodes[4]->next to allNodes[5]
// Etc...
(*node)->next = &allNodes[row * numColumns + col];
(*node) = &(*node)->next;
}
// Now head will be pointing to the lasts nodes next member
(*node) = NULL;
}
[Note: Code not tested!]
When finished you only have two pointers to free:
free(rows);
free(allNodes);
To understand exactly what's going on, if you're having trouble following along, I recommend you use a debugger together with a pen and some paper.
First of all draw a long rectangle for allNodes and divide it into numRows * numColumns number of sub-rectangles. Label them with their index (so the first becomes 0, the second 1 etc.). Then draw a second rectangle for rows and divide it into numRows sub-rectangles. Label these too with the indexes.
Now as you step along in the debugger, draw arrows between the sub-rectangles for form "pointers". For example with the first iteration of the first loop you draw an arrow from rows[0] to allNodes[0].
For the second loop, where the linked lists are created, draw another little rectangle and label it head. For each iteration of the outer linking loop you (erase) and draw an arrow from head to first rows[0], and so on.
Inside the inner linking loop (over columns) with the statement
(*head)->next = &allNodes[row * numColumns + col];
start at head and follow its arrow to rows. Then again follow the arrow to allNodes, and continue to follow any arrows until there are no more. Then draw an arrow from that element in allNodes to the next element in allNodes as indicated by row * numColumns + col. So for the first iteration you follow the arrow from head to rows[0], you follow that along to allNodes[0] where you draw an arrow to allNodes[1].
To understand why we use a pointer to a pointer for node and what (*node) = NULL is doing, then we need to draw how it looks like after the inner loop finishes. Again we use row == 0 as example.
+------+ +------------------+
| node | --> | allNodes[2].next | --> ???
+------+ +------------------+
By dereferencing node (as in (*node)) then we get to allNodes[2].next which we then can assign to be a NULL pointer.

Undefined behavior when deleting an element from dynamic array of structs

I have an n sized array of structs dynamically allocated, and each position of the array is an array too, with different sizes for each position (an array of arrays).
I created a function to delete a given array[index] but I'm facing some undefined behavior, for example:
If the array is of size 3, if I delete array[0],I can't access array[1]. This happens with other combinations of indexes too. The only way it works flawlessly is when I delete from end to start.
Here is the code I have:
Structures:
typedef struct point{
char id[5];
char type[5];
char color[10];
int x;
int y;
} Point;
typedef struct {
char lineID[5];
int nPoints;
Point *pt;
}railData;
typedef struct railway {
railData data;
}railway;
This is how the array was created:
headRail = (railway**)calloc(lineNum,sizeof(railway*));
And each Rail:
headRail[i] = (railway*)calloc(pointsNum,sizeof(railway));
These are the functions to delete a rail:
railway **delRail(railway **headRail, int j)
{
int nPts = 0;
if (!headRail)
{
puts(ERRORS[NULLPOINTER]);
return NULL;
}
// Number of rail points on jth rail
nPts = headRail[j]->data.nPoints;
// Free each rail point from jth rail
for (int i = 0; i < nPts; ++i)
{
free(headRail[j][i].data.pt);
}
// Free allocated memory for jth rail
free(headRail[j]);
return headRail;
}
And this is where I call the previous function:
railway **removeRail(railway **headRail)
{
char userID[20];
int index = 0;
// Quit if no rails
if (!headRail)
{
backToMenu("No rails available!");
return NULL;
}
// Get user input
getString("\nRail ID: ",userID,MINLEN,MAXLEN); // MINLEN = 2 MAXLEN = 4
// get index of the asked rail
getRailIndex(headRail,userID,&index);
if (index != NOTFOUND)
{
headRail = delRail(headRail, index);
// Update number of rails in the array (global var)
NUMOFRAILS--;
backToMenu("Rail deleted!\n");
}
else
backToMenu("Rail not found!");
return headRail;
}
So my question is how can I modify my code so that when position i is eliminated, all other indexes are shifted left and the last position, which would be empty, is discarded (something like realloc but for shrinking)
Is what I'm asking doable without changing the array's structure?
When removing element i, do memmove all the data from i+1 to i to the end of the array and then realloc with the size decremented by 1.
Note that arrays in C do not track their size in any way, so you need to pass the size by an external way.
Your data abstraction is strange. I would expect that headRail[j][0].data.nPoints is used to store the number of points inside the headRail[j][0].data structure, yet there you store the count of headRails in the j row headRail[j][<this count>]. I would advise to rewrite the abstraction, have one "object" for the railway and another for hadling two dimensional arrays of railways with dynamic sizes in all directions.
Like:
railway **delRail(railway **headRail, int j)
{
...
// this is strange, it's equal to
// nPts = headRail[j][0].data.nPoints;
// dunno if you mean that,
// or if [j][0].data.nPoints refers to the size of
// headRail[j][0].data.pt or to the size of the whole array
size_t nPts = headRail[j]->data.nPoints;
for (size_t i = 0; i < nPts; ++i) {
free(headRail[j][i].data.pt);
}
free(headRail[j]);
// note that arrays in C does not know how many elements are there in the array
// so you typically pass that along the arguments, like
// railway **delRail(railway **headRail, size_t railcount, int j);
size_t headRailCount = lineNum; // some external knowledge of the size
memmove(&headRail[j], &headRail[j + 1], (headRailCount - j - 1) * sizeof(*headRail));
void *pnt = realloc(headRail, (headRailCount - 1) * sizeof(*headRail));
if (pnt == NULL) return NULL; // that would be strange
headRail = pnt; // note that the previous headRail is no longer valid
--lineNum; // decrement that object where you store the size of the array
return headRail;
}
What about some encapsulation and more structs instead of 2d array? 2d arrays are really a bit of pain for C, what about:
typedef struct {
// stores a single row of rail datas
struct railData_row_s {
// stores a pointer to an array of rail datas
railData *data;
// stores the count of how many datas of rails are stored here
size_t datacnt;
// stores a pointer to an array of rows of rail datas
} *raildatas;
// stores the size of the pointer of rows of rail datas
size_t raildatascnt;
} railway;
The count of mallocs will stay the same, but thinking about data will get simpler. And each pointer that points to an array of data has it's own size tracking variable. An allocation might look like this:
railway *rail_new(size_t lineNum, size_t pointsNum) {
railway *r = calloc(1, sizeof(*r));
if (!r) { return NULL; }
// allocate the memory for rows of raildata
r->raildatascnt = lineNum;
r->raildatas = calloc(r->raildatascnt, sizeof(*r->raildatas));
if (!t->raildatas) { /* error hadnling */ free(r); abort(); }
// for each row of raildata
for (size_t i = 0; i < r->raildatascnt; ++i) {
struct railData_row_s * const row = &r->raildatas[i];
// allocate the memory for the column of raildata
// hah, looks similar to the above?
row->datacnt = pointsNum;
row->data = calloc(row->datacnt, sizeof(*row->data));
if (!row->data) { /* error ahdnling */ abort(); }
}
return r;
}

matrix product between linked list sparse matrix

i've rappresented my sparse matrix in that form, using C language:
typedef struct node
{
int column;
int value;
int row;
struct node *next;
} element;
i've got an Insert function that add an element in the matrix, here's the declaration:
void Insert(element *x[], int row, int column, int value)
my question is: how i can implement a function that compute the product between two sparse matrix in that form?
here's is my tentative:
void dotProduct( element * ptrA , element * ptrB ) {
element* initB = ptrB;
int sum = 0;
while( ptrA!=NULL ) {
ptrB = initB;
int column, int row;
while( ptrB!=NULL ) {
if( ptrA->row == ptrB->column ) {
column = ptrb->column;
sum = sum + ptra->value*ptrB->value;
row = ptrA->row;
}
ptrB = ptr->next;
}
ptrA = ptrA->next;
}
insert( row, column, sum )
}
You have a good start. But your sum variable is computing the sum of all elements of the result matrix. That's not what you want.
Here is what I would change.
1) Instead of a scalar integer int sum = 0 use a sparse matrix elment *result = NULL. You want to add the value to a specific element of the matrix, not to a scalar sum.
2) Add a function to add increase the value of a matrix element (row, column) by an int value
void Add(element *x[], int row, int column, int value){
element *ptr = x;
while (ptr != NULL) {
if (ptr->row == row && ptr->column == column) {
ptr->value += value;
return;
}
}
/* We could not find an existing element with given row and column
Create a new one */
Insert(x, row, column, value)
}
3) Replace sum = sum + ptra->value*ptrB->value; with Add(result, row, column, ptra->value*ptrB->value);
4) You can get rid of your final insert( row, column, sum ). It won't compile as it has only 3 parameters. By the time your outer while loop completes, you'll have a computed product in the sparse matrix result anyway.

Inserting node between values in static list C

I have the following Structures created:
typedef struct {
char name[15];
int ID;
} Employee;
typedef Employee Item;
typedef struct {
Item items[5];
int size;
} List;
I take in values from a file which populate these fields using this function:
void Insert (Item I, int position, List *L){
int i, LastPos;
LastPos = Length(L)-1;
if((LastPos) >= position){
for(i = 0; i < (LastPos - position); i++){
L->items[i-(LastPos+1)] = L->items[LastPos-i];
}
}
L->items[position] = I;
L->size = L->size+1;
}
When the position variable is different (IE, one that hasn't been placed yet), then there are no issues, I am able to print out the values saved EG:
Insert Name Stacy ID 1928502 at position 0
Insert Name Jimmy ID 1290589 at position 1
When I call the print function for their name and ID number, they are printed out fine.
However, if I Inserted Jimmy at position 0, his information would be printed fine however, Stacy's would appear as a random memory location every time EG:the IDs become 32767. Why does this happen when I override the position that has already been taken even though I have a loop which should reassign where the overridden information goes (one space back in the list).
Lets examine this expression:
L->items[i-(LastPos+1)]
If Length() returns 2 (the number of items currently in the array), then LastPos + 1 should be 2. Now when the loop starts, i is 0, which means that i - (LastPost + 1) is equal to 0 - 2 which is -2. Not an index you would normally use in an array.
I suggest you go the other way around, by looping from the last item to the first:
for (int i = Length(L) - 1; i >= position; --i)
L->items[i + 1] = L->items[i];

Transposing a matrix

I want to transpose a matrix, its a very easy task but its not working with me :
UPDATE
I am transposing the first matrix and
storing it in a second one
The two
arrays point to the same structure
I
need two arrays (target and source)
so I can display them later for
comparison.
struct testing{
int colmat1;
int rowmat1;
float mat[64][64];
};
int testtranspose(testing *test,testing *test2){
int i,j;
test2->colmat1 = test->rowmat1;
test2->rowmat1 = test->colmat1
for(i=0;i<test->rowmat1;i++){
for(j=0;j<test->colmat1;j++){
test2->mat[i][j] = test->mat[i][j];
}
printf("\n");
}
}
I thought this is the correct method of doing it, but apparently for a matrix such as :
1 2
3 4
5 6
7 8
I get :
1 2 0 0
3 4 0 0
What is the problem ?
Please help,
Thanks !
To transpose the matrix, you need to change rows and columns. So you need to use:
targetMatrix[i][j] = sourceMatrix[j][i];
Note how the order of i,j is changed, since one matrix's rows are another's columns.
By the way, instead of (*a).b, you can write a->b. This is the normal way of accessing a field of a struct pointer.
Try this...
struct testing{
int colmat;
int rowmat;
float mat[64][64];
};
int testtranspose(testing *test,testing *test2){
int i,j;
test2->colmat = test->rowmat;
test2->rowmat = test->colmat;
for(i=0;i<test->rowmat;i++){
for(j=0;j<test->colmat;j++){
test2->mat[j][i] = test->mat[i][j];
}
}
return 0;
}
int printmat(testing* mat)
{
for(int i=0;i<mat->rowmat;i++)
{
printf("\n");
for(int j=0;j<mat->colmat;j++)
printf((" %f"),mat->mat[i][j]);
}
return 0;
}
// 2
// main.cpp
int _tmain(int argc, _TCHAR* argv[])
{
testing mat1, mat2;
memset(&mat1,0,sizeof(testing));
memset(&mat2,0,sizeof(testing));
mat1.colmat =2;
mat1.rowmat =3;
for(int i=0;i<mat1.rowmat;i++)
{
for(int j=0;j<mat1.colmat;j++)
mat1.mat[i][j] = (float)rand();
}
printmat(&mat1);
testtranspose(&mat1,&mat2);
printmat(&mat2);
getchar();
}
I am new to C / C++ (3rd day or so :) ) and I had the same problem. My approach was slightly different in that I thought it would be nice to have a function that would return a transposed matrix. Unfortunately, as I found out, you cannot return a an array nor pass an array to a function in C++ (let alone a double array), but you can pass / return a pointer which works similar to an array. So this is what I did:
int * matrix_transpose(int * A, int A_rows, int A_cols){
int * B;
int B_rows, B_cols;
B_rows = A_cols; B_cols= A_rows;
B = new int [B_rows*B_cols];
for(int i=0;i<B_rows;i++){
for(int j=0;j<B_cols;j++){
B[i*B_cols+j]=A[j*A_cols+i];
}
}
return B;
};
The trick was in dynamic arrays. I used A_rows and B_rows as separate names (you can use only rows and cols) in order to make the problem less intricate and less confusing when reading code.
B = new int [rows*cols] // This is cool in C++.

Resources