Infinite loops with a linked list - c

I'm working on a program that takes an input of numbers from stdin and computes the median of the sequence and prints it out as a float. I'm currently getting an infinite loop in the function
len(struct node *)
at the for loop and I'm not sure why.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
float *val;
struct node *next;
};
int len(struct node *list) {
int i = 0;
struct node *temp = list;
for (i = 0; temp != NULL; i++) {
temp = temp->next;
}
return i;
}
float median(int size, struct node list) {
struct node temp = list;
int i = 0;
if (size == 1) {
return *temp.val;
} else
if (size == 2) {
return (*(temp.val) + *(temp.next->val)) / 2;
} else {
if (size / 2 == 1) {
for (i = 3; i != (size / 2) - 1; i++) {
temp = *(temp.next);
}
return *temp.val;
} else {
for (i = 3; i != (size / 2); i++) {
temp = *(temp.next);
}
return (*(temp.val) + *(temp.next->val)) / 2;
}
}
}
int main() {
struct node *tmpnode;
tmpnode = malloc(sizeof(struct node));
tmpnode->next = NULL;
struct node *list = NULL;
list = tmpnode;
float temp = 0;
int err = 0;
int size = 0;
while ((err = scanf("%f", &temp)) != EOF) {
if (err < 1) {
fprintf(stderr, "Error: non-integer character inputted\n");
return 1;
}
tmpnode->val = &temp;
tmpnode->next = list;
list = tmpnode;
}
size = len(list);
if (size == 0) {
fprintf(stderr, "Error: no inputs found");
return 1;
}
printf("%f\n", median(size, *list));
return 0;
}
Edit: I've fixed the infinite loop, but now I'm getting a segfault at temp = *(temp.next) in median(). Do I need to allocate for temp?

