【问题标题】:Proper Way to Set Up a Linked List to Store a Group ID and File Path设置链接列表以存储组 ID 和文件路径的正确方法
【发布时间】:2021-05-28 14:18:21
【问题描述】:

我正在尝试创建一个链表数据结构,它允许我存储组 ID # 以及它所属的文件目录的文件路径。该程序打开当前目录并从当前目录中获取所有常规文件,它输出每个文件的路径,并尝试将路径插入到链表中。对于它插入的每个文件路径,将创建一个新的 groupID(将 1 添加到之前的 groupID # ),从第一个 groupID 的 1 开始。到目前为止,这是我的代码:

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

typedef struct FileGroups
{
    int groupID;
    char *path;
    struct FileGroups* next;
} FileGroups;

FileGroups *head;

void insert(char *path)
{
    FileGroups *temp;
    temp = (FileGroups*)malloc(sizeof(FileGroups));
    temp->groupID += 1;
    temp->path = path;
    temp->next = head;
    head = temp;
    temp = temp ->next;
}

void print()
{
    FileGroups *temp;
    temp = head;
    printf("\nLinked list: \n");
    while(temp!=NULL)
    {
        printf("%d %s\n", temp->groupID, temp->path);
        temp = temp->next;
    }
}

void listFilesRecursively(const char *basePath)
{
    char path[1024];
    struct dirent *dp;
    DIR *dir = opendir(basePath);

    if (!dir)
    {
        return;
    }

    while ((dp = readdir(dir)) != NULL)
    {
        if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
        {
            struct stat sb;

            strcpy(path, basePath);
            strcat(path, "/");
            strcat(path, dp->d_name);

            if(stat(path, &sb) == 0 && S_ISREG(sb.st_mode))
            {
                printf("%s\n", path);
                insert(path);
            }

            else
            {
                return;
            }
        }
    }
    closedir(dir);
}

int main()
{
    listFilesRecursively(".");

    print();

    return 0;
}

当我打印出链表时,我得到以下输出:

在上半部分,您可以看到我当前目录中的所有常规文件,下面是我的链接列表,它似乎只存储我当前目录中列出的最后一个文件,并且在左侧我们看到 groupID #也没有改变,而不是在添加每个文件路径时加 1,它卡在 groupID #1。任何关于我哪里出错的建议或指示将不胜感激。谢谢!

【问题讨论】:

    标签: c unix linked-list system singly-linked-list


    【解决方案1】:

    在每次迭代中,path 都会被覆盖并分配给列表的新元素,但您不会将字符串复制到新缓冲区。
    因此,最后列表中的每个元素都将指向listFilesRecursively() 中声明的path,它只包含列出的最后一个文件

    ...
    int GroupID = 1;
    
    void listFilesRecursively(const char *basePath)
        ...
        char path[1024];
        ...
    // Here path is overwritten
        strcpy(path, basePath);
        strcat(path, "/");
        strcat(path, dp->d_name);
        ...
        insert(path);
    
    void insert(char *path)
        ...
    // This is copying only the pointer to path
        temp->path = path;
    

    您应该在插入时为路径分配一个新的缓冲区。

    void insert(char *path)
    {
        FileGroups *temp;
        temp = (FileGroups*)malloc(sizeof(FileGroups));
    /**
     * This should not be += 1
     * Memory allocated by malloc is not initialised.
     * Value at these locations are indeterminate.
     *
     * To know the next groupID I'm using a simple
     * global variable as suggested by Serge Ballesta
     * in his comment
     */
        temp->groupID = GroupID++;
    //------------------------------------------------------
        temp->path = malloc(strlen(path)*sizeof(char));
        strcpy(temp->path, path);
    //------------------------------------------------------
        temp->next = head;
        head = temp;
        temp = temp ->next;
    }
    

    你可以在这里运行它https://onlinegdb.com/O6cTm7Hu1

    关于malloc()Is malloc() initializing allocated array to zero?

    【讨论】:

    • OP 希望在每个元素上增加 groupID。由于head 已经是一个全局变量,您可以使用一个全局变量int GroupID = 1;,然后在函数temp-&gt;groupID = GroupID++; 中使用。或者,您可以在函数本身中使用 static int GroupID = 1;
    • @SergeBallesta 你说得对,我在编辑答案时忘记了这一点。谢谢
    猜你喜欢
    • 2019-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-29
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多