Je suis fatigué (je continuerai demain) sinon :
Ne m'indique rien de nouveau.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 S_ISDIR(m) Test for a directory.
(Pouvez-vous me donner un petit code avec une macro imaginaire pour que je comprenne la syntaxe ou méthode ?)
Et pour la preuve :
Sur : http://man.developpez.com/man2/stat.2.phpVALEUR RENVOYÉE
Ces fonctions retournent zéro si elles réussissent. En cas d'echec -1 est renvoyé, et errno contient le code d'erreur.
Tu as compris ce que renvoyait la macro ? Il suffit de la placer dans un if (comme un appel de fonction) et c'est tout :
je ne vois pas où est la difficulté...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 if (S_ISDIR(m)) faire ceci else faire cela...
Ceci concerne la fonction stat(), par exemple. Rien à voir avec les macros...
Merci.
Oui, elle renvoit 0 si c'est faux :
En fait, m c'est quoi comme type de variable ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 if(S_ISDIR(infos.st_mode)==0) { printf("files"); } else { printf("folder"); }![]()
Oui,mais on ne met pas '== 0', c'est inutile. On met juste if(lamacro(xxx)). Restons simple... Parce un jour tu seras tenté de mettre '== 1' et là boum, ça ne marchera pas. La norme dit "0 ou <>0", il n'y a rien à ajouter.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 if(S_ISDIR(infos.st_mode)==0)
Purée... relis la doc que je t'ai passé (posix.1). Pourquoi a-t-on appelé stat() à ton avis ? Tu penses que la réponse je vais la trouver où ? Apprends à lire la doc. Si tu ne le fais pas, je ne peux rien pour toi, c'est 40 à 50% de ce métier...
Code : Sélectionner tout - Visualiser dans une fenêtre à part En fait, m c'est quoi comme type de variable ? :)
Bon j'ai trouvé la phrase :
Donc m c'est la valeur de myStruct.st_modeThe following macros shall be provided to test whether a file is of the specified type. The value m supplied to the macros is the value of st_mode from a stat structure. The macro shall evaluate to a non-zero value if the test is true; 0 if the test is false.
Mais je ne comprend pas, il serait plutôt logique de demander comme paramètre le chemin du fichier/dossier ?!
Apparement (d'après ce que j'ai lu) m c'est le mode du fichier :
Voilà le code :mode_t st_mode Mode of file (see below).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <dirent.h> #include <errno.h> #include "myHeader.h" int lister(char *directory); int main(int argc, char **argv) { struct stat infos; char directory[256]; fgets(directory, sizeof directory, stdin); fclean(directory, stdin); stat(directory, &infos); if(S_ISDIR(infos.st_mode)) { printf("files"); } else { printf("folder"); } fprintf(stdout, "\n"); system("PAUSE"); return 0; }
Bien. Effectivement, tout est là.
Oui.Donc m c'est la valeur de myStruct.st_mode
Gné ? La vrai question est de savoir comment myStruct.st_mode a été initialisée.Mais je ne comprend pas, il serait plutôt logique de demander comme paramètre le chemin du fichier/dossier ?!
Ce qu'il y a dans les branches de test est toujours aussi faux...Voilà le code :
Correction :
Pose des questions si tu ne comprends pas.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 #include <stdio.h> #include <string.h> #include <sys/stat.h> /* made from 100% recycled bits */ void fclean (char *s_buffer, FILE * stream) { if (s_buffer != NULL && stream != NULL) { char *pc = strchr (s_buffer, '\n'); if (pc != NULL) /* La saisie n'a pas ete tronquee */ { /* On remplace '\n' par le caractere nul '\0' */ *pc = 0; } else { /* La saisie a ete tronquee, on purge le flux d'entree */ int c; while ((c = fgetc (stream)) != '\n' && c != EOF) { } } } } int main (void) { int end; do { char directory[256]; printf ("nom (ou <enter> pour quitter) : "); fgets (directory, sizeof directory, stdin); fclean (directory, stdin); end = *directory == 0; if (!end) { struct stat infos; stat (directory, &infos); if (S_ISDIR (infos.st_mode)) { printf ("'%s' is a folder\n", directory); } else { printf ("'%s' is a file\n", directory); } } } while (!end); return 0; }
(et je rappelle : UN problème par code de test ou snippet...)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 nom (ou <enter> pour quitter) : main.c 'main.c' is a file nom (ou <enter> pour quitter) : .. '..' is a folder nom (ou <enter> pour quitter) : . '.' is a folder nom (ou <enter> pour quitter) : \ '\' is a folder nom (ou <enter> pour quitter) : \autoexec.bat '\autoexec.bat' is a file nom (ou <enter> pour quitter) : Press ENTER to continue.
Merci (votre code ne donne aucun résultat mais je vais essayer de comprendre pourquoi) :
Je ne comprend un truc. Si l'on fait char directory[256], *directory n'a aucune adresse ?
Pouve-vous m'expliquer cette ligne ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2end = *directory == 0;
Sinon lorsque je rentre :
C:\Users\SamSoft\Documents\Programmation\doc\C\array\arrays.mht
Il me met : folder
La ligne que tu comprends mal est plus explicite ainsi:
En clair, la variable end devient non-nulle si le premier caractère de la chaîne est nul (donc, si la chaîne est vide).
Code : Sélectionner tout - Visualiser dans une fenêtre à part end = (directory[0] == '\0');
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Ah okMais il reste un problème : le fait d'écrire : c:\monFichier.txt me sort folder
Aucun résultat ? C'est à dire ?
Euh, tu apprends le C dans le désordre ? Ce genre de question basique devrait être réglée avant de s'attaquer aux répertoires...Je ne comprend un truc. Si l'on fait char directory[256], *directory n'a aucune adresse ?
Un tableau de char a une adresse qui est celle du premier élément de ce tableau. Il se trouve que lorsqu'on passe un tableau à une fonction, celui-ci est automatiquement converti en une adresse ... qui est celle du premier élément du tableau.
*directory est la même chose que directory[0]. Ca désigne la valeur du prelier élément du tableau.Pouve-vous m'expliquer cette ligne ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2end = *directory == 0;
Si cette valeur est 0 (ou '\0'), c'est qu'on a rien saisi. (chaine 'vide').
L'expression *directory == 0 est donc vérifiée, elle vaut donc 1.
donc end vaut 1.
Alors c'est que tu n'utilises pas mon code...Sinon lorsque je rentre :
C:\Users\SamSoft\Documents\Programmation\doc\C\array\arrays.mht
Il me met : folder
Tu as fait les tests avec des répertoires et fichiers dont tu es sûr de l'existence, comme je l'ai fait ?
En fait, il y'a préalable qui n'est pas testé ici, c'est que le fichier (ou le répertoire) existe...
Lire la doc de stat(), mais il faut probablement tester le retour avant d'agir...
Une fois la correction faite :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 nom (ou <enter> pour quitter) : xxx 'xxx' is unknown nom (ou <enter> pour quitter) : .. '..' is a folder nom (ou <enter> pour quitter) : main.c 'main.c' is a file nom (ou <enter> pour quitter) : Press ENTER to continue.
Médinoc me l'a expliqué mais je ne le savais pas avant*directory est la même chose que directory[0]. Ca désigne la valeur du prelier élément du tableau.
Si cette valeur est 0 (ou '\0'), c'est qu'on a rien saisi. (chaine 'vide').
L'expression *directory == 0 est donc vérifiée, elle vaut donc 1.
donc end vaut 1.
Sinon, oui le fichier existe, si je met main.c ca marche mais un chemin style c:\monFichier ne marche pas (il me met folder) alors que le chemin est tout à fait correct (le fichier existe).
Mon code est correct. La dernière version avec test du fichier :
Essaye le tel quel sans changer un iota.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 #include <stdio.h> #include <string.h> #include <sys/stat.h> /* made from 100% recycled bits */ void fclean (char *s_buffer, FILE * stream) { if (s_buffer != NULL && stream != NULL) { char *pc = strchr (s_buffer, '\n'); if (pc != NULL) /* La saisie n'a pas ete tronquee */ { /* On remplace '\n' par le caractere nul '\0' */ *pc = 0; } else { /* La saisie a ete tronquee, on purge le flux d'entree */ int c; while ((c = fgetc (stream)) != '\n' && c != EOF) { } } } } int main (void) { int end; do { char directory[256]; printf ("nom (ou <enter> pour quitter) : "); fgets (directory, sizeof directory, stdin); fclean (directory, stdin); end = *directory == 0; if (!end) { struct stat infos; int err = stat (directory, &infos); if (!err) { if (S_ISDIR (infos.st_mode)) { printf ("'%s' is a folder\n", directory); } else { printf ("'%s' is a file\n", directory); } } else { printf ("'%s' is unknown\n", directory); } } } while (!end); return 0; }
J'avais du faire une mauvaise manipulation, ca fonctionne parfaitement. Je vais essayer de dresser une liste de fichiers si c'est un répertoire
Merci Emmanuel (je ne poste pas encore résolu)
Bon alors voilà j'ai pris le code que l'on trouve sur le site et je l'ai couplé avec celui que j'ai déjà. Ca donne ceci :
Bon, ca compile (avec les paramètres que propose Emmanuel sur son site)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <dirent.h> #include <errno.h> #include <sys/stat.h> #include "myHeader.h" int lister(char *directory); int main (void) { int end; do { char directory[256]; printf ("nom ou <enter> pour quitter) : "); fgets (directory, sizeof directory, stdin); fclean (directory, stdin); end = (directory[0] == '\0'); if (!end) { lister(directory); } } while (!end); return 0; } int lister(char *directory) { DIR *dir = NULL; struct dirent *file = NULL; struct stat infos; stat (directory, &infos); if((dir = opendir(directory)) == NULL) { return EXIT_FAILURE; } printf("Repertoire %s :\n", directory); while((file = readdir(dir)) != NULL) { if(strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { if(S_ISDIR (infos.st_mode)) { lister(strncat(directory, file->d_name, 256)); } else { printf("\t%s\n", file->d_name); } } } printf("Fin repertoire %s\n", directory); closedir(dir); return EXIT_SUCCESS; }
Si je met :
C:\
Il me met :
Je pense que c'est parce que je mélange dirent et stat peut être que je ne devrais utiliser que stat ?nom ou <enter> pour quitter) : c:\
Repertoire c:\ :
Repertoire c:\$Recycle.Bin :
Fin repertoire c:\$Recycle.BinS-1-5-21-1977114147-3677329669-3575530183-500S-1-5
-21-2152478756-3922319563-605102323-500S-1-5-21-2256296683-2490543695-1737019047
-500S-1-5-21-3292954902-2297236452-2890570197-1000S-1-5-21-3950889498-3502377534
-3191853766-500
Merci d'avance![]()
C'est surtout que comme d'habitude, tu veux aller trop vite. Ce que tu veux tester, c'est si chaque entrée lue est un répertoire ou non.
Alors commence par appliquer stat() à la bonne valeur, c'est à dire aux entrées lues ! Simple bon sens.
Mets une trace pour vérifier la tronche de ce que fabrique avec strncat().
Enfin, se lancer dans récursivité quand on débute n'est pas forcément une bonne idée. Lister des répertoire imbriqués est une opérations assez délicate qui peu se terminer en crash assez rapidement... La méthode de l'accumulation des noms (surtout si il manque le séparateur, hum...) n'est pas forcément la meilleure. Un changement de répertoire est souvent suffisant. (chdir() avec ".." pour remonter).
Enfin, ne commence pas par tester la racine de ton disque, parce que c'est ce qu'il y a de plus long... Contente toi de 2 ou 3 répertoires imbriqués... (le répertoire courant de Code::Blocks est largement suffisant pour le test).
Merci
J'avance
Si je tape c:\Dev-Cpp il me met :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <dirent.h> #include <errno.h> #include <sys/stat.h> #include "myHeader.h" int lister(char *directory); int main (void) { int end; do { char directory[256]; printf ("nom ou <enter> pour quitter) : "); fgets (directory, sizeof directory, stdin); fclean (directory, stdin); end = (directory[0] == '\0'); if (!end) { lister(directory); } } while (!end); return 0; } int lister(char *directory) { DIR *dir = NULL; struct dirent *file = NULL; struct stat infos; stat (directory, &infos); if((dir = opendir(directory)) == NULL) { return EXIT_FAILURE; } printf("Repertoire %s :\n", directory); while((file = readdir(dir)) != NULL) { if(strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { if(S_ISDIR (infos.st_mode)) { stat (file->d_name, &infos); lister(strncat(directory, file->d_name, 256)); } else { printf("\n\t%s\n", file->d_name); } } } printf("\nFin repertoire %s\n", directory); closedir(dir); return EXIT_SUCCESS; }
La fin est un peu étrange, ca doit venir d'une mauvaise assignation de valeur mais je ne vois pas oùnom ou <enter> pour quitter) : c:\Dev-Cpp
Repertoire c:\Dev-Cpp :
main.o
Makefile.win
mingw32
NEWS.txt
Packages
Packman.exe
Packman.map
Projet1.dev
Projet1.exe
Projet1.layout
Templates
uninstall.exe
Fin repertoire c:\Dev-CppbinclearScreen.hcopying.txtdevcpp.exedevcpp.mapExamples
HelpIconsIcons.rarincludeLangliblibexecmain.c
nom ou <enter> pour quitter) :
Sinon c'est bon(enfin je crois)
C'est mieux. Maintenant, il faut contrôler (visualiser) ce que fait strncat(). D'ailleurs, tu l'utilises mal. C'est :
(il manque donc un paramètre size quelque part...)
Code : Sélectionner tout - Visualiser dans une fenêtre à part strncat (dest, src, size - strlen (dest) - 1);
Mais ça ne fait que masquer silencieusement le problème de débordement sans le signaler. Il vaudrait mieux anticiper et n'utiliser strcat() que quand c'est possible.
Mais comme je te l'ai dit, le mécanisme à accumulation, c'est bien joli, mais ça ne résout pas le problème, (même avec les bons séparateurs). Comment tu remontes ? N'oublie pas qu'un système de fichiers est une arborescence...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 if (strlen (src) + strlen (dest) + 1 < size) { strcat (dest, src); } else { /* prendre des mesures... */ }
Il y a peut être aussi un problème d'ordre d'exécution... (Enfin, je ne sais pas ce que tu veux faire exactement...)
Merci Emmanuel.
Je suis allé sur : http://www710.univ-lyon1.fr/~jciehl/...strncat.3.html et j'ai compris ce qu'il manquait. Mais je n'ai pas compris quelque chose, size c'est la taille de quoi ?
Et aussi : "prendre de mes mesures", lesquelles ?
Partager