2013-11-26 10 views
0

Я работаю со связанным списком, чтобы получить список всех файлов из каталога рекурсивно.Как правильно напечатать элементы связанного списка

Но по какой-то причине я не могу пройти через список, чтобы напечатать имя всех узлов. Вывод строки printf("%s\n", p->name); - это всего лишь мусор. При компиляции есть также два предупреждения. Я отметил строки с комментарием в коде ниже.

Вот код:

typedef struct { 
char *name; 
struct FileList *next; 
} FileList; 

FileList *head = NULL; 
FileList *cur = NULL; 
long int totalSize = 0; 

FileList* appendToFileList(char *name){ 
    FileList *ptr = (FileList*) malloc(sizeof(FileList)); 
    if (ptr != NULL) { 
     ptr->name = name; 
     ptr->next = NULL; 
     if (head == NULL) { //if its the first value add it to the head node 
      head = cur = ptr; 
      printf("added value to head %s\n", head->name); //this statement works correctly 
     } else { 
      cur->next = ptr; //warning "warning: assignment from incompatible pointer type" here 
      cur = ptr; 
      printf("added value %s\n", cur->name); //this statement works correctly 
     } 
    } else { 
     return NULL; 
    } 
    return ptr; 
} 

int ftwCallback(char *file, struct stat *info, int flag){ 
    if(flag == FTW_F) { //if entry is a file 
     appendToFileList(file); 
     totalSize += info->st_size; 
    } 
    return 0; 
} 

int main(int argc, char **argv){ 
    //this function walks a given directory recursively and calls "ftwcallback" for each entry 
    ftw(argv[1], ftwCallback, getdtablesize()-1); 
    FileList *p = head; 
    while (p->next != NULL){ 
     printf("%s\n", p->name); //just garbage here 
     p = p->next; //warning "warning: assignment from incompatible pointer type" here 
    } 
    printf("Total size: %d\n", totalSize); 

    return 0; 
} 

Я принял немного кода из this примера.

Что здесь не так?

+0

'p = head = NULL' Таким образом, нет возможности« p-> next »? – Gabson

+0

Кроме того, 'cur-> next = ptr; cur = ptr; '. Вы устанавливаете ptr-> next NULL, затем вы устанавливаете cur-> рядом с ptr, а также устанавливаете cur = ptr. Как вы думаете, что будет дальше? – chuthan20

+0

@ chuthan20 Я не понимаю. Я установил указатель на следующий узел текущего узла в новую выделенную память. После этого я изменяю указатель на текущий узел таким же образом, чтобы он указывал на последний узел. Если я ошибаюсь, вы могли бы дать мне более подробное объяснение, может быть, в качестве ответа? – Noir

ответ

1

Вы должны выполнить strcpy вместо присваивания, как показано ниже

старый код

ptr->name = name; 

новый код

ptr->name = malloc(strlen(name)+1); 
strcpy(ptr->name, name); 

В старом коде, name является временным указатель на стек, содержащий строку. Следовательно, этот указатель потенциально получит новое значение для каждого нового вызова функции appendToFileList. Следовательно, когда вы пытаетесь распечатать ptr->name, это указывает на недопустимое местоположение. Следовательно, это гарантирует распределение памяти и последующую копию, как это предлагается в новом коде.

+1

[Пожалуйста, не набрасывайте возвращаемое значение 'malloc()' in C] (http://stackoverflow.com/a/605858/28169). – unwind

+0

@unwind .. Сделано Я обновил сообщение – Ganesh

+0

Самый полный ответ, спасибо вам большое! Но благодаря другим вкладчикам. Такая глупая ошибка. * DOH * – Noir

1

Это потому, что вы никогда не выделяете память для имени, вы просто сохраняете указатель вызывающего.

Если указатель вызывающего абонента перестает быть действительным, ваша копия тоже делает.

Вы должны сохранить строку внутри узла или хотя бы распределить память динамически для этого.

Также please don't cast the return value of malloc() in C.

+0

+1 для ссылки на проблему malloc(). Спасибо! – Noir

0

Проблема не с печатью, а с сохранением значения.

Вы просто скопируете значение, переданное вашему методу appendToFileList. То, что char * указывает на область памяти, которая повторно используется после потери ее объема. malloc - область памяти размером достаточно и strcpy - имя файла для нее и сохраните указатель на область «malloced».

Смежные вопросы