Losing elements while printing a queue in C - c

This is my code :
typedef struct noeud{
int x;
struct noeud* suivant;
} noeud;
typedef noeud* file;
file enfiler(file f, int val){
file nv = (file) malloc(sizeof(noeud));
nv->x = val; nv->suivant = NULL;
if (f == NULL)
f = nv;
else {
file tmp = f;
while(tmp->suivant != NULL) tmp = tmp->suivant;
tmp->suivant = nv;
}
return f;
}
file defiler(file f){//removing an element of the FIFO data structure
if (f == NULL)
return f;
else {
file tmp = f;
f = f->suivant;//receiving address of next node, the last one points to NULL
free(tmp);
return f;
}
}
int tete(file f){
return f->x;//getting the element of the head
}
void init(file * f) {
*f = NULL;
}
void affiche(file f){//print data structure's elements
if (f == NULL)
printf("File vide.\n");
else {//emptying the FIFO data structure into tmp to access elements
file tmp; init(&tmp);
while(f != NULL){
tmp = enfiler(tmp, tete(f));
f = defiler(f);
}
int i = 0;
while(tmp != NULL) {//emptying tmp to original f
printf("F[%d] = %d\n", ++i, tete(tmp));
f = enfiler(f, tete(tmp));
tmp = defiler(tmp);
}
}
}
This is my input :
file f; init(&f);//initializing f to NULL
f = enfiler(f, 6);//adding elements
f = enfiler(f, 45);
f = enfiler(f, 78);
f = enfiler(f, 5);
affiche(f);
affiche(f);
affiche(f);
This is the output :
F[1] = 6
F[2] = 45
F[3] = 78
F[4] = 5
F[1] = 78
F[2] = 5
F[1] = 2036736 //this is a random value
With each void affiche(file f) two heads are being lost, I revised the function file defiler(file f) but can't seem to find an error, file enfiler(file f, int x) is also fine.
Thank you for your time!

In order to reverse the output, you construct and re-construct your queue. Your reconstruction does not re-link the same nodes. Instead, you just take the values and create two completely new lists. That means that the local variable f in afficher will usually be different when after entering and before leaving afficher. You can test that by adding the following statements:
void affiche(noeud *f)
{
printf("entree: %p\n", f);
// body of afficher function
printf("sortie: %p\n", f);
}
The problem is that the f in your calling function is not updated. It could point to recently free'd memory or to another valid node. In other words, your list will likely be corrupt.
The easiest way to fix that is by returning the new head, as in enfiler and defiler.

Related

What's wrong with my realloc doing on 2d-array

