user100000
user100000

Reputation: 73

How can I make this recursive function save its content into a linked list?

the following code opens a path and recursively reads through the directories and prints the files within it. At the moment it just prints the path to the directory and then every file within it but I would like to implement a linked list that will contain 1 char* variable that contains the full path to every file visited.

Here's the code :

#include <dirent.h> 
#include <stdio.h> 
#include <string.h>

void show_dir_content(char * path)
{
    DIR * d = opendir(path);                
    if(d==NULL) return;                     
    struct dirent * dir;                        
    while ((dir = readdir(d)) != NULL)      
    {
        if(dir-> d_type != DT_DIR)          // if the type is not directory just print it
            printf("\t%s\n",dir->d_name);
        else
            if(dir -> d_type == DT_DIR && strcmp(dir->d_name,".")!=0 && strcmp(dir->d_name,"..")!=0 )   // if it is a directory
            {
                char d_path[255];                               // here I am using sprintf which is safer than strcat
                sprintf(d_path, "%s/%s", path, dir->d_name);
                printf("%s\n",d_path);
                show_dir_content(d_path);                       
            }
    }
    closedir(d);                                        
}

int main(int argc, char **argv)
{
    show_dir_content(argv[1]);
    return(0);
}

The struct used for the linked list can be quite simple such as :

typedef struct search search;
struct search {
    char *path;
    char *fileName;
    char *fullPathToFile;
    search *next;
};

I'm just having a difficult time using mallocs for the struct and creating the actual linked list within the recursive function. Any help is appreciated.

Upvotes: 0

Views: 110

Answers (2)

001
001

Reputation: 13533

You need to create a new search node every time you find a file. Fill in the new node, then add it to the end of the list.

const char *path_format = "%s/%s";

// Modified to take a node ptr. This should be the last node in the list
// Returns a node ptr. This is the new last node in the list
search * show_dir_content(char * path, search *node)
{
    DIR * d = opendir(path);                
    if(d==NULL) return node;                     
    struct dirent * dir;                        
    while ((dir = readdir(d)) != NULL)      
    {
        if(dir-> d_type != DT_DIR) {
            // Found a file. Alloc a new search node and fill in
            // (TODO: You should check the return from malloc for failure)
            search *new_node = malloc(sizeof(search));
            // TODO: copy all the names. Hint: strdup
            new_node->next = NULL;
            // Append to end of list
            node->next = new_node;
            // Update node pointer to now point to the new node
            node = node->next;
        }
        else
            if(dir -> d_type == DT_DIR && strcmp(dir->d_name,".")!=0 && strcmp(dir->d_name,"..")!=0 )   // if it is a directory
            {
                // Not sure 255 chars will be enough....
                char d_path[255];                               // here I am using sprintf which is safer than strcat
                sprintf(d_path, path_format, path, dir->d_name);
                printf("%s\n",d_path);
                // Make sure you update the node pointer to reflect any
                // changes made in the recursive call
                node = show_dir_content(d_path, node);
            }
    }
    closedir(d);
    // Return the last node (this may be same as input parameter if no files found                               
    return node;
}

Update main to create a root node and pass that to the function

int main(int argc, char **argv)
{
    search root = {0};
    show_dir_content(argv[1], &root);
    // Note that root is a dummy node.
    // The list actually begins at root->next

    // Also, before you exit, free all mem
    search *node = root.next, *next;
    while (NULL != node) {
        free(node->path);
        free(node->fileName);
        free(node->fullPathToFile);
        next = node->next;
        free(node);
        node = next;
    }

    return(0);
}

Upvotes: 1

Fabian le Maux
Fabian le Maux

Reputation: 43

I think you can modify your prototype to add a struct search * param wich gonna be the head pointeur of your list.

And when u need to put an element in your list just add a node in queue (or in head if u want but u need a struct search ** instead of a simple pointer. And then when u need to put an element just call the function which gonna create an element and place it where u want. After that u will just give to every recursive call the head ptr of your list

Upvotes: 0

Related Questions