C linked list head pointer keep changing - c

I made a program which reads input form a text file and create a linked list but have trouble doing it. I am still a beginner. The problem is the head pointer keeps moving when adding a new item.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <stdbool.h>
//Visitor information
struct visitData
{
char *SrNo;
char *ticketNo;
char *Name;
char *ID;
};
//Ticket linked list
struct ticket
{
struct visitData visitor;
struct ticket *nextPtr;
};
int main() { //main
FILE *fPtr = NULL;
fPtr = fopen("Tickets.txt", "a+");
if (fPtr == NULL)
{
printf("Error, please try again.\n");
return 0;
}
FILE *outfPtr = NULL;
outfPtr = fopen("output.txt", "w");
if (outfPtr == NULL)
{
puts("Error, could not create output file, please try again.");
return 0;
}
else {
struct ticket *head = NULL;
struct ticket *new = NULL;
struct visitData *nextPtr = NULL;
char sr[2];
char ticketNumber[20];
char name[30];
char id[24];
rewind(fPtr);
if (fscanf(fPtr, "%2s%20s%29s%24s", sr, ticketNumber, name, id) == 4)
{
new = malloc(sizeof(struct ticket));
new->visitor.SrNo = strdup(sr);
new->visitor.ticketNo = strdup(ticketNumber);
new->visitor.Name = strdup(name);
new->visitor.ID = strdup(id);
new->nextPtr = NULL;
head = new;
printf("%s\n", head->visitor.SrNo);
while (!feof(fPtr))
{
if (fscanf(fPtr, "%2s%20s%29s%24s", sr, ticketNumber, name, id) == 4)
new->visitor.SrNo = sr;
new->visitor.ticketNo = ticketNumber;
new->visitor.Name = name;
new->visitor.ID = id;
new->nextPtr = malloc(sizeof(struct ticket));
new = new->nextPtr;
new->nextPtr = NULL;
}
}
}
else
{
printf("%d",fscanf(fPtr, "%2s%20s%29s%24s", sr, ticketNumber, name, id));
new->visitor.SrNo = "0";
}
if (head == NULL)
{
printf("List is empty\n");
}
struct ticket *Ptr = NULL;
Ptr = head;
printf("%s\n", Ptr->visitor.SrNo);
while (Ptr != NULL)
{
printf("%s %s\n", Ptr->visitor.SrNo, Ptr->visitor.ticketNo);
Ptr = Ptr->nextPtr;
}
}
}
I did try to add a line which is `
new = malloc(sizeof(struct ticket));
`, but it became another problem, that the head pointer cannot link to the second node.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <stdbool.h>
//Visitor information
struct visitData
{
char *SrNo;
char *ticketNo;
char *Name;
char *ID;
};
//Ticket linked list
struct ticket
{
struct visitData visitor;
struct ticket *nextPtr;
};
int main() { //main
FILE *fPtr = NULL;
fPtr = fopen("Tickets.txt", "a+");
if (fPtr == NULL)
{
printf("Error, please try again.\n");
return 0;
}
FILE *outfPtr = NULL;
outfPtr = fopen("output.txt", "w");
if (outfPtr == NULL)
{
puts("Error, could not create output file, please try again.");
return 0;
}
else {
struct ticket *head = NULL;
struct ticket *new = NULL;
struct visitData *nextPtr = NULL;
char sr[2];
char ticketNumber[20];
char name[30];
char id[24];
rewind(fPtr);
if (fscanf(fPtr, "%2s%20s%29s%24s", sr, ticketNumber, name, id) == 4)
{
new = malloc(sizeof(struct ticket));
new->visitor.SrNo = strdup(sr);
new->visitor.ticketNo = strdup(ticketNumber);
new->visitor.Name = strdup(name);
new->visitor.ID = strdup(id);
new->nextPtr = NULL;
head = new;
printf("%s\n", head->visitor.SrNo);
while (!feof(fPtr))
{
if (fscanf(fPtr, "%2s%20s%29s%24s", sr, ticketNumber, name, id) == 4)
{
new = malloc(sizeof(struct ticket));
new->visitor.SrNo = sr;
new->visitor.ticketNo = ticketNumber;
new->visitor.Name = name;
new->visitor.ID = id;
new->nextPtr = malloc(sizeof(struct ticket));
new = new->nextPtr;
new->nextPtr = NULL;
}
}
}
else
{
printf("%d",fscanf(fPtr, "%2s%20s%29s%24s", sr, ticketNumber, name, id));
new->visitor.SrNo = "0";
}
if (head == NULL)
{
printf("List is empty\n");
}
struct ticket *Ptr = NULL;
Ptr = head;
printf("%s\n", Ptr->visitor.SrNo);
while (Ptr != NULL)
{
printf("%s %s\n", Ptr->visitor.SrNo, Ptr->visitor.ticketNo);
Ptr = Ptr->nextPtr;
}
}
}