I am solving binary tree paths leet code programming question 257. I am having issue for one of the larger input where my code is getting segmentation fault. I suspect that there is an problem with my realloc but I am not able to figure it out.
Below is my approach:
Initially I started by dynamically allocating 80 bytes of memory of type char (80/8 = 10 rows)and storing the returned address to char **res variable.
char ** res = (char **)malloc(sizeof(char *) * sum);
I am calling findpath function recursively to find all the binary tree paths. Whenever one path is found , I dynamic allocate 100 bytes for each row index.
res[resIdx] = (char *)malloc(sizeof(char) * 100);
I have one global variable resIdx which points to the current row index where I copy the found binary tree path and increment the global variable resIdx.
if the resIdx becomes greater then total number of rows which was previously allocated then I do realloc of the memory but it looks like realloc is getting failed.
if (resIdx >= sum)
{
sum = sum + 10;
res = (char **)realloc(res,sizeof(char *) * sum); //Any issue here?
}
Can anyone please help me to figure out what's wrong I am doing in my code. Below is my full code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int sum;
int resIdx;
void findpath (struct TreeNode* root, int *ls,int ls_idx,char **res);
char ** binaryTreePaths(struct TreeNode* root, int* returnSize){
if (root == NULL)
{
*returnSize = 0;
return NULL;
}
resIdx = 0;
sum = 10;
char ** res = (char **)malloc(sizeof(char *) * sum);
int ls[100];
findpath(root,&ls[0],0,res);
*returnSize = resIdx;
return &res[0];
}
void findpath (struct TreeNode* root, int *ls,int ls_idx,char **res)
{
char temp[100];
int l=0,i=0;
if (root->left == NULL && root->right == NULL)
{
ls[ls_idx] = root->val;
ls_idx+=1;
if (resIdx >= sum)
{
sum = sum + 10;
res = (char **)realloc(res,sizeof(char *) * sum);
}
res[resIdx] = (char *)malloc(sizeof(char) * 100);
while (i < ls_idx)
{
if (i==0)
{
l = l + sprintf(&temp[l], "%d", ls[i]);
}
else
{
l = l + sprintf(&temp[l], "->%d", ls[i]);
}
i++;
}
strcpy(res[resIdx],temp);
resIdx++;
return;
}
ls[ls_idx] = root->val;
if (root->left != NULL)
{
findpath(root->left,ls,ls_idx+1,res);
}
if (root->right != NULL)
{
findpath(root->right,ls,ls_idx+1,res);
}
return;
}
The last argument to your findPath function is declared as a char** type; thus, when you make the call findpath(root,&ls[0],0,res); in binaryTreePaths, where the res variable is a char** type, a copy of that pointer is passed to the findPath function (most likely, but not necessarily, by placing that copy on the stack).
Then, if reallocation is required, the res = (char **)realloc(res,sizeof(char *) * sum); line in that function overwrites the value in the passed copy and, at the same time (if the call is successful – vide infra), will (probably) invalidate (i.e. free) the memory referenced by the previous address in that res copy. Thus, when control returns to the calling binaryTreePaths function, its own version of res will not have been modified and will remain pointing to that (now invalid) memory.
So, in order for your findPath function to be able to modify the given res argument, that must be passed as a pointer – in this case, a pointer to a char**, which will be of type char***; then, when called, you will need to pass the address of the res variable in binaryTreePaths.
Note also that directly overwriting a pointer in a call to realloc, as you have done in the line of code quoted above is dangerous. This is because, should that call fail, then you have lost the original data pointer (it will have been overwritten with NULL) and error recovery will be very difficult. You should save the return value in a temporary variable and only replace your original if the call succeeds.
With the code you have provided, I cannot properly test for any other errors but, taking the points above in hand, the below is a possible fix. See also: Do I cast the result of malloc?
int sum;
int resIdx;
void findpath(struct TreeNode* root, int* ls, int ls_idx, char*** res); // Note last argument type!
char** binaryTreePaths(struct TreeNode* root, int* returnSize)
{
if (root == NULL) {
*returnSize = 0;
return NULL;
}
resIdx = 0;
sum = 10;
char** res = malloc(sizeof(char*) * sum);
int ls[100];
findpath(root, &ls[0], 0, &res); // Pass ADDRESS of res
*returnSize = resIdx;
return &res[0];
}
void findpath(struct TreeNode* root, int* ls, int ls_idx, char*** res)
{
char temp[100];
int l = 0, i = 0;
if (root->left == NULL && root->right == NULL) {
ls[ls_idx] = root->val;
ls_idx += 1;
if (resIdx >= sum) {
sum = sum + 10;
char** test = realloc(*res, sizeof(char*) * sum);
if (test == NULL) {
// Handle/signal error
return;
}
*res = test; // Only replace original if realloc succeeded!
}
(*res)[resIdx] = malloc(sizeof(char) * 100);
while (i < ls_idx) {
if (i == 0) {
l = l + sprintf(&temp[l], "%d", ls[i]);
}
else {
l = l + sprintf(&temp[l], "->%d", ls[i]);
}
i++;
}
strcpy((*res)[resIdx], temp);
resIdx++;
return;
}
ls[ls_idx] = root->val;
if (root->left != NULL) {
findpath(root->left, ls, ls_idx + 1, res);
}
if (root->right != NULL) {
findpath(root->right, ls, ls_idx + 1, res);
}
return;
}

Problem adding unique char* to linked list

