我正在尝试将目录和子目录的名称存储在链接列表中。当我使用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("%s\n", 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
答案 0 :(得分:2)
这些声明
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 )'\0' ) );
,然后将字符串复制到分配的内存中。
strcpy( temp, path );
strcat(temp, "/");
strcat(temp, file->d_name);
此外,未显示其代码的函数ft_list_insert
可能无法在列表中正确插入节点。
答案 1 :(得分:0)
您的代码具有未定义的行为,因为您在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 '\0'
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("%s\n", 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
}
答案 2 :(得分:0)
这是工作代码:
更改 :(在@chqrlie更改之上完成)
基本上,您需要妥善处理内存分配和释放。否则,您会遇到这类问题。
#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("%s\n",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 '\0'
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("%s\n", 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;
}