Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Candidat au Club
    Programme de recherche de fichier (crash)
    Bonjour, je suis en train de créer un programme permettant de rechercher un fichier dans un répertoire (et ses sous répertoires). Le fonctionement est le suivant:

    -L'utilisateur donne le chemin au programme (via la variable path), ensuite le programme parcours l'arborescence dossier par dossier jusqu'à arriver au bout. Une fois au bout il ajoute ce répertoire dans un tableau pour ne pas y aller encore.
    Ensuite, le programme revient au répertoire du début et recommence l'opération jusqu'à ce qu'il ne reste plus de répertoire (cela voudras donc dire que la recherche sera terminée) et bien sûr tout celà en analysant le nom des fichiers et noter le résultat dans un fichier texte avec le chemin des fichiers trouvés.

    Voici le code du premier programme que j'ai fait (celui ci est fonctionnel mais le tableau "d'exclusion" arrive vite à saturation quand il y a beaucoup de répertoires car celui ci est trop petit et on ne peut pas l'agrandir car la taille est fixée ce qui fait planter.)
    Celui ci est configuré pour rechercher les fichiers *.exe
    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
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h> //pour lire les répertoires
    #include <string.h>
    #include <errno.h>
     
    #define MAX_FILE_ARRAY 1000
    #define MAX_FILE_NAME 300
     
    #define EXCLUDE_MAX_FILE_ARRAY 3000
    #define EXCLUDE_MAX_FILE_NAME 500
     
     
    int is_dir(char *name);
    int get_dir(char path[], char file_array[][MAX_FILE_NAME]); //fonction remplissant un tableau donné avec les fichiers de l'adresse contenue dans "path"
    int dir_db(char *path, char exclude_array[][EXCLUDE_MAX_FILE_NAME], int mode, int *global_cmp); //fonction permettant de connaître et d'inscrire dans un tableau les dossiers déja visités
     
    int main(int argc, char *argv[]) {
    	/*initialisation des tableaux 2D*/
    	char file_array[MAX_FILE_ARRAY][MAX_FILE_NAME];
    	char exclude_array[EXCLUDE_MAX_FILE_ARRAY][EXCLUDE_MAX_FILE_NAME]; //tableau d'exclusion problématique (3000 cases)
     
     
    	char path[] = "."; //le chemin dans lequel on va rechercher (en l'occurence le dossier actuel)
    	char actual_path[MAX_FILE_NAME] = "";
     
    	FILE *result_file = fopen("resultat.txt", "w");
    	if (result_file == NULL) {
    		puts("impossible d'ouvrir le fichier !");
    		exit(1);
    	}
     
    	int begin = 0; 
    	int cmp = 0;
    	int global_cmp = 0;
    	int nbr_file = get_dir(path, file_array); //remplir le tableau de fichier une première fois
    	while (1) {
    	while (cmp < nbr_file) {
    		printf("occurence %d: %s\n",cmp, file_array[cmp]); //afficher le chemin du fichier actuel
    		if (( is_dir(file_array[cmp]) ) && (dir_db(file_array[cmp], exclude_array, 0, &global_cmp) == 0) ) { //si ce fichier est un répertoire ET qu'il n'est pas présent dans le tableau d'exclusion
    			puts("repertoire !");
    			strcpy(actual_path, file_array[cmp]); //remplace le path du chemin actuel par ce répertoire
    			printf("nv chemin : %s\n", actual_path);
     
    			nbr_file = get_dir(actual_path, file_array); //remplir le tableau avec les fichiers du répertoire
    			printf("nombre de fichiers : %d\n", nbr_file); 
    			cmp = 0;
    			begin = 1; //cette variable sert à ne pas incrémenter compt quand celle ci est égale à 0 car sinon on ne traite pas la première case du tableau
     
    		}
     
    		if (nbr_file == 0) {
    			puts("le dossier est vide");
    			break;
    		}
    		if ((strstr(file_array[cmp], ".exe") != NULL) && begin != 1) { //si un fichier "*exe" est trouvé 
    			puts("fichier trouve !!!");
    			fprintf(result_file,"%s\n", file_array[cmp]); //inscription du résultat
    		}
    		if (begin != 1) {cmp++;} else {begin = 0;} 
     
    	}
     
    	if (strcmp(actual_path, path) == 0) {
    		puts("Fin de la recherche");
    		fclose(result_file);
    		break;
    		break;
    	}
     
    	printf("fin du chemin, ajout de \"%s\" a la base d'exclusion \n", actual_path);
    	printf("global: %d",global_cmp);
     
    	dir_db(actual_path, exclude_array, 1, &global_cmp);
    	nbr_file = get_dir(path, file_array); //revient au path premier
    	strcpy(actual_path, path);
    	cmp = 0;
    	begin = 1;
    	}
    	return 0;
    }
     
     
    int get_dir(char path[], char file_array[][MAX_FILE_NAME]) {
    	struct dirent *actual_folder;
    	DIR *pFolder;
    	pFolder = opendir(path);
    	int compteur = 0;
    	if (pFolder == NULL) {
    		perror("opendir() error");
    	}
    	readdir(pFolder); //SKIP . AND ..
    	readdir(pFolder);
     
    	while ((actual_folder = readdir(pFolder)) != NULL) {
    		file_array[compteur][0] = '\0'; //remet l'array à "zero"
    		char *tmp = actual_folder->d_name;
    		//puts(actual_folder->d_name); //afficher le fichier actuel (debug)
    		strcat(file_array[compteur], path);
    		strcat(file_array[compteur], "/");
    		strcat(file_array[compteur], tmp);
    		compteur++;
    	}
    	closedir(pFolder);
    	return compteur; //renvoie le nombre d'élément du tableau
    }
     
     
    int is_dir(char *name) { //cette fonction vérifie si le fichier est un dossier ou
        DIR *file = opendir(name);
     
    	if (file == NULL) {
    		closedir(file);
    		return 0; //ce n'est pas un dossier 
    	} else {
    		closedir(file);
    		return 1; //c'est un dossier
    	}
    }
     
    int dir_db(char *path, char exclude_array[][EXCLUDE_MAX_FILE_NAME], int mode, int *global_cmp) { 
    	if (mode) {
    		int tmp = *global_cmp;
    		strcpy(exclude_array[tmp], path); //copier le path envoyé dans le tableau
    		(*global_cmp)++;
    	} else if (!mode) {
    		int tmp = *global_cmp;
    		if (tmp == 0) { 
    			puts("tableau vide en lecture");
    			return 0;
    		}
    		int i;
    		for (i=0; i<tmp; i++) { //parcours le tableau et compare chaques occurences avec le path envoyé
    			if (strcmp(exclude_array[i], path) == 0) { //si le path envoyé est identique au texte stocké dans le tableau
    				return 1; //le path est présent 
    			}
    		} 
    		return 0; //le path n'est pas présent
    	}
    }


    Pour pallier à celà, j'ai donc essayé de créer un tableau alloué dynamiquement qui s'agrandis à chaque passages (exclude_array) dans la boucle pour stocker dans la mémoire les valeurs. Mais le programme plante...

    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
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h>
    #include <string.h>
    #include <errno.h>
     
    #define MAX_FILE_ARRAY 3000
    #define MAX_FILE_NAME 500
     
     
     
    int is_dir(char *name);
    int get_dir(char path[], char file_array[][MAX_FILE_NAME]);
    int dir_db(char *path, char **exclude_array, int mode, int *global_cmp);
     
    int main(int argc, char *argv[]) {
    	/*initialisation des tableaux 2D*/
    	char file_array[MAX_FILE_ARRAY][MAX_FILE_NAME];
    	char **exclude_array = (char**)malloc(2*sizeof(char*)); //initialise le tableau avec 2 cases pour laisser un peu de place
     
     
    	char path[] = "."; //le chemin dans lequel on va rechercher
    	char actual_path[MAX_FILE_NAME] = "";
     
    	FILE *result_file = fopen("resultat.txt", "w");
    	if (result_file == NULL) {
    		puts("impossible d'ouvrir le fichier !");
    		exit(1);
    	}
     
    	int begin = 0; 
    	int cmp = 0;
    	int global_cmp = 0;
    	int nbr_file = get_dir(path, file_array); //remplir le tableau de fichier une première fois
     
    	while (1) { //boucle principale
    	while (cmp < nbr_file) {
    		printf("occurence %d: %s\n",cmp, file_array[cmp]); //afficher le chemin du fichier actuel
    		if (( is_dir(file_array[cmp]) ) && (dir_db(file_array[cmp], exclude_array, 0, &global_cmp) == 0) ) { //si ce fichier est un répertoire ET qu'il n'est pas présent dans le tableau d'exclusion
    			puts("repertoire !");
    			strcpy(actual_path, file_array[cmp]); //remplace le path du chemin actuel par ce répertoire
    			printf("nv chemin : %s\n", actual_path);
     
    			nbr_file = get_dir(actual_path, file_array); //remplir le tableau avec les fichiers du répertoire
    			printf("nombre de fichiers : %d\n", nbr_file); 
    			cmp = 0;
    			begin = 1; //cette variable sert à ne pas incrémenter cmp quand celle ci est égale à 0 car sinon on ne traite pas la première case du tableau
     
    		}
     
    		if (nbr_file == 0) {
    			puts("le dossier est vide");
    			break;
    		}
    		if ((strstr(file_array[cmp], ".exe") != NULL) && begin != 1) { //si le fichier contient l'extension suivante
    			puts("fichier trouve !!!");
    			fprintf(result_file,"%s\n", file_array[cmp]); //écrit le résultat dans le fichier
    		}
    		if (begin != 1) {cmp++;} else {begin = 0;} 
     
    	}
     
    	if (strcmp(actual_path, path) == 0) {
    		puts("Fin de la recherche");
    		fclose(result_file);
    		free(exclude_array);
    		break;
    	}
     
    	printf("fin du chemin, ajout de \"%s\" a la base d'exclusion \n", actual_path);
     
     
    	dir_db(actual_path, exclude_array, 1, &global_cmp);
    	printf("allocation du tableau de %d cases", global_cmp+2);
    	exclude_array = (char**)realloc(exclude_array,sizeof(char*)*(global_cmp+2)); //réalloue le tableau pour augmenter sa place de une case
     
    	if (exclude_array == NULL) {puts("erreur !"); exit(1);}
     
    	nbr_file = get_dir(path, file_array); //revient au path premier
    	strcpy(actual_path, path);
    	cmp = 0;
    	begin = 1;
    	}
    	return 0;
    }
     
     
    int get_dir(char path[], char file_array[][MAX_FILE_NAME]) {
    	struct dirent *actual_folder;
    	DIR *pFolder;
    	pFolder = opendir(path);
    	int compteur = 0;
    	if (pFolder == NULL) {
    		perror("opendir() error");
    	}
    	readdir(pFolder); //SKIP . AND ..
    	readdir(pFolder);
     
    	while ((actual_folder = readdir(pFolder)) != NULL) {
    		file_array[compteur][0] = '\0'; //remet l'array à "zero"
    		char *tmp = actual_folder->d_name;
    		strcat(file_array[compteur], path);
    		strcat(file_array[compteur], "/");
    		strcat(file_array[compteur], tmp);
    		compteur++;
    	}
    	closedir(pFolder);
    	return compteur; //renvoie le nombre d'élément du tableau
    }
     
     
    int is_dir(char *name) {
        DIR *file = opendir(name);
     
    	if (file == NULL) {
    		closedir(file);
    		return 0; //ce n'est pas un répertoire
    	} else {
    		closedir(file);
    		return 1; //c'est un répertoire
    	}
    }
     
    int dir_db(char *path, char **exclude_array, int mode, int *global_cmp) {
    	if (mode) {
    		int tmp = *global_cmp;
     
    		exclude_array[tmp] = (char*)malloc(sizeof(char)*strlen(path)); //alloue assez de ressource pour le path dans la case du tableau
    		strcpy(exclude_array[tmp], path); //copier le path envoyé dans le tableau
     
    		(*global_cmp)++;
     
    	} else if (!mode) {
    		int tmp = *global_cmp;
    		if (tmp == 0) { 
    			puts("tableau vide en lecture");
    			return 0;
    		}
    		int i;
    		for (i=0; i<tmp; i++) { //parcours le tableau et compare chaques occurences avec le path envoyé
    			if (strcmp(exclude_array[i], path) == 0) { //si le path envoyé est identique au texte stocké dans le tableau
    				return 1; //le path est présent 
    			}
    		} 
    		return 0; //le path n'est pas présent
    	}
    }


    Si vous avez pris la peine de lire mon code merci d'avance !

  2. #2
    Responsable Systèmes

    Moi j’utiliserais simplement readdir() sur le dossier analysé dans une fonction récursive en analysant chaque entrée avec stat() pour détecter dans la liste des entrées celles qui sont des dossiers.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutor...s/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  3. #3
    Candidat au Club
    Merci de ta réponse. Je pourrais essayer ta proposition (ou l'implémenter dans mon programme plus tard) mais ce que j'aimerais surtout pour le moment est de savoir comment faire une liste de chaines (string) que l'on peut augmenter/réallouer à souhait. C'est la seule chose qui empèche mon programme de marcher j'ai l'impression (la variable concerné est exclude_array).

  4. #4
    Expert éminent
    Je n'ai pas eu le temps de compiler et tester ton code, mais ton code est bizarre

    Dans la fonction dir_db
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    if (mode) {
    } else if (!mode) {
    }

    L'opérateur non logique est binaire : vrai ou faux. Donc le sinon si ne sert à rien.

    Dans la fonction is_dir
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if (file == NULL) {
        closedir(file);
    } else {
        closedir(file);
    }

    Un copié collé parce que je pense qu'appeler la fonction closedir avec NULL peut soit avoir aucun effet soit planté (lire la documentation)

    Dans la fonction dir_db, le paramètre int mode doit être 1 enum
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef enum e_db_mode {
        db_mode_insert = 0,
        db_mode_search
    } t_db_mode;


    Sinon, je trouve ton code ultra bizarre C'est la variable global_cmp qui contient le nombre de chemins dossier dans la base de données.
    À chaque tour de boucle, d'abord la fonction dir_db l'incrémente, et ensuite on fait 1 réalloc ayant comme taille global_cmp + 2
    Ce n'est pas plus simple de faire 1 tableau dynamique qu'on alloue X chemins par X chemins ... ou 1 liste chaînée

  5. #5
    Candidat au Club
    Citation Envoyé par foetus Voir le message

    L'opérateur non logique est binaire : vrai ou faux. Donc le sinon si ne sert à rien.
    effectivement c'est corrigé


    Citation Envoyé par foetus Voir le message

    Un copié collé parce que je pense qu'appeler la fonction closedir avec NULL peut soit avoir aucun effet soit planté (lire la documentation)
    Encore une erreur de ma part (j'ai mal lu la doc )

    Citation Envoyé par foetus Voir le message

    Dans la fonction dir_db, le paramètre int mode doit être 1 enum
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef enum e_db_mode {
        db_mode_insert = 0,
        db_mode_search
    } t_db_mode;

    D'accord

    Citation Envoyé par foetus Voir le message

    Sinon, je trouve ton code ultra bizarre C'est la variable global_cmp qui contient le nombre de chemins dossier dans la base de données.
    À chaque tour de boucle, d'abord la fonction dir_db l'incrémente, et ensuite on fait 1 réalloc ayant comme taille global_cmp + 2
    Oui je débute donc je sais pas trop comment stocker un grand nombre d'informations

    Citation Envoyé par foetus Voir le message

    Ce n'est pas plus simple de faire 1 tableau dynamique qu'on alloue X chemins par X chemins ... ou 1 liste chaînée
    J'ai pas très bien compris ton histoire du tableau dynamique et pour la liste chaînée il faudrais que je regarde (je ne sais pas faire).

    En tout cas merci de ta réponse c'est complet ça fait plaisir

  6. #6
    Expert éminent sénior
    Bonjour
    Citation Envoyé par mauvaisetasse Voir le message
    mais ce que j'aimerais surtout pour le moment est de savoir comment faire une liste de chaines (string) que l'on peut augmenter/réallouer à souhait.
    Voici un algo généraliste permettant de stocker n "trucs" qui arrivent au fur et à mesure et que tu traites un à un

    Code c :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
    #define SZ_ALLOC	(10)		// Taille des blocs d'allocation
    typedef struct {
    	truc* tab;			// Tableau de trucs
    	size_t nb;			// Nombre de trucs présents
    	size_t alloc;			// Taille allouée (sera toujours >= nb)
    } t_xxx;				// Je sais pas quel nom donner à ce type, tu lui donneras un nom de ton choix
     
    t_xxx area;				// Zone de stockage
    memset(area, 0, sizeof(area));		// Il faut impérativement tout mettre à 0
     
    // Boucle de traitement et stockage des datas qui entrent une à une
    while ((data=fonction_qui_fait_entrer_une_data()) != marqueur_fin_input) {		// Exemple while (fgets(...) != NULL)
    	// Vérification mémoire pleine (ce qui arrivera fatalement à la première itération quand nb et alloc sont à 0)
    	if (area.nb >= area.alloc) {
    		// Agrandissement
    		area.alloc+=SZ_ALLOC;
     
    		// Réallocation (et si la zone à réallouer est nulle, alors realloc se comporte comme malloc)
    		truc *tmp=realloc(area.tab, area.alloc, sizeof(*area.tab));
     
    		// Erreur d'allocation
    		if (tmp == NULL) {
    			// Là il faut gérer le souci, généralement il n'y a rien à faire, il faut nettoyer et quitter
    			free(area.tab);
    			return -1;
    		}
     
    		// Allocation ok - On la récupère
    		area.tab=tmp;
    	}
     
    	// Ici quoi qu'il arrive, on a la place de stocker la data
    	area.tab[area.nb]=data;
     
    	// On a une data de plus
    	area.nb++,
    }
     
    // Ici, on a area.nb qui contient le nb exact de datas stockées, et area.tab[x] qui contient chaque data (x < nb)
    // Ne pas oublier free(area.tab) à la fin


    Voila. Ensuite tu peux jouer avec SZ_ALLOC selon que tu as une machine puissante ou faible (plus la taille est grande moins il y aura d'opérations d'allocations mais plus tu perdras de la place). Puis ne reste plus qu'à appliquer aux strings.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

###raw>template_hook.ano_emploi###