I am trying to implement a data structure where I have a list of char* values and an array that stores the number of occurrences for each unique char* value from cmd line. It's a bit messy, but I thought I had it figured it out until I tried testing it (each test does not have to be compiled differently, I just renamed each run to make the test names different).
Test cmd inputs:
test1 a b c d e f g
test2 a a b b c d d e f f g g
test3 a a a a a a a a a a a
test4 a a a a a a a a a a a b c c
test5 a j i q y z n f o p m a
test6 a a b b c d d e f f g
test7 a j k q e s l i h i a
test8 a j i q y z n f o p m
Based on these inputs, the table lengths for each should look like:
test1 table->length = 7 <- works
test2 table->length = 7 <- works
test3 table->length = 1 <- works
test4 table->length = 3 <- works
test5 table->length = 11 <- works
test6 table->length = 7 <- no work
test7 table->length = 9 <- no work
test8 table->length = 11 <- no work
Based on these results, I don't believe it's the length of argc (as tests 1, 2, 3 works) nor is it the number of unique *chars (as per tests 2, 3, 4,5). When running the code below, it either works and I get to the end of main(...), or, depending on the input, it will fail after displaying:
...
ptr address: 00DF04F4
ptr value: 00DF0510
test.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node {
char *path;
int index;
struct node *next;
} node;
typedef struct lookup {
struct node *head;
struct node *ptr;
int length;
int array[];
} lookup;
void add(lookup *table, char *path);
void search(lookup *table, char *path, int *i);
void add(lookup *table, char *path) {
int i = 0;
search(table, path, &i);
if(table->ptr == NULL) {
node *new_node = malloc(sizeof(node));
if (table->head == NULL) {
table->head = new_node;
table->head->next = NULL;
table->head->path = path;
table->array[0] = 1;
table->head->index = 0;
table->length = 1;
} else {
new_node->path = path;
new_node->next = table->head;
table->head = new_node;
table->array[i] = 1;
table->head->index = i;
table->length += 1;
}
} else {
table->array[table->ptr->index] += 1;
}
}
void search(lookup *table, char *path, int *i) {
if(table->head == NULL) {
table->ptr = NULL;
return;
}
table->ptr = table->head;
(*i) = 0;
while(table->ptr != NULL) {
printf("ptr address: %p\n", &(table->ptr));
printf("ptr value: %p\n", (table->ptr));
/* FAILURE POINT */
printf("%s\n", table->ptr->path);
printf("comparing ptr string: '%s' with given '%s'\n", table->ptr->path, path);
if(strcmp(table->ptr->path, path) == 0) {
printf("found match!\n");
return;
}
table->ptr = table->ptr->next;
(*i) += 1;
}
printf("could not find '%s' in table\n", path);
}
int main(int argc, char **argv) {
lookup *table = malloc(sizeof(lookup) + argc);
table->head = NULL;
int i = 1;
for(i; i < argc; i++) {
printf("\n\ntry adding: %s\n", argv[i]);
add(table, argv[i]);
}
printf("\n\n############\nfinished adding\n");
printf("table length: %d\n", table->length);
return 0;
}
I know the pointer isn't null (as I print it's address and value right before) yet I'm not sure why it stops execution where it does with seemingly normal input. Expected output (based on current code) should show each char* that is attempted to be added, the address and value of the pointer as search(...) searches the table, the current *char ptr is pointing to, what two *chars are being compared, whether or not a match was found, or if search(...) could not find the *char.

fprintf is not printing the data into the file