You created only one node and assigned next of the node to itself, so this is cause of the infinite loop.
Create new nodes and link them in the input loop.
Assigning address of temp to all nodes is also not good.
Your main() function should be like this:
int main(void){
struct node *tmpnode;
tmpnode = malloc(sizeof(struct node));
if(tmpnode == NULL){
perror("malloc 1");
return 1;
}
tmpnode->next = NULL;
struct node *list = NULL;
list = tmpnode;
float temp = 0;
int err = 0;
int size = 0;
while((err = scanf("%f", &temp)) != EOF){
if(err < 1){
fprintf(stderr, "Error: non-integer character inputted\n");
return 1;
}
tmpnode->val = malloc(sizeof(float));
if(tmpnode->val == NULL){
perror("malloc 2");
return 1;
}
*tmpnode->val = temp;
tmpnode->next = malloc(sizeof(struct node));
if(tmpnode->next == NULL){
perror("malloc 3");
return 1;
}
tmpnode = tmpnode->next;
tmpnode->val = NULL;
tmpnode->next = NULL;
}
size = len(list);
if(size == 0){
fprintf(stderr, "Error: no inputs found");
return 1;
}
printf("%f\n", median(size, *list));
/* code to free the list should be here */
return 0;
}
(I gave input 1 2 3 4 5 and this program's output was 1.500000, which might be wrong)

If you're looking for the median you would have to arrange the nodes in order and get the number that is in the middle.If the number of nods is even and there is no middle you should add the two middlemost numbers and divide them by two.
Is the sequence in order? If not you're miscalculating the median.
Supposing the sequence is in order.
I didn't really understand the usefulness of this statement
if(size/2 == 1)
Maybe you're trying to see if the size is odd. In that case you should do:
> if(size%2 == 1)
Why the list is probably looping might be due to this
for(i = 3; i != (size/2); i++){
temp = *(temp.next);
}
Suppose you pass a 5 to the function size/2=2 (decimal part is lost), so it'll keep on going until an overflow occurs and it actually reaches 2, making your program most probably seg_fault in the process.
Start from i=0, because even though you started from 3 your current node is not the third one but the FIRST ONE.
Good luck hope this helps!!!!

Related

Problems regarding an multiple choice question program

I have created a program to generate the result of a multiple choice exam. The program was supposed to show the total number of mistakes, blank answers and the number of the question which were answered incorrectly. For the following input:
6
1..223
(Here . means blank answer)
123124
The output was supposed to be:
Your result:
Mistakes: 3
Blanks: 2
Your mistakes are following:
4 5 6
Your blanks are following:
2 3
But the code shows undefined behavior. It seems to go through infinite loop. Expecting solution to my problem shortly. Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
char data;
struct node* next;
}node;
void printNode(node* head)
{
node* local = head;
int i = 0;
if(local -> data == 0)
{
printf("0");
return;
}
while(local != NULL)
{
if(i == 3)
{
i = 0;
printf("\n");
}
printf("%d\t", local -> data);
local = local -> next;
++i;
}
}
void freeNode(node** head)
{
node* temp = (*head);
while((*head) != NULL)
{
(*head) = (*head) -> next;
free(temp);
temp = (*head);
}
}
int main()
{
int n, i, flagB, flagM, blnk, mstk;
blnk = mstk = flagB = flagM = 0;
printf("Enter the number of questions: ");
scanf("%d", &n);
char ques[n], ans[n];
if(n == 0)
return 0;
node* headM = (node*)malloc(sizeof(node));
node* nodeM;
node* headB = (node*)malloc(sizeof(node));
node* nodeB;
printf("Enter your given answers: ");
fflush(stdin);
for(i = 0; i < n; ++i)
{
scanf("%c", &ques[i]);
}
fflush(stdin);
ques[n] = '\0';
printf("Enter the solution: ");
for(i = 0; i < n; ++i)
{
scanf("%c", &ans[i]);
}
ans[n] = '\0';
for(i = 0; i < n; ++i)
{
if(ques[i] == '.')
{
++blnk;
if(flagB == 0)
{
headB -> data = i + 1;
headB -> next = NULL;
nodeB = headB;
continue;
}
nodeB -> next = (node*)malloc(sizeof(node));
nodeB = nodeB -> next;
nodeB -> data = i + 1;
nodeB-> next = NULL;
flagB = 1;
}
else if(ques[i] != ans[i])
{
++mstk;
if(flagM == 0)
{
headM -> data = i + 1;
headM -> next = NULL;
nodeM = headM;
continue;
}
nodeM -> next = (node*)malloc(sizeof(node));
nodeM = nodeM -> next;
nodeM -> data = i;
nodeM-> next = NULL;
flagM = 1;
}
}
printf("Your result:\n\tMistakes: %d\n\tBlanks: %d\n", mstk, blnk);
printf("Your mistakes are follwing:\n");
printNode(headM);
printf("\nYour blanks are follwing:\n");
printNode(headB);
freeNode(&headM);
freeNode(&headM);
return 0;
}
Here are some additional thoughts. What makes your code very convoluted and hard to debug and keep the logic straight is you are mixing your linked-list Add function within the logic of your blanks and mistakes and using special conditions to handle adding the first node and subsequent nodes. This make things difficult to test and debug. If you need to add nodes to a linked-list, then write an add() function that you can thoroughly test and debug before putting it to use in your code.
Your VLAs ques and ans are too short to hold a string of n characters, at minimum they must be n + 1 characters long to provide storage for the nul-termining character that marks the end of the string. Ideally, you will make them at least 2-character longer to also hold the '\n' which will allow you to take input with fgets() rather than looping scanf() a character at a time -- which is just nuts.
You do not need to pass the address of the pointer to freeNode() simply pass a pointer. Sure freeNode() will receive a copy of the pointer -- but it will contain the original address -- and since you don't have to make any changes to that pointer available back to the caller, there is no need to pass the address of the pointer (there won't be any list left to worry about when you are done...)
So putting those pieces together, adding an add() function to add to your linked lists (See Linus on Understanding Pointers for why a pointer-to-pointer is used to iterate to the end), and adding a simple empty_stdin() function to remove the '\n' left in stdin from reading n with scanf() before making calls to fgets() later for ques and ans, you could do:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* simple function to empty stdin to end-of-line */
void empty_stdin (void)
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
typedef struct node
{
int data;
struct node *next;
} node;
node *add(node **head, int v)
{
node **ppn = head, /* pointer to pointer to head */
*pn = *head, /* pointer to head */
*newn = malloc (sizeof *newn); /* allocate new node */
if (!newn) { /* validate allocation */
perror ("malloc-node");
return NULL;
}
newn->data = v; /* initialize members values */
newn->next = NULL;
while (pn) { /* iterate to end of list */
ppn = &pn->next;
pn = pn->next;
}
return *ppn = newn; /* add & return new node */
}
void printNode (node *head)
{
for (; head; head = head->next)
printf (" %d", head->data);
putchar ('\n');
}
void freeNode(node *head)
{
while (head != NULL)
{
node *victim = head;
head = head->next;
free(victim);
}
}
int main()
{
int n, i, blnk, mstk;
blnk = mstk = 0;
node *headM = NULL; /* declare pointers and initialize NULL */
node *headB = NULL;
printf ("Enter the number of questions: ");
/* you must VALIDATE every user-input */
if (scanf ("%d", &n) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
empty_stdin(); /* remove '\n' (and any other chars from user) */
/* before calling fgets() below */
if (n == 0) /* check 0 BEFORE VLA declaration */
return 0;
char ques[2*n], ans[2*n]; /* declare question/answer VLAs, don't skimp */
printf("Enter your given answers: ");
if (!fgets(ques, sizeof ques, stdin)) /* read ques from stdin */
return 1;
ques[strcspn(ques, "\r\n")] = 0; /* trim '\n' from end of ques */
printf("Enter the solution: ");
if (!fgets(ans, sizeof ans, stdin)) /* read ans from stdin */
return 1;
ans[strcspn(ans, "\r\n")] = 0; /* ditto for ans */
for(i = 0; i < n; ++i) /* loop n times */
{
if(ques[i] == '.') /* if blank */
{
add (&headB, i + 1); /* add to list headB */
++blnk; /* increment counter */
}
else if(ques[i] != ans[i]) /* if mistake */
{
add (&headM, i + 1); /* add to list headM */
++mstk; /* increment counter */
}
}
printf ("Your result:\n\tMistakes: %d\n\tBlanks: %d\n"
"Your mistakes are following:\n", mstk, blnk);
printNode(headM);
printf("\nYour blanks are following:\n");
printNode(headB);
freeNode(headM); /* no need to pass the address of the pointer to free */
freeNode(headB); /* there won't be a list left when freeNode is done */
return 0;
}
There is a lot there, so go through it slowly.
Example Use/Output
$ ./bin/llquestions
Enter the number of questions: 6
Enter your given answers: 1..223
Enter the solution: 123124
Your result:
Mistakes: 2
Blanks: 2
Your mistakes are following:
4 6
Your blanks are following:
2 3
(note: in 1..223 and 123124, 5 is not a mistake, the 2 is in the correct position at the end)
Look things over and let me know if you have further questions.
I made some changes to this code, check this out.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node node;
struct Node
{
int data;
struct Node * next;
};
void printNode(node *head)
{
node *local = head;
while (local != NULL)
{
printf("%d ", local->data);
local = local->next;
}
}
void freeNode(node **head)
{
node *temp = (*head);
while ((*head) != NULL)
{
(*head) = (*head)->next;
free(temp);
temp = (*head);
}
}
int main()
{
int n, i, flagB = 0, flagM = 0, blnk = 0, mstk = 0;
blnk = mstk = flagB = flagM = 0;
printf("Enter the number of questions: ");
scanf("%d", &n);
char ques[n], ans[n];
if (n == 0)
return 0;
node *headM = (node*) malloc(sizeof(node));
headM->data = 0;
node *nodeM = headM;
node *headB = (node*) malloc(sizeof(node));
headB->next = 0;
node *nodeB = headB;
printf("Enter your given answers: ");
for (i = 0; i < n; ++i)
{
scanf("%s", &ques[i]);
}
ques[n] = '\0';
fflush(stdin);
printf("Enter the solution: ");
for (i = 0; i < n; ++i)
{
scanf("%s", &ans[i]);
}
ans[n] = '\0';
fflush(stdin);
for (i = 0; i < n; ++i)
{
if (ques[i] == '.')
{ ++blnk;
if (flagB == 0)
{
nodeB->data = i + 1;
nodeB->next = NULL;
flagB = 1;
continue;
}
nodeB->next = (node*) malloc(sizeof(node));
nodeB = nodeB->next;
nodeB->data = i + 1;
nodeB->next = NULL;
}
else if (ques[i] != ans[i])
{ ++mstk;
if (flagM == 0)
{
nodeM->data = i + 1;
nodeM->next = NULL;
flagM = 1;
continue;
}
nodeM->next = (node*) malloc(sizeof(node));
nodeM = nodeM->next;
nodeM->data = i + 1;
nodeM->next = NULL;
//flagM = 1; //You made a mistake here
}
}
nodeM = headM;
nodeB = headB;
printf("Your result:\n\tMistakes: %d\n\tBlanks: %d\n", mstk, blnk);
printf("Your mistakes are following question numbers:\n");
if (mstk != 0)
printNode(headM);
else
printf("No Mistakes\n");
printf("\nYour blanks are following question numbers:\n");
if (blnk != 0)
printNode(headB);
else
printf("No Blanks\n");
freeNode(&headM);
freeNode(&headM);
return 0;
}

C code, compiler Xcode, detected source and destination buffer overlap

I'm doing a project for school in which I have to create a program that plays go fish. In which a deck of cards is in a doubly linked list. I read the cards from a file in the function Addcard. I have a function to print the cards and a function that is supposed to shuffle the cards. I have ot use the parameters of the struct to implement the cards. I sometimes see the error "detected source and destination buffer overlap" when I run the shuffle function, sometimes not. When the error comes up it says Thread 1: signal SIGABRT next to a string copy function. I believe it has something to do with the buffer size of some kind of allocated memory being too small, but I don't really know how to fix it. Any help would be more then appreciated. Here is an excerpt of the code I have written.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
typedef struct card_s{
char suit[7];
int value;
struct card_s *next, *previous;
}card;
int rand_gen(int count){
double frac;
frac = (double)rand()/((double)RAND_MAX+1);
return floor(count * frac); //random number in [0, count]
}
void addCard(card *p, card **hl, card **hr, FILE *inp){
card *temp; // pointer to a node_t
temp = (card *)malloc(sizeof (card)); // new node creation
fscanf(inp, "%d", &temp->value);
fscanf(inp, "%s", temp->suit);
if (*hl == NULL){ // if left head is null, i.e., list is empty
temp->previous = NULL;
temp->next = NULL;
*hl = temp;
*hr = temp;
}
else if (p->next == NULL){ // if adding at the end of list
temp->previous = p;
temp->next = NULL;
p->next = temp;
*hr = temp;
}
else{ // if adding to the middle of the list
temp->next = p-> next;
temp->previous = p;
p->next = temp;
temp->next->previous = temp;
}
}
void Print(card **headl) { //this function prints from left to right only
card *temp;
temp = (*headl);
while(temp != NULL) {
printf("|");
printf("%d", temp->value);
if(strcmp(temp->suit,"hea")==0) {
printf("♥");
}
if(strcmp(temp->suit,"clu")==0) {
printf("♣");
}
if(strcmp(temp->suit,"spa")==0) {
printf("♠");
}
if(strcmp(temp->suit,"dia")==0) {
printf("♦");
}
printf("|");
//printf("%s ", temp->suit);
temp = temp->next;
}
}
void Print1(card **headl) { //this function prints from left to right only
card *temp;
temp = (*headl);
while(temp != NULL) {
for(int i = 0; i < 13; i++) {
printf("|");
if(temp->value == 11){
printf("J");
}
else if(temp->value == 12) {
printf("Q");
}
else if(temp->value == 13) {
printf("K");
}
else if(temp->value == 14) {
printf("A");
}
else {
printf("%d", temp->value);
}
if(strcmp(temp->suit,"h")==0) {
printf("♥");
}
if(strcmp(temp->suit,"c")==0) {
printf("♣");
}
if(strcmp(temp->suit,"s")==0) {
printf("♠");
}
if(strcmp(temp->suit,"d")==0) {
printf("♦");
}
printf("|");
//printf("%s ", temp->suit);
temp = temp->next;
}
printf("\n");
}
}
void swap(card *pt, int i, int j) {
card *temp;
temp = (card *)malloc(sizeof(card));
card *temp1 = pt, *temp2 = pt; //creates temperaries that start from the head left
for(int x = 0; x < i; x++) { //counts the number of nodes until i
temp1 = temp1->next;
}
for(int x = 0; x < j; x++) { //counts the number of nodes until j
temp2 = temp2->next;
}
temp->value = temp1->value; //swaps the information not the nodes
strcpy(temp->suit,temp1->suit);
temp1->value = temp2->value;
strcpy(temp1->suit, temp2->suit);
temp2->value = temp->value;
strcpy(temp2->suit, temp->suit);
}
int main(void) {
FILE *inp = NULL;
inp = fopen("cards.txt", "r");
srand((int)time(NULL));
card *headl = NULL, *headr = NULL;
for(int i = 0; i < 52; i++) {
addCard(headr, &headl, &headr, inp);
}
if(inp == NULL) {
printf("No file found");
return -1;
}
printIntro();
printf("\n");
Print1(&headl);
printf("\n");
printf("\n");
for(int i = 0; i <= 45; i++) { //does the swap function swap number times
swap(headl, rand_gen(52), rand_gen(52));
}
Print1(&headl);
return(0);
}
You have an error message saying "detected source and destination buffer overlap", near a string copy function, which copies data from a source to a destination...
Are there any instances of strcpy where the source and dest might point to the same memory?
I see these two lines:
card *temp1 = pt, *temp2 = pt; //creates temperaries that start from the head left
//advance `temp1` `i` times, and `temp2` `j` times
...
strcpy(temp1->suit, temp2->suit);
What happens when i and j are the same value?

segmentation fault in a linked list while loop?

I'm trying to setup a graph in C. I tried the graph with user input and it works perfectly. However, i am trying to implement a read from file. The last else statement is where the error is coming from because when i commented it out it compiles without any problems. I have included a comment over the block i think that has the problem. Please let me know if there is anything else needed for this question.
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node* next;
};
//int counter and mainVertex would be used to determine if graph is connected.
// void graphConnection(){
//
//
//
//
//
//
// }
char* deblank(char* input)
{
int i,j;
char *output=input;
for (i = 0, j = 0; i<strlen(input); i++,j++)
{
if (input[i]!=' ')
output[j]=input[i];
else
j--;
}
output[j]=0;
return output;
}
struct node *G[1000];
int counter = 0;
char *mainVertex;
void readingEachLine(){
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
//Read file and exit if fail
fp = fopen("test.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
line = deblank(line);
int i = 0;
struct node* cursor = malloc(sizeof(struct node));
struct node* secondcursor = malloc(sizeof(struct node));
struct node* tempitem;
while(line[i] != '\n'){
//If its the first of the line look into the array and set struct cursor to the corresponding
//array position
if (i == 0){
mainVertex[counter] = line[0];
int convertor = line[i] - '0';
cursor = G[convertor];
counter++;
}
//if its not the first, then set a struct with that number as data
else{
tempitem = malloc(sizeof(struct node));
int convertor = line[i] - '0';
tempitem->data = convertor;
tempitem->next = NULL;
}
//if there is no element connected to the struct in array, connect the tempitem
if (cursor->next == NULL){
cursor->next = tempitem;
}
//If there are already connected elements, loop until the end of the linked list
//and append the tempitem
//ERROR: I GET SEGMENTATION FAULT FROM HERE. TRIED AFTER COMMENTING IT OUT
else{
secondcursor = cursor;
while(secondcursor->next != NULL){
secondcursor = secondcursor->next;
}
secondcursor->next = tempitem;
}
i++;
}
printf("\n");
}
}
int main(void){
for (int i = 1; i < 1000; i++)
{
G[i]= malloc(sizeof(struct node));
G[i]->data = i;
G[i]->next = NULL;
}
readingEachLine();
}
EDIT: This is how the text file looks like:
1 3 4
2 4
3 1 4
4 2 1 3
Your code has several misconceoptions:
Apparently, you can have a maximum of 1,000 nodes. You have an array G of 1,000 head pointers to linked lists. Don't allocate memory for all 1,000 nodes at the beginning. At the beginning, all lists are empty and an empty linked list is one that has no node and whose head is NULL.
In your example, cursor is used to iterate oer already existing pointers, so don't allocate memory for it. If you have code like this:
struct node *p = malloc(...);
// next use of p:
p = other_node;
you shouldn't allocate. You would overwrite p and lose the handle to the allocated memory. Not all pointers have to be initialised with malloc; allocate only if you create a node.
Your idea to strip all spaces from a line and then parse single digits will fail if you ever have more then 9 nodes. (But you cater for 1,000 node.) Don't try to parse the numbers yourself. There are library functions for that, for example strtol.
It is not clear what mainVertex is supposed to be. You use it only once, when you assign to it. You treat it like an array, but it is a global pointer, initialised to NULL. When you dereference it, you get undefined behaviour, which is where your segmentation fault probably comes from.
Here's a program that does what you want to do. (It always inserts nodes at the head for simplicity and it should have more allocation checks.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum {
maxNodes = 1000
};
struct node{
int data;
struct node* next;
};
struct node *G[maxNodes];
size_t nnode = 0;
int read_graph(const char *fn)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
fp = fopen(fn, "r");
if (fp == NULL) return -1;
while (getline(&line, &len, fp) != -1) {
char *p;
char *end;
int id;
int n;
id = strtol(line, &end, 10);
if (end == line) continue;
if (id < 1 || id > maxNodes) break;
if (id > nnode) nnode = id;
id--;
p = end;
n = strtol(p, &end, 10);
while (p != end) {
struct node *nnew = malloc(sizeof(*nnew));
nnew->data = n - 1;
nnew->next = G[id];
G[id] = nnew;
p = end;
n = strtol(p, &end, 10);
}
}
fclose(fp);
free(line);
return 0;
}
int main(void)
{
if (read_graph("test.txt") < 0) {
fprintf(stderr, "Couldn't gread raph.\n");
exit(1);
}
for (int i = 0; i < nnode; i++) {
struct node *p = G[i];
if (p) {
printf("%d:", i + 1);
for (; p; p = p->next) {
printf(" %d", p->data + 1);
}
puts("");
}
}
for (int i = 0; i < nnode; i++) {
struct node *p = G[i];
while (p) {
struct node *old = p;
p = p->next;
free(old);
}
}
return 0;
}

