将dirent结构体中文件/文件夹名存入链表后仅首个条目可打印的问题
问题分析与解决方案
你的代码存在两个核心问题,导致仅能输出第一个文件条目:
1. 链表节点未正确链接
原代码中,初始创建head节点后,cur指向head。第一次循环赋值cur->name并将cur->next设为NULL,随后cur = cur->next变为NULL。后续循环中虽然重新malloc了cur,但这个新节点并没有被链接到前一个节点的next指针上,导致链表断链,只有第一个节点在链表中。
2. 文件名指针复用问题
pDirent->d_name指向的是readdir内部的缓冲区,每次调用readdir都会覆盖这个缓冲区的内容。直接将cur->name赋值为该指针,会导致所有节点的name最终指向同一个缓冲区,显示的都是最后一次readdir读取的文件名(甚至可能出现未定义行为)。
修改后的代码
修复后的完整代码
#include <stdio.h> #include <dirent.h> #include <stdlib.h> #include <string.h> #include <errno.h> typedef struct s_files { char *name; struct s_files *next; } t_files; t_files *add_files() { DIR *pDir; struct dirent *pDirent; t_files *head = NULL; t_files *cur = NULL; // 检查目录打开是否成功 pDir = opendir("."); if (!pDir) { perror("opendir failed"); return NULL; } while((pDirent = readdir(pDir))) { // 创建新节点并检查内存分配 t_files *new_node = malloc(sizeof(t_files)); if (!new_node) { perror("malloc failed"); closedir(pDir); return head; } // 复制文件名,避免复用内部缓冲区 new_node->name = strdup(pDirent->d_name); if (!new_node->name) { perror("strdup failed"); free(new_node); closedir(pDir); return head; } new_node->next = NULL; // 将新节点链接到链表尾部 if (!head) { head = new_node; cur = new_node; } else { cur->next = new_node; cur = new_node; } } closedir(pDir); return head; } void print_files(t_files *head) { for ( ; head != NULL; head = head->next ) printf( "%s ", head->name); printf("\n"); // 添加换行,输出更整洁 } // 添加内存释放函数,避免内存泄漏 void free_files(t_files *head) { t_files *tmp; while (head) { tmp = head; head = head->next; free(tmp->name); free(tmp); } } // 示例主函数 int main() { t_files *file_list = add_files(); if (file_list) { print_files(file_list); free_files(file_list); } return 0; }
修改说明
- 链表构建逻辑优化:使用头指针和尾指针的方式,确保每个新节点都被正确链接到链表尾部,不会出现断链情况。
- 文件名复制:使用
strdup复制d_name的内容,每个节点拥有独立的文件名内存,避免缓冲区覆盖问题。 - 错误检查:添加了
opendir、malloc、strdup的错误检查,增强代码鲁棒性。 - 内存释放:新增
free_files函数,用于释放链表节点和复制的文件名内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者imbaled
相关产品推荐
相关产品推荐