I have written a code in C. Inside the for loop in main(), I have written the following. When I run the code, the fprintf statement is not writing the data into the datafile. I am adding edges to a graph. While adding, I am checking whether the pairs are already in the list using adjacent list. If the pairs are not in the list, I am adding the edges, using the function call addEdge():
int main()
{
FILE *ed = NULL;
ed = fopen("c2.txt","w");
FILE *ls = NULL;
ls = fopen("e2.txt", "w");
FILE *lk = NULL;
lk = fopen("link2.txt","w");
if(ls == NULL){
printf("Error in opening file ls!\n");}
if(ed == NULL){
printf("Error in opening file ed!\n");}
if(lk == NULL){
printf("Error in opening file lk!\n");}
else
{
int src,dest;
int src1,dest1;
int i,k,v;
int NV = 500 #No. of nodes
int m = 10000 #No. of edges
int nblinks = 0; # edge counter:
double x[NV],x1[NV];
double x2[NV];
unifRand(x,x1,x2); // function call for infection rate:Pass only name of array:
int ss[NV];
data1(ss); // function call for generated data:
double sum,sum1 = 0.0;
double R = 0.00268; //Learning rate: // (i) 0.01 // ii. 0.001 // (iii) 0.00251 (iv)0.00268
double L[NV][NV-1];
double L1[NV][NV-1];
double L_old[NV][NV-1];
double L2[NV][NV-1];
double t = 0, dt = 0.1;
double C;
struct Graph* graph = createGraph(NV); // Function call for graph:
int d;
int nblinks = 0; // Edge counter:
L_old[0][1] = 0.01; // choice of initial coupling/guess : 0.02
for(i=0; i<NV-1; i++)
{
x2[i] = 0.02;
}
fprintf(ed,"True\t\tMeasured\t x[i]\t\t x1[i]\t\t x2[i]\t\tsum\t\t Error\t\ttime\tnode\n");
fprintf(ed,"------------------------------------------------------------------------------------------------------------\n");
fprintf(lk," Pair of Nodes:\n");
fprintf(lk,"---------------------------------------------------------------------\n");
for( i = 0, k = 1; i < NV-1; i++)
{
struct AdjListNode* temp = graph->array[i].head;
printGraph(graph, &sum, temp);
# if the adjacent node is not zero:
while(temp != NULL && temp->next != NULL)
{
fprintf(ls,"%d %d\n", i, temp->dest);
temp = temp->next;
while(nblinks < m)
{
#Random numbers for source and destination nodes:
int src1 = random()%NV;
int dest1 = random()%NV;
if(src1 < dest1)
{
src = src1;
dest = dest1;
}
else
{
src = dest1;
dest = src1;
}
int pairs[2] = {src, dest};
//If pairs are not in the list, add the edges then:
if(src != dest && pairs[2] != (i, temp->dest))
{
printf("%d\t%d\n",src,dest);
fprintf(lk,"(%d,%d)\t(%d,%d)\n", pairs[0],pairs[1],i, temp->dest);
addEdge(graph, src, dest);
nblinks++; // counter:
} // End if
} //End while1 :
} // End while 2:
# I have written my calculation here :
fprintf(ed,"%0.6lf\t%0.6lf\t%0.6lf\t%0.6lf\t%0.5lf\t\t%0.6lf\t%0.6lf\t%0.1lf\t%d\t%0.6lf\n", L[i][k],L1[0][1],x[i],x1[i],
x2[i],sum1,C, t,ss[k],L2[i][k]);
} // End for
} // End else
fclose(ed);
fclose(ls);
fclose(lk);
ed = NULL;
ls = NULL;
lk = NULL;
return 0;
}
This code is quite strange and some parts of it should not be compiled by c compiler.
E.g.:
int NV = 500 #No. of nodes
int m = 10000 #No. of edges
int nblinks = 0; # edge counter:
where #No. of nodes is like comment and int NV = 500 has no ; in the end - so is not completed line of code.
Style is also not perfect, e.g.:
if(ls == NULL){
printf("Error in opening file ls!\n");}
if(ed == NULL){
printf("Error in opening file ed!\n");}
if(lk == NULL){
printf("Error in opening file lk!\n");}
else
{
should be
if(ls == NULL)
{
printf("Error in opening file ls!\n");
return 1;
}
if(ed == NULL)
{
printf("Error in opening file ed!\n");
return 1;
}
if(lk == NULL)
{
printf("Error in opening file lk!\n");
return 1;
}
// no else needed after 3 way to the exit (return)
or better
if(!lk || !ed || !ls)
{
printf("Error in opening on of the files\n");
return 1;
}
In general, if all files are opened in the required mode (and after all writing are closed) no problem should be with fprintf except incorrect format string or wrong data for output.
UPDATE:
Just to check output, you can use stdout as the first argument of fprintf to see result at the screen (console), or make lk = stdout; instead of lk = fopen("link2.txt", "w");.
Then if you see data at the screen look what is wrong with the file.

fread and fwrite a linked list in C

Here is my struct:
struct Car{
char plateNum[10];
char returnDate[7];
int milage;
float income;
struct Car * next;
};
typedef struct Car Car;
I need to use fwrite and fread to store the value and load back in after. Is there an easy way?
To write a LL to a file
// Be sure to have opened the file in binary mode
Car *x = head;
// Walk the list and write each node.
// No need to write the next field - which happens to be the last one.
// v-----------------v size of data before the `next` field
while (x && fwrite(x, offsetof(Car, next), 1, out_stream) == 1) {
x = x->next;
}
To read records from a file into a LL and return the head node:
#include <stddef.h>
// Be sure to have opened the file in binary mode
Car *ReadCars(FILE *in_stream) {
Car Top;
Top.next = NULL; // code only uses the `next` field of Top
Car *previous = &Top;
Car x;
// While another record was successfully read ...
while (fread(&x, offsetof(Car, next), 1, in_stream) == 1) {
// Fill the next field
x.next = NULL;
// Allocate space and copy
previous->next = malloc(sizeof *(previous->next));
assert(previous->next);
*(previous->next) = x;
// Advance to the next
previous = previous->next;
}
return Top.next;
}
The following was written off the cuff by me and has not been tested, so it might need tweaking. Please also note; for the sake of time, I have not tested the return value of fwrite and fread or checked for read errors. YOU SHOULD DO THIS.
Writing the file
int length = lengthOfList(bar); // Assuming you've already created bar as a linked list of Cars
Car foo[length];
putLinkedListIntoArray(&bar, foo);
FILE* fh = NULL;
if((fh = fopen("filename", "wb")) == NULL) {
// Error and die
}
fwrite(&length, sizeof(int), 1, fh);
fwrite(bar, sizeof(Car), length, fh);
fclose(fh);
Reading the file
FILE* fh = NULL;
if((fh = fopen("filename", "rb")) == NULL) {
// Error and die
}
int length;
fread(&length, sizeof(int), 1, fh);
Car foo[length];
fread(foo, sizeof(Car), length, fh);
fclose(fh);
relinkCarList(foo, length);
Functions
int lengthOfList(Car* start) {
int length;
for(length = 0; start->next != NULL; length++) {
start = start->next;
}
return length;
}
void putLinkedListIntoArray(Car* start, Car* array) {
for(int i = 0; start->next != NULL; i++) {
array[i] = *start;
start = start->next;
}
}
void relinkCarList(Car* array, int length) {
for(int i = 0; i < length; i++) {
if(i < length - 1) {
array[i].next = array[i + 1].next;
}
}
}

having trouble with storing string in linked list

I am having trouble storing a string in a linked list. This is the function that inserts a node to the list:
void insert_rec(rec_ptr *h_ptr, rec_ptr *t_ptr, int a, int b, int c, char* cs)
{
rec_ptr new_ptr;
new_ptr = rec_ptr( malloc( sizeof(REC) ) );
if(new_ptr != NULL)
{
new_ptr->x = a;
new_ptr->y = b;
new_ptr->z = c;
new_ptr->c = cs;
new_ptr->next = NULL;
if(*h_ptr == NULL){
*h_ptr = new_ptr;
}
else{
(*t_ptr)->next = new_ptr;
}
*t_ptr = new_ptr;
}
else
{
printf("%d %d %d not inserted. No memory available.\n",a,b,c);
}
}
This is the function that reads input from an output file. I am inserting a string into the list as a char*. The fscanf() has read the string in correctly.
void read_from_input2(rec_ptr & hptr, rec_ptr & tptr)
{
fp3=fopen("input2.txt","r");
if (fp3 == NULL)
printf("Error: Couldn't open file: input2.txt\n");
else
{
while(!feof(fp3))
{
int x,y,z;
char c1[10];
fscanf(fp3,"%d",&x);
fscanf(fp3,"%d",&y);
fscanf(fp3,"%d",&z);
fscanf(fp3,"%s",c1);
char *c2 = c1;
insert_rec(&hptr,&tptr,x,y,z,c2);
}
}
fclose(fp3);
}
This is the function where I am having problems. When I extract the data from the linked list, the variable c1 outputs garbage.
void write_to_output2(rec_ptr hptr)
{
fp4=fopen("output2.txt","w");
if (fp4 == NULL)
printf("Error: Couldn't open file: output2.txt\n");
else
{
if(hptr == NULL){
printf("List is empty.\n\n");
}
else{
while(hptr != NULL)
{
int x,y,z;
char *c1,*c2;
x = hptr->x;
y = hptr->y;
z = hptr->z;
c1 = hptr->c;
c2 = get_class(x,y,z);
fprintf(fp4,"%d %d %d %s %s\n",x,y,z,c1,c2);
hptr = hptr->next;
}
}
}
fclose(fp4);
}
If anyone can see my error please help me out. Thanks.
char c1[10];
/* ... */
char *c2 = c1;
insert_rec(&hptr,&tptr,x,y,z,c2);
The problem is c1 is on the stack of read_from_input2 and then you store a pointer to its contents. It will go out of scope when the while ends thus access to it will be invalid.
You'll want to strdup it (or equivalent).
char *c2 = strdup(c1);
/* or */
new_ptr->c = strdup(cs);
And don't forget to free it at some point.

Resources