0

A I have managed to get the linked list to function in the sense that it can create a list store variables in them, but now I have run into another issue that I've never been able find the solution to. Any time I run it through a list of variables I want stored it will run through the list and create the right number of nodes, but the string variable keeps getting changed after each append.
For example if I run:

"Dog" "cat" "house"

Instead of the desired output:

Dog
cat
house

It produces

house
house
house

I'm unsure why it keeps doing it and I can't seem to pin where the head node string is being altered except for the first instance in which the list is empty and thus needs to assign a new head.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>


#define EMPTY NULL;

typedef struct listnode{
  struct listnode* next;
  char* fileName;
} listnode;

struct listnode* head;

//This section of code will be dedicated to the creation and management
//of the listnode functions

listnode* createNode(char* str, listnode* next){
  listnode* tempo;
  tempo = (listnode*)malloc(sizeof(struct listnode));

  if(tempo == NULL){
    printf("Error creating space for new node.\n");
    exit(0);
  }

  tempo->fileName = str;
  tempo->next = next;

  return tempo;
}

listnode* append(listnode* head, char* str){
  listnode* temp;
  listnode* curr;

  temp = createNode(str, NULL);

  if(head == NULL){
    head = temp;
    return head;
  }
  else{
    curr = head;
    while(curr->next != NULL){
      curr = curr->next;
    }
    curr->next = temp;
    return head;
  }
}

void printNames(listnode* head){
  listnode* curr= head;

  while(curr !=NULL){
    printf("%s \n", curr->fileName);
    curr = curr->next;
  }
}

void list_free(listnode* head){
  listnode* current;
  listnode* temp;

  if(head != NULL){
    current = head->next;

    if(head !=NULL){
      current = head -> next;
      head ->next = NULL;
      while(current != NULL){
    temp = current -> next;
    free(current);
    current = temp;
      }
    }
  }
  free(head);
}


int main(int argc, char **argv){
  char *current_dir = NULL;
  DIR *direct_ptr = NULL;
  struct dirent *dir_ptr = NULL;
  unsigned int fileNum = 0;
  int c;
  listnode* head = NULL;

  current_dir = getenv("PWD");
  if(NULL == current_dir){
    printf("\n Error: Couldn't grab current directory.\n");
    return -1;
  }

  direct_ptr = opendir((const char*)current_dir);
  if(NULL == direct_ptr){
    printf("\n Error: couldn't open current directory\n");
    return -1;
  }


  for(fileNum=0; NULL != (dir_ptr = readdir(direct_ptr)); fileNum++){
    if(dir_ptr->d_name[0] != '.'){
      head = append(head, dir_ptr->d_name);
    }
  }
  printNames(head);
}
  • 2
    The usual reason for this, is because you are storing a pointer to the same buffer in every node, but the buffer contains just the latest string. Instead of `tempo->fileName = str;` try `tempo->fileName = strdup(str);` if your compiler supports `strdup()`. If not, you can `malloc()` sufficient memory (`strlen(fileName) + 1`) and `strcpy()` the string. – Weather Vane Oct 28 '19 at 20:13
  • Possible duplicate of [Linked list of strings has the same strings for each node](https://stackoverflow.com/questions/47863608/linked-list-of-strings-has-the-same-strings-for-each-node). – Weather Vane Oct 28 '19 at 20:25

1 Answers1

0

In C, arrays (such as strings) are not passed by value. They are instead passed by pointer. When you specify the a char array as a function parameter, the array decays to a pointer.

Therefore, you must either

  1. ensure that the string that the listnode struct member filename points to remains valid and is not overwritten, or
  2. store a copy of the string in the listnode struct.

In order to copy a string, you can use the function strcpy. However, you must then either allocate enough space for the char array in the listnode struct or you must use dynamic memory allocation (such as malloc) and store a pointer to the dynamically allocated memory.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39