typical way to add nodes to a list is:
new = malloc(size); // Create a new node
new->nextPtr = head; // Save the existing list
head = new; // Add the new element at the front of the list
You are changing head before saving your old value, so you lose the list.

Related

One of my functions is accidentally deleting elements from list

I am trying to make a "library" where there are alphabetically-sorted catalogs and each of them has books also in alphabetical order. As part of deletebook function(not included because it's not there yet), I wrote function that finds catalog of the book. The function works, but it deletes books in the process( I think) which is not good. How to change it so it doesn't delete them?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct book
{
char *title;
int number;
char *country;
struct book* new;
};
struct catalog
{
char *name;
struct catalog* next;
struct book* firstbook;
};
void printList(struct catalog *head)
{
struct catalog *temp = head;
while(temp != NULL)
{
struct book* book = temp->firstbook;
if(book == NULL)
{
printf("%s\n", temp->name);
}
while(book != NULL)
{
printf("%s ", temp->name);
printf("%s ", book->title);
printf("%d ", book->number);
printf("%s\n", book->country);
book = book->new;
}
temp = temp->next;
}
}
struct catalog *newcatalog(char *new_name)
{
struct catalog* new_node = (struct catalog*) malloc(sizeof(struct catalog));
new_node->name = malloc(strlen(new_name)+1);
strcpy(new_node->name, new_name);
new_node->next = NULL;
new_node->firstbook = NULL;
return new_node;
}
struct book *newbook(char *booktitle, int number, char *country)
{
struct book* newbook = (struct book*) malloc(sizeof(struct book));
newbook->title = malloc(strlen(booktitle)+1);
newbook->country = malloc(strlen(country)+1);
strcpy(newbook->title, booktitle);
strcpy(newbook->country, country);
newbook->number = number;
newbook->new = NULL;
return newbook;
}
struct catalog *findcatalog(struct catalog** head, char *catalogname)
{
struct catalog* current;
current = *head;
while(current != NULL)
{
if(!strcmp(current->name,catalogname))
{
return current;
}
current = current->next;
}
return NULL;
}
struct catalog *findbookcatalog(struct catalog** head, int number) //function that deletes a book when used
{
struct catalog* current;
current = *head;
while(current != NULL)
{
while(current->firstbook != NULL)
{
if(current->firstbook->number == number)
{
return current;
}
current->firstbook = current->firstbook->new;
}
current = current->next;
}
return NULL;
}
struct book *findbook(struct catalog** head, int number)
{
struct catalog* current = findbookcatalog(head, number);
struct book* booklocation;
while(current->firstbook != NULL)
{
booklocation = current->firstbook;
if(current->firstbook->number == number)
{
return booklocation;
}
current->firstbook = current->firstbook->new;
}
return NULL;
}
void sortedBookInsert(struct catalog** head, char *catalogname, char *booktitle, int number, char *country)
{
struct catalog* searched;
struct book* pom;
struct book* ksiazka = newbook(booktitle, number, country);
searched = findcatalog(head, catalogname);
if(searched->firstbook == NULL || strcmp(searched->firstbook->title, ksiazka->title)>0)
{
ksiazka->new =searched->firstbook;
searched->firstbook = ksiazka;
}
else
{ pom = searched->firstbook;
while(pom->new!= NULL && strcmp(searched->firstbook->title, ksiazka->title)< 0)
{
pom = pom->new;
}
ksiazka->new = pom->new;
pom->new = ksiazka;
}
}
void sortedInsert(struct catalog** head,char *name)
{
struct catalog* current;
struct catalog* new_node = newcatalog(name);
if(new_node == NULL)
{
return;
}
if (*head == NULL || strcmp((*head)->name, new_node->name) > 0)
{
new_node->next = *head;
*head = new_node;
}
else
{
current = *head;
while (current->next!=NULL && strcmp(current->next->name, new_node->name) < 0)
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
}
int main()
{
struct catalog* head = NULL;
sortedInsert(&head, "Kappa");
sortedInsert(&head, "Pxntry");
sortedInsert(&head, "Sdafscx");
sortedInsert(&head, "Saxzxc");
sortedInsert(&head, "Zsdas");
sortedInsert(&head, "Zzzzzzzz");
sortedInsert(&head, "Country");
sortedBookInsert(&head, "Country", "PKP", 11111, "Germany");
sortedBookInsert(&head, "Country", "Polacy", 11112, "Italy");
sortedBookInsert(&head, "Country", "Bus", 11234, "France");
sortedBookInsert(&head, "Country", "Poltics", 14111, "Russia");
printList(head);
findbookcatalog(&head, 11112); // this will "eat" "Bus" and "PKP", so books that appear before Polacy
printf("\n");
printList(head);
return 0;
}
It should print my nested lists two times, two times the same, but it deletes all books that are before the searched book.
Result:
Country Bus 11234 France
Country PKP 11111 Germany
Country Polacy 11112 Italy
Country Poltics 14111 Russia
Kappa
Pxntry
Saxzxc
Sdafscx
Zsdas
Zzzzzzzz
Country Polacy 11112 Italy
Country Poltics 14111 Russia
Kappa
Pxntry
Saxzxc
Sdafscx
Zsdas
Zzzzzzzz
This code is removing books from a list:
current->firstbook = current->firstbook->new;
You probably meant to use something like this:
current_book = current->firstbook;
while (current_book) {
if (current_book->number == number) {
return current_book;
}
current_book = current_book->new;
}
I changed this function which fixes your current problem:
struct catalog *findbookcatalog(struct catalog** head, int number) //function that deletes a book when used
{
struct catalog* current;
current = *head;
struct book *current_book;
while(current != NULL)
{
current_book = current->firstbook;
while(current_book != NULL)
{
if(current_book->number == number)
{
return current;
}
current_book = current_book->new;
}
current = current->next;
}
return NULL;
}
I also changed this function. It has the same problem, you just haven't tested it yet.
struct book *findbook(struct catalog** head, int number)
{
struct catalog* current = findbookcatalog(head, number);
struct book* booklocation;
if (current != NULL) {
booklocation = current->firstbook;
while(booklocation != NULL)
{
if(booklocation->number == number)
{
return booklocation;
}
booklocation = booklocation->new;
}
}
return NULL;
}

Problem with the print output from binary tree

I have to read data from file countries.txt. The file contains countries name and their ID, insert them in a linked list (sorted insert alph.). Linked list node contains name of country, ID of country and pointer to root of binary tree which contains cities of that country. I have to insert cities from other file (cities.txt).
I insert countries successfully but I cant insert cities.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct CITY{
char *name;
struct CITY *left;
struct CITY *right;
}nodeCity;
typedef struct COUNTRY{
char *name;
int id;
struct CITY *root;
struct COUNTRY *next;
}nodeCountry;
int listInsert(nodeCountry**, char*, int);
int printList(nodeCountry*);
nodeCity* findCity(nodeCountry*, int);
nodeCity* treeInsert(nodeCity*, char*);
int inorderPrint(nodeCity*);
int main()
{
nodeCountry *head;
int result, ID, k;
FILE *cities, *countries;
char buffer[1024];
nodeCity *root;
head = NULL;
countries = fopen("countries.txt", "r");
while(fscanf(countries, "%s %d", buffer, &ID) == 2)
result = listInsert(&head, buffer, ID);
cities = fopen("cities.txt", "r");
while(fscanf(cities, "%s %d", buffer, &ID) == 2)
{
root = findCity(head, ID);
root = treeInsert(root, buffer);
}
//result = printList(head);
scanf("%d", &k);
root = findCity(head, k);
result = inorderPrint(root);
return 0;
}
int inorderPrint(nodeCity *root)
{
int result;
if(root == NULL)
return NULL;
result = inorderPrint(root->left);
printf("%s\n", root->name);
result = inorderPrint(root->right);
return 1;
}
nodeCity* treeInsert(nodeCity *root, char *buffer)
{
printf("K");
if(root == NULL){
root = (nodeCity*)malloc(sizeof(nodeCity));
root->name = strdup(buffer);
root->left = NULL;
root->right = NULL;
}
else if(strcmp(buffer, root->name) > 0)
root->right = treeInsert(root->right, buffer);
else if(strcmp(buffer, root->name) < 0)
root->left = treeInsert(root->left, buffer);
return root;
}
nodeCity* findCity(nodeCountry *head, int ID)
{
while(head->id != ID)
head = head->next;
return head->root;
}
int listInsert(nodeCountry **head, char *buffer, int ID)
{
nodeCountry *current, *new_node;
if((*head) == NULL)
{
(*head) =
(nodeCountry*)malloc(sizeof(nodeCountry));
(*head)->name = strdup(buffer);
(*head)->id = ID;
(*head)->root = NULL;
(*head)->next = NULL;
return 1;
}
if(strcmp(buffer, (*head)->name) < 0)
{
new_node =
(nodeCountry*)malloc(sizeof(nodeCountry));
new_node->name = strdup(buffer);
new_node->id = ID;
new_node->root = NULL;
new_node->next = (*head);
(*head) = new_node;
return 1;
}
current = (*head);
while(current->next != NULL && strcmp(buffer, current->next->name) > 0)
current = current->next;
new_node = (nodeCountry*)malloc(sizeof(nodeCountry));
new_node->name = strdup(buffer);
new_node->id = ID;
new_node->next = current->next;
current->next = new_node;
new_node->root = NULL;
return 1;
}
int printList(nodeCountry *current)
{
while(current != NULL)
{
printf("%s\n", current->name);
current = current->next;
}
return 1;
}

Program sorts the data in the wrong way

I have to wirte a project for school, here is Program description
As can you see in the program description i have to sort the books by labels. Right now for some reason books that do not belong to specific label are printed under that label. For exemple Plato is printed under medival
I cannot find where did I made a mistake, I will be grateful for any help.
Here is my code:
#define _CRT_SECURE_NO_WARNINGS
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <stdio.h>
#include <string.h>
typedef struct BOOK Book;
struct BOOK
{
char *author;
char *title;
Book *next;
};
typedef struct LABEL Label;
struct LABEL
{
char *text;
Label *next;
Book *books;
};
void clear(Label** head);
void addLabel(Label **head, Label *elem);
void addBook(Book **head, Book **elem);
void readFromFile(char *fileName, char *outputFileName, Label *Ihead);
void saveBooks(FILE *file, Book *head);
void saveLabels(FILE *file, Label *Ihead);
void saveToFile(char *fileName, Label *Ihead);
void ComandConsole(int argc, char* argv[], int* fileinput, int* fileoutput);
Label* checkIfExists(Label **head, char *labelText);
Label* checkIfExists(Label **head, char *labelText)
{
Label *tmp = *head;
while (tmp != NULL)
{
if (strcmp(labelText, tmp->text) == 0)
return tmp;
tmp = tmp->next;
}
return NULL;
}
void addLabel(Label **head, Label *elem)
{
Label *temp = NULL;
if ((temp = checkIfExists(head, elem->text)) == NULL)
{
if (*head == NULL)
{
*head = elem;
return;
}
temp = *head;
while (temp->next != NULL)
temp = temp->next;
temp->next = elem;
}
else
addBook(&(temp->books), &(elem->books));
}
void addBook(Book **head, Book **elem)
{
Book *pom = *head;
if (strcmp(pom->author, (*elem)->author) > 0)
{
(*elem)->next = (*head)->next;
*head = *elem;
*elem = pom;
(*head)->next = *elem;
return;
}
while (pom->next != NULL && (strcmp((*elem)->author, pom->author) > 0))
pom = pom->next;
(*elem)->next = pom->next;
pom->next = *elem;
}
void readFromFile(char *fileName, char *outputFileName, Label *head)
{
FILE* input;
if ((input = fopen(fileName, "r")) == NULL)
{
printf("Reading failed!\n");
exit(1);
}
char buf[255];
while (fgets(buf, sizeof buf, input) != NULL)
{
Book *ksiazka = (Book*)malloc(sizeof(Book));
ksiazka->next = NULL;
char *store = strtok(buf, ";");
char * autor = (char*)malloc(sizeof(char)*strlen(store) + 1);
strcpy(autor, store);
ksiazka->author = autor;
store = strtok(NULL, ";");
char * tytul = (char*)malloc(sizeof(char)*strlen(store) + 1);
strcpy(tytul, store);
ksiazka->title = tytul;
store = strtok(NULL, "\n");
char * label = (char*)malloc(sizeof(char)*strlen(store) + 1);
strcpy(label, store);
char *tmp = strtok(label, ",\n");
while (tmp != NULL)
{
Label *newLabel = (Label*)malloc(sizeof(Label));
newLabel->books = NULL;
newLabel->next = NULL;
char *labelText = (char*)malloc(sizeof(char)*strlen(tmp) + 1);
strcpy(labelText, tmp);
newLabel->text = labelText;
newLabel->books = ksiazka;
addLabel(&head, newLabel);
tmp = strtok(NULL, ",\n");
}
}
saveToFile(outputFileName, head);
fclose(input);
}
void clear(Label** head)
{
while (*head != NULL)
{
Label* cur = *head;
*head = (*head)->next;
Book* a = cur->books;
while (a != NULL)
{
Book* b = a;
a = a->next;
free(b->author);
free(b->title);
free(b);
}
free(cur->text);
free(cur);
}
}
void saveBooks(FILE *file, Book *head)
{
Book *tmp = head;
while (tmp != NULL)
{
fprintf(file, "%s, %s\n", tmp->author, tmp->title);
tmp = tmp->next;
}
fprintf(file, "\n");
}
void saveLabels(FILE *file, Label *head)
{
Label *tmp = head;
while (tmp != NULL)
{
fprintf(file, "%s:\n", tmp->text);
if (tmp->books != NULL)
{
saveBooks(file, tmp->books);
}
tmp = tmp->next;
}
}
void saveToFile(char *fileName, Label *head)
{
FILE *output;
if ((output = fopen(fileName, "w")) == NULL)
{
printf("Writing failed!\n");
exit(1);
//clear(&head);
}
else
{
saveLabels(output, head);
}
//clear(&head);
fclose(output);
}
void ComandConsole(int argc, char* argv[], int* fileinput, int* fileoutput)
{
int i;
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
switch (argv[i][1])
{
case 'i':
{
i++;
if (i == argc) break;
*fileinput = i;
}
break;
case 'o':
{
i++;
if (i == argc) break;
*fileoutput = i;
}
break;
default:
{
printf("Wrong parameter");
} break;
}
}
}
int main(int argc, char* argv[])
{
int fileinputname = 0;
int fileoutputname = 0;
ComandConsole(argc, argv, &fileinputname, &fileoutputname);
if (fileinputname == 0 || fileoutputname == 0)
{
printf("Wrong parrametes");
getchar();
return 1;
}
Label *head = NULL;
readFromFile(argv[fileinputname], argv[fileoutputname], head);
_CrtDumpMemoryLeaks();
return 0;
}

C Read from file to populate linked list

I have a txt file that I need to read and populate a linked list. The file structure is the following
IBE0101;2016;11;20;07;50;Alvaro;Carvajal;12345678R
IBE0101;2016;11;20;07;50;Juan;Garcia;12345678R
I am trying to read it doing the following
tPassenger * ops_loadPassengersList()
{
tPassenger * retValue;
retValue = malloc(sizeof(tPassenger));
tPassenger *lastPassenger = retValue;
// Open file handle with read mode
FILE *file = fopen(OPS_PASSENGERS_FILE, "r");
// Loop until end of file
while(!feof(file)) {
tDateTime date;
fscanf(file, "%[^;];%d;%d;%d;%d;%d;%[^;];%[^;];%[^;]\n", lastPassenger->name, &date.year, &date.month, &date.day, &date.hour, &date.minute, lastPassenger->name, lastPassenger->surname, lastPassenger->dni);
printf(lastPassenger->name);
if(!feof(file)) {
lastPassenger->nextPassenger = malloc(sizeof(tPassenger));
lastPassenger = lastPassenger->nextPassenger;
}
}
// Close file handle
fclose(file);
return retValue;
}
However I get stuck on a infinite loop by fscanf not finding what I told to scan on? The pattern seems correct the first iteration works fine.
The tDateTime element is not used on this piece but I want to get it too.
Probably you should not parse the line yourself. There is a strtok() function which can give you the tokens separated by a delimiter. But this will not give you all the feilds together in one call. You will need to call it as many times as the number of fields are in a line of the file.
Similar method is discussed here
Something like this could work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCHAR 100
typedef struct {
int yyyy, mm, dd;
} date_t;
typedef struct {
int hh, min;
} times_t;
typedef struct node node_t;
struct node {
char *passenger_num, *name, *lastname, *dni;
date_t date;
times_t times;
node_t *next;
};
typedef struct {
node_t *head;
node_t *foot;
} list_t;
list_t *create_list(void);
list_t *insert_nodes(list_t *list, FILE *filename);
void free_list(list_t *list);
void print_list(list_t *list);
void exit_if_null(void *ptr, const char *msg);
void *malloc_str(size_t bytes);
int
main(int argc, char const *argv[]) {
FILE *filename;
list_t *list;
if ((filename = fopen("passengers.txt", "r")) == NULL) {
fprintf(stderr, "%s\n", "Error reading file!");
exit(EXIT_FAILURE);
}
list = create_list();
list = insert_nodes(list, filename);
print_list(list);
free_list(list);
list = NULL;
return 0;
}
list_t
*insert_nodes(list_t *list, FILE *filename) {
char line[MAXCHAR];
node_t *newnode;
char *passenger, *name, *lastname, *dni;
char *yyyy, *mm, *dd, *hh, *min;
while (fgets(line, MAXCHAR, filename) != NULL) {
passenger = strtok(line, ";");
yyyy = strtok(NULL, ";");
mm = strtok(NULL, ";");
dd = strtok(NULL, ";");
hh = strtok(NULL, ";");
min = strtok(NULL, ";");
name = strtok(NULL, ";");
lastname = strtok(NULL, ";");
dni = strtok(NULL, "\n");
newnode = malloc(sizeof(*newnode));
exit_if_null(newnode, "Node Allocation");
newnode->date.yyyy = atoi(yyyy);
newnode->date.mm = atoi(mm);
newnode->date.dd = atoi(dd);
newnode->times.hh = atoi(hh);
newnode->times.min = atoi(min);
newnode->passenger_num = malloc_str(strlen(passenger));
strcpy(newnode->passenger_num, passenger);
newnode->name = malloc_str(strlen(name));
strcpy(newnode->name, name);
newnode->lastname = malloc_str(strlen(lastname));
strcpy(newnode->lastname, lastname);
newnode->dni = malloc_str(strlen(dni));
strcpy(newnode->dni, dni);
newnode->next = NULL;
if (list->foot == NULL) {
list->head = newnode;
list->foot = newnode;
} else {
list->foot->next = newnode;
list->foot = newnode;
}
}
return list;
}
void
*malloc_str(size_t bytes) {
void *ptr = malloc(bytes+1);
exit_if_null(ptr, "Initial Allocation");
return ptr;
}
void
print_list(list_t *list) {
node_t *curr = list->head;
printf("Nodes inserted into linked list:\n");
while(curr) {
printf("%s;%4d;%2d;%2d;0%d;%2d;%s;%s;%s\n",
curr->passenger_num, curr->date.yyyy,
curr->date.mm, curr->date.dd,
curr->times.hh, curr->times.min,
curr->name, curr->lastname, curr->dni);
curr = curr->next;
}
}
void
free_list(list_t *list) {
node_t *curr, *prev;
curr = list->head;
while (curr) {
prev = curr;
curr = curr->next;
free(prev);
}
free(list);
}
list_t
*create_list(void) {
list_t *list = malloc(sizeof(*list));
exit_if_null(list, "Initial Allocation");
list->head = NULL;
list->foot = NULL;
return list;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}

Relocating a Node in a Singly Linked List Creates Infinite Loop

In my homework I was asked to relocate a specific node by his name field to specific index. I'm having trouble to figure out why is my list becomes an infinite list. The problem is in the function "changePlacement" Example: Given linked list : 1->2->3->4 Output : 1->3->3->3... Expected output : 1->3->2->4
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Frame
{
char *name;
unsigned int duration;
char *path; // may change to FILE*
};
typedef struct Frame frame_t;
struct Link
{
frame_t *frame;
struct Link *next;
};
typedef struct Link link_t;
int listLen = 0;
link_t* lastNode = NULL;
void addFrame(link_t** list);
void frameData(frame_t* frame);
void freeVideo(link_t* video);
void showList(link_t* list);
void freeNode(link_t* list);
void changePlacement(link_t** list, int newIndex, char* name);
int main(void)
{
link_t* video = NULL;
lastNode = video;
if (!video)
{
perror(video);
}
addFrame(&video);
addFrame(&video);
addFrame(&video);
addFrame(&video);
showList(video);
changePlacement(&video, 2, "3");
showList(video);
printf("\n");
freeVideo(&video);
_flushall();
getchar();
return 0;
}
void addFrame( link_t** video)
{
char strTemp[200] = { 0 };
link_t* newFrame = (link_t*) calloc(1, sizeof(link_t));
newFrame->frame = (frame_t*) malloc(sizeof(frame_t));
printf(" *** Creating new frame ***\n");
printf("Please insert a frame path:\n");
scanf(" %s", &strTemp);
newFrame->frame->path = (char*) calloc(strnlen(strTemp, 200) + 1, sizeof(char));
strncpy(newFrame->frame->path, strTemp, strnlen(strTemp, 200));
printf("Please insert frame duration(in miliseconds):\n");
scanf(" %d", &(newFrame->frame->duration));
printf("Please choose a name for that frame:\n");
scanf(" %s", &strTemp);
newFrame->frame->name = (char*) calloc(strnlen(strTemp, 200) + 1, sizeof(char));
strncpy(newFrame->frame->name, strTemp, strnlen(strTemp, 200));
if (!(*video))
{
(*video) = newFrame;
}
else
{
lastNode->next = newFrame;
}
lastNode = newFrame;
++listLen;
}
void freeVideo(link_t** video)
{
link_t* currNode = NULL;
int loop = 0;
for (; currNode; currNode = *video) // set curr to head, stop if list empty.
{
// advance head to next element.
freeNode(currNode);
(*video) = (*video)->next; // delete saved pointer.
}
freeNode((*video)->next);
freeNode((*video));
}
void showList(link_t* list)
{
printf("\n\t|Name\t\t| Duration | Path\n");
printf("\t+++++++++++++++++++++++++++++++++++++++++++++++\n");
for (;list; list = list->next)
{
printf("\t|%10s\t|%10d\t|\t%s\n", list->frame->name, list->frame->duration, list->frame->path);
printf("\t+++++++++++++++++++++++++++++++++++++++++++++++\n");
}
}
void freeNode(link_t* node)
{
free(node->frame->name);
free(node->frame->path);
free(node->frame);
free(node);
}
void changePlacement(link_t** list, int newIndex, char* name)
{
link_t *prevOldNode = (*list), *prevTemp = NULL, *oldNode = NULL, *newNode = NULL;
link_t *temp = (*list), *PrevNewNode = NULL, *nodeAfterNewNode = NULL;
int currIndex = 0, i = 0, flag = 0;
while ((temp->next))
{
++currIndex;
if (!strcmp(temp->frame->name, name)) //looking for the wanted node
{
oldNode = temp;
prevOldNode = prevTemp;
}
if (currIndex == newIndex)
{
PrevNewNode = prevTemp;
newNode = temp;
}
prevTemp = temp;
temp = temp->next;
}
nodeAfterNewNode = newNode->next; //temporal variable that stores the node after the new node
prevOldNode->next = oldNode->next;
newNode->next = oldNode;
oldNode->next = nodeAfterNewNode;
}
Do you have any ideas after looking on my code? any help would be blessed
Your code at the end of changePlacement() doesn't account for the case of oldNode and newNode being adjacent to each other, i. e. e. g. nodeAfterNewNode = newNode->next being identical to oldNode. (Besides it doesn't account for the case of not finding the name.) It is far easier to just exchange the frame pointers; change
nodeAfterNewNode = newNode->next; //temporal variable that stores the node after the new node
prevOldNode->next = oldNode->next;
newNode->next = oldNode;
oldNode->next = nodeAfterNewNode;
to
if (!oldNode) return; // wanted node name not found
frame_t *f = oldNode->frame;
oldNode->frame = newNode->frame;
newNode->frame = f;

Resources