我正在尝试将目录和子目录的名称存储在链表中。当我使用printf
显示它们时,名称正确列出,但是当我尝试将它们存储在链表中时,它们没有正确显示。
当我只是打印时,一切都有效,但是当我将字符串存储到链表中并显示它时,结果会有所不同。
void ls_r(char *path) {
DIR *dir;
struct dirent *file;
struct stat buf;
char *temp;
t_list *list;
if (!(dir = opendir(path)))
return;
list = NULL;
while ((file = readdir(dir)) != NULL) {
if (file->d_name[0] != '.') {
temp = strdup(path);
strcat(temp, "/");
strcat(temp, file->d_name);
stat(temp, &buf);
if (buf.st_mode && S_ISDIR(buf.st_mode)) {
ft_list_insert(&list, temp);
printf("%sn", temp);
ls_r(temp);
}
}
}
ft_print_list(list, "n");
}
printf
结果:
./file3
./file3/file32
./file3/file33
./file3/file31
./file3/file31/file311
./file3/file31/file313
./file3/file31/file312
./file2
./file1
./file1/file11
./file1/file12
./file1/file13
链表结果:
./file3/file31/f .@��
./file3/file31/f�-@��
./file3/file31/f./file3/file31
./file3/file33
./file3/file32./file1/file13
./file1/file12
./file1/file11./file1
./file2
./file3
这些陈述
temp = strdup(path);
strcat(temp, "/");
strcat(temp, file->d_name);
无效。
您必须保留足够的空间来包含字符串path
、"/"
和file->d_name
的串联。
所以使用例如
temp = malloc( strlen( path ) + sizeof( ( char )'/' ) + strlen( file->d_name ) + sizeof( ( char )' ' ) );
然后将字符串复制到分配的内存中。
strcpy( temp, path );
strcat(temp, "/");
strcat(temp, file->d_name);
此外,未显示其代码ft_list_insert
函数可能无法在列表中正确插入节点。
您的代码具有未定义的行为,因为您在strdup
分配的字符串末尾复制了额外的字符。必须为整个字符串分配足够的空间。
另请注意,所有不是目录的条目都有内存泄漏,您应该在返回之前释放列表。如果路径重复,ft_list_insert()
也应该释放它。
此外,测试buf.st_mode
似乎毫无用处,但必须测试stat
失败以避免读取buf
结构的未初始化内容。
这是带有实用程序功能的修改版本:
char *makepath(const char *dir, const char *name) {
size_t len1 = strlen(dir);
size_t len2 = strlen(name);
// allocate extra space for '/' and ' '
size size = len1 + len2 + 2;
char *p = malloc(size);
if (p != NULL) {
// copy the directory part
memcpy(p, dir, len1);
if (len1 > 0 && dir[len - 1] != '/') {
// only append a path separator if needed
p[len1++] = '/';
}
// copy the filename and its null terminator
memcpy(p + len1, name, len2 + 1);
}
return p;
}
void ls_r(const char *path) {
DIR *dir;
struct dirent *file;
struct stat buf;
char *temp;
t_list *list;
if (!(dir = opendir(path)))
return;
list = NULL;
while ((file = readdir(dir)) != NULL) {
if (file->d_name[0] != '.') {
temp = makepath(path, file->d_name);
if (temp != NULL && !stat(temp, &buf) && S_ISDIR(buf.st_mode)) {
ft_list_insert(&list, temp);
printf("%sn", temp);
ls_r(temp);
} else {
free(temp);
}
}
}
ft_print_list(list, "n");
ft_free_list(list); // assuming ft_free_list() also frees the list payload
}
这是工作代码:
更改:(在@chqrlie更改之上完成(
- 添加了调用 ls_r(( 函数的主函数。
- 在将实际路径写入同一内存位置之前为"char *temp"分配堆内存。
- 添加了单链表实用程序函数来维护目录列表。
- 删除了 ft_print_list(list, ""(;从 ls_r(( 调用,因为它被递归调用。将具有不同函数名称 (print_list((( 的相同调用移动到主函数。
基本上,您需要正确处理内存分配和释放。否则,您会遇到此类问题。
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
/* directory node structure */
struct dir_node
{
char *path;
struct dir_node *next;
};
typedef struct dir_node dnode;
/* Global pointers, these can be moved to main() function
* and can be passed to the required functions.
* To do that you will have to use double pointers(pointer to pointer).
* Just for understanding making these as global.
*/
dnode *newnode,*temp;
dnode *list = NULL, *last = NULL;
/*
* Creating new node.
*/
dnode* create_node(char* path)
{
newnode = (dnode *)malloc(sizeof(dnode));
if (newnode == NULL)
{
printf("nMemory was not allocated");
return NULL;
}
else
{
int path_len = strlen(path);
//make sure we have received valid path.
if(path_len <= 0)
{
free(newnode);
newnode=NULL;
return NULL;
}
newnode->path = path;
newnode->next = NULL;
return newnode;
}
}
/*
* Insert new node at the end of the list.
*/
void insert_node(char* path)
{
newnode = create_node(path);
if(newnode == NULL)
{
//Something went wrong.
//Either path is invalid or memory is not allocated properly.
return;
}
if (list == last && last == NULL)
{
//First node in the list.
list = last = newnode;
list->next = NULL;
last->next = NULL;
}
else
{
last->next = newnode;
last = newnode;
last->next = NULL;
}
}
/*
* Print the list.
*/
void print_list()
{
temp=list;
while(temp!=NULL)
{
printf("%sn",temp->path);
temp=temp->next;
}
printf("n");
}
/*
* Clear the list.
*/
void clear_list()
{
dnode* current = list;
dnode* next;
while (current != NULL)
{
next = current->next;
if(current->path != NULL)
{
free(current->path);
current->path=NULL;
}
free(current);
current = next;
}
list = NULL;
temp=list;
}
char *create_path(const char *dir, const char *name) {
size_t len1 = strlen(dir);
size_t len2 = strlen(name);
// allocate extra space for '/' and ' '
size_t size = len1 + len2 + 2;
char *p = (char *)malloc(sizeof(char)*size);
if (p != NULL) {
// copy the directory part
memcpy(p, dir, len1);
if (len1 > 0 && dir[len1 - 1] != '/') {
// add a path separator if needed
p[len1++] = '/';
}
// copy the filename and its null terminator
memcpy(p + len1, name, len2 + 1);
}
return p;
}
void ls_r(const char *path) {
DIR *dir;
struct dirent *file;
struct stat buf;
char *temp=NULL;
if (!(dir = opendir(path)))
return;
while ((file = readdir(dir)) != NULL) {
if (file->d_name[0] != '.') {
temp = create_path(path, file->d_name);
if (temp != NULL && !stat(temp, &buf) && S_ISDIR(buf.st_mode)) {
printf("%sn", temp);
insert_node(temp);
ls_r(temp);
} else {
free(temp);
}
}
}
}
int main()
{
ls_r("/work/Workspace/");
printf(".....Directory list:....n");
print_list();
clear_list();
printf(".....Directory list after clearing:....n");
print_list();
printf("...done....n");
return 0;
}