Filter linked list and return new linked list C

I am trying to filter a linked list. Since I don't want to change the original linked list, I want to create a linked list and return it.

I'm having problems with this because I only know how to get 1 node from the filtering process, but I don't know how to navigate and add nodes from the original linked list to the linked list.

I have a structure like this (this represents an entry in a hash table):

typedef struct Entry {
   char *word;
   int len;
   struct Entry *next;
} Entry;

      

My filter function will take the word length and the original linked list as arguments, and then find nodes with the same len value. Whenever it finds a node that has the same len value, it adds the node to another linked list. Finally, it returns a new linked list.

struct Entry* filterLen(int len, struct Entry *en) {
   struct Entry *temp = (struct Entry *)malloc(sizeof(struct Entry));

   while(en->next != NULL) {
      if (en->len == len) {
         // assign values to temp list
         temp->word = en->word;
         temp->len = en->len;
         temp->next = en;
      }

      en = en->next; // move through list
   }

   return temp;
}

      

+3


source to share


4 answers


Entry* filterLen(int len, Entry *en) {
   Entry *result = NULL, **temp = &result;

   while(en != NULL) {
      if (en->len == len) {
     // assign values to temp list
         *temp = malloc(sizeof(Entry));
         (*temp)->word = en->word;
         (*temp)->len = en->len;
         (*temp)->next = NULL;
         temp = &((*temp)->next);
      }

      en = en->next; // move through list
  }

  return result;
}

      

EDIT There seems to be competition here, so:



Entry* filterLen(int len, Entry *en) {
   Entry *result, **temp = &result;

   for ( ; en; en = en->next) { // Move through list
      if (en->len == len) {        // Then assign values to temp list
         *temp = malloc(sizeof(Entry));
         (*temp)->word = en->word; // WARNING str shared with en list!!!
         (*temp)->len = en->len;
         temp = &((*temp)->next);
      }
   }
   *temp = NULL;
   return result;
}

      

+2


source


Entry* filterLen(int len, Entry *en) {
    Entry result = { NULL, 0, NULL };
    Entry *curr  = &result;

    while(en != NULL){
        if(en->len == len){
            Entry *temp = malloc(sizeof(*temp));
            *temp = *en;
            temp->next = NULL;
            curr = curr->next = temp;
        }
        en = en->next;
    }
    return result.next;
}

      



+2


source


From what I understood in your question, you want to return a linked list of records with len equal to the input parameter. Your code currently only stores one "temp" and you need to rebuild the new list.

struct Entry* filterLen(int len, struct Entry *en) {
  struct Entry *first = NULL;
  struct Entry *last = NULL;
  while(en != NULL) {
    if (en->len == len) {
      if(last){
        last->next = (struct Entry *)malloc(sizeof(struct Entry));
        last = last->next;
      } else {
        last = (struct Entry *)malloc(sizeof(struct Entry));
        first = last;
      }
      // assign values to temp list
      last->word = en->word;
      last->len = en->len;
      last->next = NULL;
    }
    en = en->next; // move through list
  }
  return first;

      

}

+1


source


Now your filter function copies the contents of the last found node (including the pointer next

) to temp

node. This causes the function to return the last node match plus whatever comes after it in the list.

What you need to do is create a new node every time you find the corresponding node and copy the content to the node. This includes string duplication, so you don't have to worry about potentially doubling everything.

struct Entry* filterLen(int len, struct Entry *en) {
   struct Entry *result = NULL, *temp = NULL;

   while(en != NULL) {
      if (en->len == len) {
         // copy node to end of temp list
         if (temp == NULL) {
             result =  malloc(sizeof(struct Entry));
             temp = result;
         } else {
             temp->next =  malloc(sizeof(struct Entry));
             temp = temp->next;
         }
         temp->word = strdup(en->word);  // Perform a deep copy
         temp->len = en->len;
         temp->next = NULL;
      }

      en = en->next; // move through list
   }

   return result;
}

      

+1


source







All Articles