Sorting a linked list using merge sort

Given this problem:
Write a function that takes two date of birth structures as input and
returns -1, 0, 1 if the first parameter is less than, equal to or
greater than the second parameter respectively. Using your function,
write a recursive mergeSort program to sort the linked list of student
records in increasing order of their age (do not use arrays, use
linked list only).
here is what I wrote:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*Recursive Merge Sort to sort linked list of students in increasing order
of their age*/
/*A structure dateofbirth is created to store date of birth of each
student*/
struct dateofbirth {
int date;
int month;
int year;
};
/*Another structure student is created whihc contains information about a
student and it is also a nested structure that contains another structure
dateofbirth*/
struct student {
char firstname[64];
struct dateofbirth d;
int height;
float weight;
struct student *next;
};
/*Some pointers are made global as they will be used many a times in the
programs*/
struct student *temp = NULL, *start = NULL, *end = NULL;
/*comparedob will take two dateofbirth structures and compare them which one
is greater */
int comparison(struct dateofbirth d1,struct dateofbirth d2) {
if (d1.year > d2.year)
return 1;
else if (d1.year < d2.year)
return -1;
else if (d1.month > d2.month)
return 1;
else if (d1.month < d2.month)
return -1;
else if (d1.date > d2.date)
return 1;
else if (d1.date < d2.date)
return -1;
else return 0;
}
/*It displays the linked list starting from the first till the last*/
void display() {
temp = start;
while (temp != NULL) {
printf("%s, ", temp->firstname);
if (temp->d.month < 10)
printf("%d0%d%d, ", temp->d.date, temp->d.month, temp->d.year);
else
printf("%d%d%d, ", temp->d.date, temp->d.month, temp->d.year);
printf("%d, ", temp->height);
printf("%.2f\n", temp->weight);
temp = temp->next;
}
}
/*It reads from the file*/
void readdata() {
int a;
if (start == NULL) { /*This case will be implemented when the first record is read
from the file*/
temp = (struct student*) malloc(sizeof(struct student));
if (temp == NULL) {
printf("\nNot enough memory");
}
scanf("%s", (*temp).firstname);
scanf("%d", &a);
(*temp).d.date = a / 1000000;
(*temp).d.month = (a % 1000000) / 10000;
(*temp).d.year = a % 10000;
scanf("%d", &(*temp).height);
scanf("%lf", &(*temp).weight);
temp->next = NULL;
start = temp;
end = temp;
} else { /*For all subsequent records this case will be implemented*/
temp = (struct student*) malloc(sizeof(struct student));
if (temp == NULL) {
printf("\nNot enough memory");
}
scanf("%s", (*temp).firstname);
scanf("%d", &a);
(*temp).d.date = a / 1000000;
(*temp).d.month = (a % 1000000) / 10000;
(*temp).d.year = a % 10000;
scanf("%d", &(*temp).height);
scanf("%lf", &(*temp).weight);
temp->next = NULL;
end->next = temp;
end = temp;
}
}
/*This function will swap two student record with the help of pointers*/
void swap(struct student* s1,struct student* s2) {
struct student s;
strcpy(s.firstname, (*s1).firstname);
strcpy((*s1).firstname, (*s2).firstname);
strcpy((*s2).firstname, s.firstname);
s.d.date = (*s1).d.date;
(*s1).d.date = (*s2).d.date;
(*s2).d.date = s.d.date;
s.d.month = (*s1).d.month;
(*s1).d.month = (*s2).d.month;
(*s2).d.month = s.d.month;
s.d.year = (*s1).d.year;
(*s1).d.year = (*s2).d.year;
(*s2).d.year = s.d.year;
s.height= (*s1).height;
(*s1).height = (*s2).height;
(*s2).height = s.height;
s.weight = (*s1).weight;
(*s1).weight = (*s2).weight;
(*s2).weight = s.weight;
}
/*This function is used to find the middle record in a linked list by making
one pointer move at a double pace than the other*/
void middle(struct student* head, struct student** s1, struct student** s2) {
struct student* x = NULL, *y = NULL;
if (head == NULL || head->next == NULL) {
*s1=head;
*s2=NULL;
} else {
x = head;
y = head->next;
while (y != NULL) {
y=y->next;
if (y != NULL) {
x = x->next;
y = y->next;
}
}
*s1 = head;
*s2 = x->next;
x->next = NULL;
}
}
/*This function will combine both the independently sorted linked lists of
records of student*/
struct student* merge(struct student* a,struct student* b) {
struct student* final = NULL; // final will store the result of merging 'a' and 'b'
if (a == NULL)
return (b);
else if (b == NULL)
return (a);
if (comparison((*a).d, (*(b)).d) == 1) {
final = a;
final->next = merge(a->next, b);
} else {
final=b;
final->next = merge(a, b->next);
}
return (final);
}
/*Recursive merge sort*/
void mergesort(struct student** Ref) {
struct student* base = *Ref; /*Ref is a pointer to pointer which will point to
the starting record so that we do not lose the reference of the starting
record in the process of merging*/
struct student* a = NULL; //Variable pointer
struct student* b = NULL; //Variable pointer
if ((base == NULL) || (base->next == NULL))
return;
middle(base, &a, &b);
mergesort(&a);
mergesort(&b);
*Ref = merge(a,b);
}
void main() {
int m, i;
scanf("%d", &m);
printf("%d\n", m);
for (i = 0; i < m; i++)
readdata();
mergesort(&start);
display();
}
The program is sorting, but the weight properties reported in the output are changed to zero. Why is that happening?

