La valeur de la structure stat contenait la structure perdue

J’essaie de coder la fonction de ls à partir de zéro. Pour ce faire, j’ai créé une liste liée de structures contenant les informations de chaque fichier / structure.

Voici la structure:

typedef struct s_ls { char *name; struct stat stat; struct s_ls *next; } t_ls; 

J’ai ensuite créé une liste chaînée:

 t_ls *ft_store(char *foldername) { t_ls *stock = NULL; DIR *dir; struct dirent *dent; dir = opendir(foldername); if(dir != NULL) { while((dent = readdir(dir)) != NULL) { stock = ft_add_elem(dent->d_name, stock); stat(stock->name, &(stock->stat)); } } return (stock); } 

La fonction ft_add_elem mallocs une nouvelle structure, ajoute un nouvel élément par ordre alphabétique et renvoie un pointeur sur le premier élément de la manière suivante:

 t_ls *ft_new_elem(char *name) { t_ls *tmp; if (!(tmp = malloc(sizeof(t_ls)))) exit(1); tmp->name = ft_strdup(name); return (tmp); } t_ls *ft_add_elem(char *name, t_ls *stock) { t_ls *new; t_ls *check; new = ft_new_elem(name); if (!stock) return (new); check = stock; while (check && check->next && ft_strcmp(check->next->name, new->name) next; new->next = check->next; check->next = new; return (stock); } 

Mon problème est que lorsque je passe en revue les éléments pour les imprimer lorsque l’option -l est déclenchée, par exemple, toutes les structures stat sont vides, à l’exception du premier. Ce n’est cependant pas le cas si je les imprime à partir de la même fonction qui les remplit (ft_store).

Le problème est que ft_add_elem() renvoie le pointeur sur le premier élément de la liste, et non sur l’élément qui vient d’être ajouté. Vous conservez la liste dans l’ordre sortingé (via la fonction ft_strcmp() ). Donc, vous continuez à exécuter stat() sur le prénom de la liste – ce qui sera le cas . sauf si vous avez des fichiers inhabituels dans votre répertoire (actuel).

Correction qui est un peu plus complexe. Il est probablement préférable de faire l’opération stat() dans ft_add_elem() . Notez toutefois que vous devez également vous préoccuper du chemin d’access au répertoire à partir duquel vous lisez les entrées. Si vous êtes en train de traiter (le répertoire actuel) seulement, alors cela fonctionnera. Si vous traitez d’autres répertoires, vous devez créer le chemin du fichier en préfixant le nom du répertoire au nom du fichier.

Cela vaut également la peine de s’assurer que le nouvel élément est complètement initialisé. cela évite un comportement accidentellement indéfini.

Voici un code fixe. Les fonctions dont le nom commence par err_ sont disponibles sur Github ( https://github.com/jleffler/soq/tree/master/src/libsoq ) dans stderr.c et stderr.h . Ils sont utilisés pour simplifier la notification des erreurs.

 #include "stderr.h" #include  #include  #include  #include  #include  #include  #define ft_strcmp(s, t) strcmp(s, t) #define ft_strdup(s) strdup(s) typedef struct s_ls { char *name; struct stat stat; struct s_ls *next; } t_ls; static t_ls *ft_new_elem(char *name) { t_ls *tmp; if (!(tmp = malloc(sizeof(t_ls)))) err_error("Failed to allocate %zu bytes of memory\n", sizeof(*tmp)); tmp->name = ft_strdup(name); tmp->next = 0; tmp->stat = (struct stat){ 0 }; return(tmp); } static t_ls *ft_add_elem(char *name, const char *dirname, t_ls *stock) { t_ls *new; t_ls *check; new = ft_new_elem(name); if (!stock) return(new); check = stock; while (check && check->next && ft_strcmp(check->next->name, new->name) < 0) check = check->next; new->next = check->next; check->next = new; char pathname[strlen(dirname) + strlen(name) + 2]; sprintf(pathname, "%s/%s", dirname, name); if (stat(pathname, &new->stat) < 0) err_sysrem("Failed to stat '%s': ", pathname); return(stock); } static t_ls *ft_store(char *foldername) { t_ls *stock = NULL; DIR *dir; struct dirent *dent; dir = opendir(foldername); if (dir != NULL) { while ((dent = readdir(dir)) != NULL) { stock = ft_add_elem(dent->d_name, foldername, stock); } } return(stock); } int main(int argc, char **argv) { err_setarg0(argv[0]); if (argc < 2) { argc = 2; argv = (char *[]){ ".", 0 }; } for (int i = 1; i < argc; i++) { t_ls *list = ft_store(argv[i]); t_ls *node = list; while (node != 0) { printf("Name: %s (size %llu)\n", node->name, node->stat.st_size); node = node->next; } } return 0; } 

Le code utilise deux littéraux composés, une fonctionnalité de C99. Il existe d’autres moyens pour obtenir les mêmes effets.

Exécuter le programme ( rd37 ) sur un répertoire, etc donné:

 $ ./rd37 etc Name: . (size 0) Name: .. (size 2448) Name: .gitignore (size 38) Name: README.md (size 99) Name: posix-opt-end.gif (size 65) Name: posix-opt-start.gif (size 69) Name: soq-head.mk (size 1618) Name: soq-tail.mk (size 665) Name: suppressions (size 16139) Name: suppressions-macos-10.12.5 (size 4998) $ ls -l etc total 88 -rw-r--r-- 1 jleffler staff 99 Jul 9 2016 README.md -rw-r--r--@ 1 jleffler staff 65 Nov 10 2016 posix-opt-end.gif -rw-r--r--@ 1 jleffler staff 69 Nov 10 2016 posix-opt-start.gif -rw-r--r-- 1 jleffler staff 1618 Jun 16 23:38 soq-head.mk -rw-r--r-- 1 jleffler staff 665 Aug 16 2016 soq-tail.mk -rw-r--r-- 1 jleffler staff 16139 Aug 20 2016 suppressions -rw-r--r-- 1 jleffler staff 4998 May 21 15:40 suppressions-macos-10.12.5 $