I've been working on a linked list which was implemented by the name vector_string.
I'm trying to insert words into it, if the word is already existed in the linked list, skip it.
void vector_string_insert(vector_string *vs, char *key) {
vs_entry_t *newNode = (vs_entry_t*)malloc(sizeof(vs_entry_t));
newNode->value = key;
newNode->next = NULL;
vs_entry_t *current = vs->head;
if(vs->head == NULL)
{
vs->head = newNode;
}
else{
while(current->next != NULL)
current = current->next;
current->next = newNode;
}
}
bool vector_string_find(vector_string *vs, char *key)
{
vs_entry_t *current = vs->head;
while(current != NULL)
{
if (current->value == key)
return true;
current = current->next;
}
return false;
}
And here's my main:
if (vector_string_find(header, "Hello") == false);
vector_string_insert(header,"Hello");
if (vector_string_find(header, "Hello") == false);
vector_string_insert(header,"Hello");
if (vector_string_find(header, "Hola") == false);
vector_string_insert(header,"Hola");
Although the vector_string_find() returned "true" for the second "Hello", it still got inserted in the linked list:
1. Hello
2. Hello
3. Hola
Related
Is it possible to have multiple data inside a single linked list node in C? And how do you input and access data with this?
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
char name[30];
struct node *next;
};
struct node *head, *tail = NULL;
void addNode(int data, char string) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
newNode->name[30] = string;
newNode->next = NULL;
if(head == NULL) {
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
void sortList() {
struct node *current = head, *index = NULL;
int temp;
if(head == NULL) {
return;
}
else {
while(current != NULL) {
index = current->next;
while(index != NULL) {
if(current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
}
index = index->next;
}
current = current->next;
}
}
}
void display() {
struct node *current = head;
if(head == NULL) {
printf("List is empty \n");
return;
}
while(current != NULL) {
printf("%d - %s", current->data, current->name);
current = current->next;
}
printf("\n");
}
int main()
{
char string1[10] = "Aaron";
char string2[10] = "Baron";
char string3[10] = "Carla";
addNode(9, string1);
addNode(7, string2);
addNode(2, string3);
printf("Original list: \n");
display();
sortList();
printf("Sorted list: \n");
display();
return 0;
}
I don't understand why my code didn't work. I was trying to make use of single linked list where it can accept/input and print/output the number and the name at the same time.
What I want it to happen is to print the number and the name.
The output should be:
Carla - 2
Baron - 7
Aaron - 9
Please read my comments marked as // CHANGE HERE.
// CHANGE HERE: accept a character array as argument
void addNode(int data, char string[]) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
// CHANGE HERE: copy char array argument to name
strncpy(newNode->name, string, 30);
newNode->next = NULL;
if(head == NULL) {
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
void sortList() {
struct node *current = head, *index = NULL;
int temp;
char temp1[30];
if(head == NULL) {
return;
}
else {
while(current != NULL) {
index = current->next;
while(index != NULL) {
if(current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
// CHANGE HERE: swap the name along with data
strncpy(temp1, current->name, 30);
strncpy(current->name, index->name, 30);
strncpy(index->name, temp1, 30);
}
index = index->next;
}
current = current->next;
}
}
}
void display() {
struct node *current = head;
if(head == NULL) {
printf("List is empty \n");
return;
}
while(current != NULL) {
printf("%d - %s\n", current->data, current->name);
current = current->next;
}
printf("\n");
}
I am trying to implement an algorithm in C which splits a linked list. So what I am trying to do is, I have a linked list of all entries, I am trying to split that linked list into two separate lists based on distance of elements from a specific node.
What shiftAndCluster does is takes in a linked list list, 2 empty lists oldFreshList and newList and 2 nodes best1 and best2. It first searches for these 2 nodes in list and pushed them into 2 empty lists respectively. Then the function iterates over each node of list and calculates its distance from either of the nodes and pushes it to the list containing the closer best node.
The code goes like this
void shiftAndCluster(SinglyLinkedList* list, SinglyLinkedList* oldFreshList, SinglyLinkedList* newList, SinglyLinkedListNode *best1, SinglyLinkedListNode *best2)
{
SinglyLinkedListNode *curr1 = list->front;
SinglyLinkedList *temp = cloneFullList(list);
SinglyLinkedListNode *prev = curr1;
while (curr1 != NULL)
{
if (curr1 == best2)
{
break;
} //reach till best2 in the list, so we have the prev of best2 with us
prev = curr1;
curr1 = curr1->next;
}
if (prev == curr1)
{
list->front = curr1->next;
list->size--;
SinglyLinkedList_pushFront(newList,curr1);
}
else
{
prev->next = curr1->next;
list->size--;
SinglyLinkedList_pushFront(newList,curr1);
}
curr1 = list->front;
prev = curr1;
while(curr1 != NULL)
{
if (curr1 == best1) {
// break when found best1
break;
};
prev = curr1;
curr1 = curr1->next;
}
// first, middle and last
if (prev == curr1)
{
list->front = curr1->next;
list->size--;
SinglyLinkedList_pushFront(oldFreshList,curr1);
}
else
{
prev->next = curr1->next;
list->size--;
SinglyLinkedList_pushFront(oldFreshList,curr1);
}
int firstSize = 1;
int secondSize = 1;
curr1 = list->front;
double dist1, dist2;
while (curr1 != NULL && list->size)
{
curr1=list->front;
SinglyLinkedList_popFront(list);
dist1 = calculateDistance(curr1,best1);
dist2 = calculateDistance(curr1,best2);
if (dist1 < dist2)
{
SinglyLinkedList_pushFront(oldFreshList,curr1);
firstSize++;
if (firstSize == 10) break;
}
else
{
SinglyLinkedList_pushFront(newList,curr1);
secondSize++;
if (secondSize == 10) break;
}
}
list->front = temp->front;
list->size = temp -> size;
}
The size of list is 11 nodes so the algorithm stops when either of the new list reaches size 10. At the end, the old list is repopulated with it's original entries.
The struct has been defined as
typedef struct SinglyLinkedListNode
{
void *data;
struct SinglyLinkedListNode *next;
}SinglyLinkedListNode;
typedef struct SinglyLinkedList
{
int size;
struct SinglyLinkedListNode *front;
}SinglyLinkedList;
Helper functions are:
SinglyLinkedListNode* cloneList(SinglyLinkedListNode *head) {
if(head == NULL) return NULL;
SinglyLinkedListNode *result = (SinglyLinkedListNode *)malloc(sizeof(SinglyLinkedListNode));
result->data = head->data;
result->next = cloneList(head->next);
return result;
}
SinglyLinkedList* cloneFullList(SinglyLinkedList *list) {
if(list == NULL) return NULL;
SinglyLinkedList *result = (SinglyLinkedList *)malloc(sizeof(SinglyLinkedList));
result->size = list->size;
result->front = cloneList(list->front);
return result;
}
pushFront, popFront and calculateDistance functions are trivial and work correctly. (Can provide them if required, but I have tested them extensively, they work correctly)
The issue I am facing is that when I try to use this function in a loop, it breaks after a single iteration.
Example is
//templist is a normal linked list containing 11 nodes
SinglyLinkedListNode *ppp1 = templist->front;
SinglyLinkedListNode *ppp2 = templist->front;
int ctrin = 0, ctr=0;
while (ppp1 != NULL)
{
ctr++;
ppp2 = templist->front;
ctrin = 0;
while (ppp2 != NULL)
{
SinglyLinkedList* tp2 = createEmptyList();
SinglyLinkedList* np2 = createEmptyList();
ctrin++;
if (ppp1 == ppp2)
{
ppp2 = ppp2->next;
ctrin++;
}
shiftAndCluster(templist, tp2, np2, ppp1, ppp2, listType, 1);
templist = cloneFullList(list);
printf("(%d, %d)\n", ctr, ctrin);
ppp2 = ppp2->next;
}
iter++;
ppp1 = ppp1->next;
}
createEmptyList function just creates an empty list.
The output prints (1,2) indicating it does check for (1,1) and skip it and after shifting and clustering once, it breaks down. The incoming list is fine and I think there are issues with the logic of the function. Can someone please help?
May not be the only problem but when you do :
prev = curr1;
curr1 = curr1->next;
prev will always be different of curr1. So the test if (prev == curr1) if always false except if list->front is NULL
I'm developing a client-server program and when and I'm trying to implement a user linked list using this structure:
typedef struct user {
char username[50];
int user_pid;
struct user *next;
} user_list;
I'm trying figure out what's wrong with the code, because the compiler doesn't give me any error, but when I try to user to print the users list, it simply doesn't display anything.
AddUser function:
AddUser(user_list *head, req req)
{
if(head == NULL)
{
head = malloc(sizeof(user_list));
if (head == NULL)
fprintf(stdout,"[SERVER] Error memory allocation ");
strcpy(head->username, req.str);
head->user_pid = req.client_pid;
head->next = NULL;
}
else
{
user_list *current = head;
while (current->next != NULL)
current = current->next;
current->next = malloc(sizeof(user_list));
strcpy(current->next->username, req.str);
current->next->user_pid = req.client_pid;
current->next->next = NULL;
}
num_users++;
}
Main Function (short version)
int Main()
{
struct request req;
struct answer ans;
user_list *head = NULL;
do{
read(fifo_1, &req, sizeof(req)); // Read client request
if(strcasecmp(req.str, "adduser") == 0)
{
AddUser(head, req);
strcpy(ans.str, "User added with success! You're logged!");
}
if(strcasecmp(req.str, "users") == 0) // Print on the screen the users list
{
user_list *current = head;
while (current != NULL)
{
fprintf(stdout, "%s\n", current->username);
fprintf(stdout, "%d\n", current->user_pid);
current = current->next;
}
}
}while(strcmp(req.str,"exit") != 0);
}
Putting together what others have already pointed out in comments:
Change main. Instead of
int Main()
use
int main()
The value of head, doesn't change in main when you change it in AddUser. Here's one solution. Return head from AddUser.
user_list* AddUser(user_list *head, req req)
{
if(head == NULL)
{
head = malloc(sizeof(user_list));
if (head == NULL)
fprintf(stdout,"[SERVER] Error memory allocation ");
strcpy(head->username, req.str);
head->user_pid = req.client_pid;
head->next = NULL;
}
else
{
user_list *current = head;
while (current->next != NULL)
current = current->next;
current->next = malloc(sizeof(user_list));
strcpy(current->next->username, req.str);
current->next->user_pid = req.client_pid;
current->next->next = NULL;
}
num_users++;
return head;
}
Capture the return value of AddUser in main. Instead of just
AddUser(head, req);
use
head = AddUser(head, req);
I want to write a copy_list function that creates a linked list(the function result) with new nodes that contain the same data as the linked list referenced by the single argument of copy_list.But my copy_list function doesn't work.It goes into infinite loop,While loop doesn't quit.
My structures
typedef struct name_node_s {
char name[11];
struct name_node_s *restp;
}name_node_t;
typedef struct {
name_node_t *headp;
int size;
}name_list_t;
My copy_list function:
name_node_t *copy_list(name_node_t *head){
name_node_t *current = head;
name_node_t *newList = NULL;
name_node_t *tail = NULL;
while (current != NULL){
if (newList == NULL) {
newList = malloc(sizeof(name_node_t));
strcpy(newList->name, current->name);
newList->restp = NULL;
tail = newList;
}
else {
tail->restp = malloc(sizeof(name_node_t));
tail = tail->restp;
strcpy(tail->name, current->name);
tail->restp = NULL;
}
current = current->restp;
}
return(newList);
}
Rest of code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct name_node_s {
char name[11];
struct name_node_s *restp;
}name_node_t;
typedef struct {
name_node_t *headp;
int size;
}name_list_t;
name_node_t* presidents(void);
void insertAfter(name_node_t* mynode,name_node_t* newNode);
//void delete_last(name_node_t** headRef);
//void ListDelete(name_list_t* listP, char pname[]);
void lastDelete(name_list_t* listP);
void place_first(name_node_t **headRef, char pname[]);
name_node_t *copy_list(name_node_t *head);
int main(void)
{
name_list_t list;
name_list_t list_two;
//name_node_t *np, *qp;
list.headp = presidents();
name_node_t *new_node;
new_node = malloc(sizeof(name_node_t));
strcpy(new_node->name, "Eisenhower");
insertAfter(list.headp->restp, new_node);
lastDelete(&list);
place_first(&list.headp, "Mustafa");
printf("%s %s %s %s", list.headp->name, list.headp->restp->name, list.headp->restp->restp->name, list.headp->restp->restp->restp->name);
list_two.headp = copy_list(list.headp);
printf("%s %s %s %s", list_two.headp->name, list.headp->restp->name, list.headp->restp->restp->name, list.headp->restp->restp->restp->name);
return(0);
}
name_node_t* presidents(void)
{
name_node_t* head = NULL;
name_node_t* second = NULL;
name_node_t* third = NULL;
head = malloc(sizeof(name_node_t));
second = malloc(sizeof(name_node_t));
third = malloc (sizeof(name_node_t));
strcpy(head->name, "Washington");
head->restp = second;
strcpy(second->name, "Roosevelt");
second->restp = third;
strcpy(third->name, "Kennedy");
third->restp = NULL;
return(head);
}
void insertAfter(name_node_t* mynode,name_node_t* newNode)
{
newNode->restp = mynode->restp;
mynode->restp = newNode;
}
void ListDelete(name_list_t* listP, char pname[]){
name_node_t *to_freep, *cur_nodep;
if(strcmp(listP->headp->name, pname)){
to_freep = listP->headp;
listP->headp = to_freep->restp;
--(listP->size);
}
else {
for (cur_nodep = listP->headp;
cur_nodep->restp != NULL && !strcmp(cur_nodep->restp->name, pname);
cur_nodep = cur_nodep->restp) {
if( cur_nodep->restp != NULL && strcmp(cur_nodep->restp->name, pname)) {
to_freep = cur_nodep->restp;
cur_nodep->restp = to_freep->restp;
free(to_freep);
--(listP->size);
}
}
}
}
void lastDelete(name_list_t* listP){
name_node_t *to_freep, *cur_nodep;
for (cur_nodep = listP->headp;
cur_nodep->restp != NULL;
cur_nodep = cur_nodep->restp) {}
to_freep = cur_nodep;
cur_nodep->restp = to_freep->restp;
free(to_freep);
--(listP->size);
}
void place_first(name_node_t **headRef, char pname[]) {
name_node_t *newNode = malloc(sizeof(name_node_t));
strcpy(newNode->name, pname);
newNode->restp = *headRef;
*headRef = newNode;
}
/*name_node_t *copy_list(name_node_t *head) {
name_node_t *current = head;
name_node_t *newList = NULL;
name_node_t **lastPtr;
lastPtr = &newList;
while (current != NULL) {
printf("**");
place_first(lastPtr, current->name);
lastPtr = &((*lastPtr)->restp);
current = current->restp;
}
return(newList);
}*/
/*name_node_t *copy_list(name_node_t *head) {
if (head == NULL)
return NULL;
else {
name_node_t *newList = malloc(sizeof(name_list_t));
strcpy(newList->name, head->name);
newList->restp = copy_list(head->restp);
return(newList);
}
}*/
/name_node_t *copy_list(name_node_t *head){
name_node_t *current = head;
name_node_t *newList = NULL;
name_node_t *tail = NULL;
while (current != NULL){
if (newList == NULL) {
newList = malloc(sizeof(name_node_t));
strcpy(newList->name, current->name);
newList->restp = NULL;
tail = newList;
}
else {
tail->restp = malloc(sizeof(name_node_t));
tail = tail->restp;
strcpy(tail->name, current->name);
tail->restp = NULL;
}
current = current->restp;
}
return(newList);
}
In lastDelete(), this loop:
for (cur_nodep = listP->headp;
cur_nodep->restp != NULL;
cur_nodep = cur_nodep->restp) {}
... stops at the last node in the list. Afterwards you never set restp to NULL in the second-to-last element. You only work on the last one as to_freep and cur_nodep point to the same element.
This may be easier to do recursively, since singly-linked lists are recursive structures:
A copy of NULL is just NULL.
A copy of a name_node_t is a freshly malloc'd name_node_t with the same name as the original and a copy of the original's restp as its restp.
It's been a long time since I wrote C++. Still:
Doesn't look like there's anything in copy_list that should make it go into an infinite loop.
The logic has:
while (current!=null) current = current->next;
Perhaps copy_list is being passed in a bad list? (i.e A list where the last element does not have restp == null).
In main you are calling:
insertAfter(....);
lastDelete(....);
...
copy_list(....);
So the problem could be in insertAfter or lastDelete ... or ...
Check lastDelete:
name_node_t *to_freep, *cur_nodep;
for (cur_nodep = listP->headp;
cur_nodep->restp != NULL;
cur_nodep = cur_nodep->restp) {}
to_freep = cur_nodep;
cur_nodep->restp = to_freep->restp;
free(to_freep); //what if listP->headp was null? i.e. list had size 0?
--(listP->size);
Plenty of issues
What if you're passed a list with 0 elements?
What if you're passed a list with 1 element?
In any case after you free "to_freep", the node prior to "to_freep" does not have it's restp set to null. So the second last node, now points to a deleted node! This means the list never terminates.
A better lastDelete: (just an algo, can't remember the syntax anymore...)
if (head == null) return; //do nothing
if (head->next == null)
{
listP->head = null;
listP->size = 0;
return;
}
node* prev = head;
head = head->next;
while (head->next != null)
{
prev = head;
head = head->next;
}
//now prev points to a 2nd last node
//head points to last node
free(head);
prev->restp = null;
After spending more than 10 hrs, the following code is developed:
struct stockRecord* temp = NULL;
struct stockRecord* head = NULL;
struct stockRecord* prevptr = NULL;
struct stockRecord* recurfun(struct stockRecord* list) {
temp = list;
if (head == NULL) head = temp;
if (temp == NULL) {
return head;
} else {
/*first node*/
if (prevptr == NULL) {
if (strstr(temp->name, "ABC-") != NULL) {
temp = temp->next;
head = temp;
prevptr = head;
}
}
/*last node*/
if (temp->next == NULL) {
if (strstr(temp->name, "ABC-") != NULL) {
prevptr->next = NULL;
}
return head;
}
/*middle node*/
if (strstr(temp->name, "ABC-") != NULL) {
prevptr->next = temp->next;
} else {
if (prevptr != NULL) {
prevptr = temp;
} else {
prevptr = head;
}
}
return recurfun(temp->next);
}
The problem is, when first node and the second node also contains "ABC-", the function only remove the first node, the second node still can't be removed.
What's the problems of my code?
Suppose you start out with 1->2->3
After you remove the first node, you set prevptr, head, and temp to all point to 2.
Then at the end of the function you recursively call it on temp->next which points to 3.
The result is that you are skipping the second node when you remove the first.