realloc in recursion in trees

I am trying to find the maximum sum leaf to root path in a Binary Tree as in below
http://www.geeksforgeeks.org/find-the-maximum-sum-path-in-a-binary-tree/
1) I am unable to find why the path doesn't get printed in the main()
Is this because of wrong reallocs in the function.?
2) Also is my free correct?
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
/* A tree node structure */
struct node
{
int data;
struct node *left;
struct node *right;
};
// Returns the maximum sum and prints the nodes on max sum path
int maxsumtoleaf(struct node *node,int** path,int &height)
{
// base case
if (node == NULL)
return 0;
printf("\n At node %d,",node->data);
if (node->left==NULL && node->left==NULL) {
*path=(int*)realloc(*path,sizeof(int));
*path[0]=node->data;
height=1;
printf("\n value is %d,",*path[0]);
return node->data;
}
// find the target leaf and maximum sum
int rightheight=0,leftheight=0;
int *path1=NULL,*path2=NULL;
int left=maxsumtoleaf (node->left,&path1,leftheight);
int right=maxsumtoleaf (node->right,&path2,rightheight);
if ( left > right ) {
printf("\nbefore left is");
for(int i=0;i<leftheight;i++)
printf("%d,",path1[i]);
path1=(int*)realloc(path1,sizeof(int)*(leftheight+1));
if ( path1 == NULL ) {
printf("Out of Memory!\n");
return 0;
}
path1[leftheight]=node->data;
height=leftheight+1;
printf("\nafter left %d is ",leftheight);
for(int i=0;i<height;i++)
printf("%d,",path1[i]);
path=&path1;
return left+node->data;
} else {
printf("\nbefore right is");
for(int i=0;i<rightheight;i++)
printf("%d,",path2[i]);
path2=(int*)realloc(path2,sizeof(int)*(rightheight+1));
if ( path2 == NULL ) {
printf("Out of Memory!\n");
return 0;
}
path2[rightheight]=node->data;
height=rightheight+1;
printf("\nafter right is");
for(int i=0;i<height;i++)
printf("%d,",path2[i]);
path=&path2;
return right+node->data;
}
// return maximum sum
}
/* Utility function to create a new Binary Tree node */
struct node* newNode (int data)
{
struct node *temp = new struct node;
temp->data = data;
temp->left = NULL;
temp->right = NULL;
return temp;
}
/* Driver function to test above functions */
int main()
{
struct node *root = NULL;
/* Constructing tree given in the above figure */
/* (8<--2->-4)<-10->7 */
root = newNode(10);
root->left = newNode(-2);
root->right = newNode(7);
root->left->left = newNode(8);
root->left->right = newNode(-4);
int sum=0;
int** path=NULL;
int height=0;
sum = maxsumtoleaf(root,path,height);
printf ("\nSum of the nodes is %d ,len=%d", sum,height);
printf ("\nPath is ");
for(int i=0;i<height;i++)
printf("%d,",*path[i]);
free(path);
getchar();
return 0;
}
Output:
At node 10,
At node -2,
At node 8,
value is 8,
At node -4,
value is -4,
before left is8,
after left 1 is 8,-2,
At node 7,
value is 7,
before right is7,
after right is7,10,
Sum of the nodes is 17 ,len=2
Path is ---> Breaks at this point in main()
Code is C++ with passing args by reference and using new.
To make C, lots of little fixes including how C "reference" variable are passed (explicitly by address).
You are not doing rellloc() correctly should the allocation fail as you have lost the original pointer.
Always good form to NULL a pointer after freeing it.
#include <stdio.h>
#include <string.h>
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
/* A tree node structure */
struct node {
int data;
struct node *left;
struct node *right;
};
// Returns the maximum sum and prints the nodes on max sum path
int maxsumtoleaf(struct node *node, int** path, int *height) {
// base case
if (node == NULL)
return 0;
printf("\n At node %d,", node->data);
if (node->left == NULL && node->left == NULL) {
*path = (int*) realloc(*path, sizeof(int));
(*path)[0] = node->data;
*height = 1;
printf("\n value is %d,", *path[0]);
return node->data;
}
// find the target leaf and maximum sum
int rightheight = 0, leftheight = 0;
int *path1 = NULL, *path2 = NULL;
int left = maxsumtoleaf(node->left, &path1, &leftheight);
int right = maxsumtoleaf(node->right, &path2, &rightheight);
if (left > right) {
printf("\nbefore left is");
for (int i = 0; i < leftheight; i++)
printf("%d,", path1[i]);
path1 = (int*) realloc(path1, sizeof(int) * (leftheight + 1));
if (path1 == NULL) {
printf("Out of Memory!\n");
return 0;
}
path1[leftheight] = node->data;
*height = leftheight + 1;
printf("\nafter left %d is ", leftheight);
for (int i = 0; i < *height; i++)
printf("%d,", path1[i]);
*path = path1;
return left + node->data;
} else {
printf("\nbefore right is");
for (int i = 0; i < rightheight; i++)
printf("%d,", path2[i]);
path2 = (int*) realloc(path2, sizeof(int) * (rightheight + 1));
if (path2 == NULL) {
printf("Out of Memory!\n");
return 0;
}
path2[rightheight] = node->data;
*height = rightheight + 1;
printf("\nafter right is");
for (int i = 0; i < *height; i++)
printf("%d,", path2[i]);
*path = path2;
return right + node->data;
}
// return maximum sum
}
/* Utility function to create a new Binary Tree node */
struct node* newNode(int data) {
struct node *temp = malloc(sizeof *temp); // new struct node;
temp->data = data;
temp->left = NULL;
temp->right = NULL;
return temp;
}
/* Driver function to test above functions */
int main() {
struct node *root = NULL;
/* Constructing tree given in the above figure */
/* (8<--2->-4)<-10->7 */
root = newNode(10);
root->left = newNode(-2);
root->right = newNode(7);
root->left->left = newNode(8);
root->left->right = newNode(-4);
int sum = 0;
int* path = NULL;
int height = 0;
sum = maxsumtoleaf(root, &path, &height);
printf("\nSum of the nodes is %d ,len=%d", sum, height);
printf("\nPath is %p ", path);
// return 0;
for (int i = 0; i < height; i++)
printf("%d,", path[i]);
free(path);
path = NULL;
// getchar();
return 0;
}
Preferred realoc() use
// Somehow these are to be updated (initial to NULL and 0)
some_type *current_ptr;
size_t current_element_count; // best too use type size_t
size_t new_element_count = some_function(current_size);
void *new_ptr = realloc(current_ptr, new_element_count * sizeof *current_ptr);
if (new_ptr == NULL && new_element_count > 0) {
Handle_OOM(); // current_ptr is still same & current_element_count elements
return;
}
current_ptr = new_ptr;
current_element_count = new_element_count;
// continue on the happy path

Resources