In C how to search all the file names in a directory and save them in an array of character strings?

2

Create a code to search all the names of the files in a directory, this code is recursive in case I find other directories in which I am reviewing them. The path inside the directory and file search works well for me, since I have tried them by printing what I read on the screen and finding everything and not repeating any file name. The problem I have is that it saves the names I find in a string array of characters, so when I find all the files I will have the array of strings in the main with all the names of the files. The problem is that in the end when you print that arrangement on the screen, not all the files are there but a few repeated files. The final goal of this program is not to print all the file names on the screen, but to save all the names of the files in the array. If you can help me, it has been days without finding the reason.

    void findfiles(char *root,char *p[],int *tam){
        DIR * dir;
        struct dirent *entrada;
        struct stat stt;
        dir = opendir(root);
        char *aux;
        char nombre[BUFFER_TAM];
        char buf[30];
        if (dir == NULL) {
                printf("hola4\n");
                return;
         }
     while ((entrada = readdir(dir)) != NULL) {
                if (strcmp(entrada->d_name,".")==0 || strcmp(entrada->d_name,"..")==0);
                else {
                    if (entrada->d_type == DT_DIR){
                        strcpy(nombre,root);
                        strcat(nombre,"/");
                        strcat(nombre,entrada->d_name);
                        findfiles(nombre,p,tam);
                    }
                    else {
                        strcpy(nombre,root);
                        strcat(nombre,"/");
                        strcat(nombre,entrada->d_name);
                        p[*tam]=malloc(strlen(nombre)+1);
                        p[*tam]=nombre;
                        *tam = *tam +1;
                    }
                }

            }


}


    void main(){
    char *archivos[BUFFER_TAM];
    char root[BUFFER_TAM]="/home/jesusmolina/Documentos";
    int i=0,tam=0;
    findfiles(root,archivos,&tam);
    for (i;i<tam;i++)
       printf("%s\n",archivos[i]);
}
    
asked by Jesus Molina Garcia 19.06.2016 в 21:32
source

1 answer

1

You should simplify your code and avoid, as far as possible, duplicities.

This:

if (strcmp(entrada->d_name,".")==0 || strcmp(entrada->d_name,"..")==0);
else {
  if (entrada->d_type == DT_DIR){
    strcpy(nombre,root);
    strcat(nombre,"/");
    strcat(nombre,entrada->d_name);
    findfiles(nombre,p,tam);
  }
  else {
    strcpy(nombre,root);
    strcat(nombre,"/");
    strcat(nombre,entrada->d_name);
    p[*tam]=malloc(strlen(nombre)+1);
    p[*tam]=nombre;
    *tam = *tam +1;
  }
}

It's equivalent to this:

if ( strcmp(entrada->d_name,".") && strcmp(entrada->d_name,"..") )
{
  strcpy(nombre,root);
  strcat(nombre,"/");
  strcat(nombre,entrada->d_name);

  if (entrada->d_type == DT_DIR)
    findfiles(nombre,p,tam);
  else
  {
    p[*tam]=malloc(strlen(nombre)+1);
    p[*tam]=nombre;
    *tam++;
  }
}

Also, you have to be careful when copying strings. In the following lines:

    p[*tam]=malloc(strlen(nombre)+1);
    p[*tam]=nombre;

You are making a memory reservation and then modify that pointer for another one, with which you lose the initial reservation and your program ends with memory leaks. Another collateral effect of this situation is that several elements of p will end up pointing to the same site, then having repeated entries will be inevitable. Also, freeing the associated memory will be problematic because the same memory pool can not be released twice:

char* ptr = malloc(100);
free(ptr); // OK
free(ptr); // ERROR

There you must use strcpy , as you have done previously:

strcpy(p[*tam],nombre);

Another problem that your code has is the following:

void findfiles(char *root,char *p[],int *tam)

In the previous function, what is the size assigned to the p ?

I ask because you do not do any checking to ensure that your limits are not exceeded.

What you should do, in my opinion, is that p is resized according to the needs, that is, according to the amount of files that are found. You can achieve this in two different ways:

1. Resizing the fix every time you need

In this case, before adding a file to the list, it checks if the array is full, in which case it is resized to provide it with more capacity.

This solution is the easiest to implement, but also the most expensive since calling realloc means copying the contents of the old array into the new one.

Note that to apply this solution you need a new variable that indicates the total capacity of the array.

if ( tam == max_size )
{
  char** p_temp = (char**)realloc(p,(max_size+100)*sizeof(char*));
  if( p_temp )
    p = p_temp;
  else
    // ERROR AL REASIGNAR LA MEMORIA
}
// Se añaden nuevos ficheros a la lista

2. Use a simple linked list to store the results and then dump everything into the array

This solution has the advantage that p will only occupy the size you need, neither more nor less. Its main disadvantage is to implement a simple linked list to store the results.

In this case I do not put code because the linked list could be programmed from scratch or use a third-party library and the solution to be applied in each case could vary.

Greetings.

    
answered by 20.06.2016 в 09:02