2014-05-03 2 views
0

J avez ci-dessous un code qui affiche le nom (c'est char []/chaîne) de répertoires ou de fichiers dans le répertoire donné. Je veux mettre ces noms dynamiquement au tableau. Dans print table1 affiche les valeurs (nom des répertoires ou des fichiers) qui sont itérées. Mais dans une autre table d'impression3 affiche des valeurs incorrectes. Quelqu'un pourrait-il m'aider avec ça? Est-ce un problème avec la mémoire ou autre chose?Comment mettre une chaîne dynamique dans un tableau en utilisant C

char** do_ls(char dirname[]){ 
DIR *dir_ptr; 
struct dirent *direntp; 
char **strArray; 
int count=0; 
strArray = (char**)malloc(1 * sizeof(char*)); 
strArray[0] = NULL; 

if ((dir_ptr = opendir(dirname)) == NULL) 
    fprintf(stderr,"ls1: cannot open %s\n", dirname); 
else { 
    while ((direntp = readdir(dir_ptr)) != NULL) { 
     if(strchr(direntp->d_name, '.') == NULL) { 

      strArray[count] = (char*)direntp->d_name; 
      printf("\nTable1: %s \n", strArray[count]); 
      count++; 
      strArray = (char **)realloc(strArray, sizeof(char *) * (count + 1)); 
      printf("\nCount: %d \n", count); 

     } 
    } 
    strArray[count] = NULL; /* Terminate the array */ 
printf("\nTable3: %s \n", strArray[0]); 
printf("\nTable3: %s \n", strArray[1]); 
printf("\nTable3: %s \n", strArray[2]); 
printf("\nTable4: %s \n", strArray[strlen(strArray)-1]); 
printf("\nIndex: %d \n", strlen(strArray)-1); 

    closedir(dir_ptr); 
} 



return strArray; 

}

+0

S'il vous plaît fournir une complète exemple reproductible, y compris le code compilable et un ensemble minimal de noms de fichiers qui montre le problème. – merlin2011

Répondre

0

Le pointeur retourné par readdir() points attribués une structure statique, de sorte que vous ne devriez pas conserver des références à ce après avoir fait des appels ultérieurs, puisque chaque fois que vous appelez readdir() à nouveau, il va juste être écrasé .

Vous voulez changer:

strArray[count] = (char*)direntp->d_name; 

à quelque chose comme:

strArray[count] = strdup(direntp->d_name); 

pour faire une copie de ce qu'il fait, plutôt que d'essayer de conserver le pointeur. N'oubliez pas d'appeler free() lorsque vous avez terminé, car strdup()malloc() s la mémoire pour vous.

Une alternative est d'utiliser readdir_r() qui utilise une structure allouée par l'appelant, mais pour ce que vous faites, ce n'est probablement pas nécessaire, puisque vous voulez juste stocker le nom.

Comme toujours, ne la chassez le retour de malloc() en C.

strlen(strArray) est faux, puisque strArray n'est pas une chaîne, et strlen() ne fonctionne que pour les chaînes. Vous avez déjà une variable count pour garder une trace de sa longueur, donc utilisez-la. Ce bloc entier:

printf("\nTable3: %s \n", strArray[0]); 
printf("\nTable3: %s \n", strArray[1]); 
printf("\nTable3: %s \n", strArray[2]); 
printf("\nTable4: %s \n", strArray[strlen(strArray)-1]); 

est un candidat évident pour une boucle, et peut être remplacé par:

for (int s = 0; s < count; ++s) { 
    printf("\nTable3: %s \n", strArray[s]); 
} 

ou:

int s = 0; 
while (strArray[s]) { 
    printf("\nTable3: %s \n", strArray[s++]);  
} 

puisque vous définissez le dernier élément à NULL.

est ici une version fixe:

#define _POSIX_C_SOURCE 200809L 

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <dirent.h> 

char ** do_ls(const char * const dirname) { 
    DIR * dir_ptr; 
    struct dirent * direntp; 
    char ** strArray; 
    size_t count = 0; 

    if ((strArray = malloc(sizeof(*strArray))) == NULL) { 
     fprintf(stderr, "ls1: couldn't allocate memory"); 
     exit(EXIT_FAILURE); 
    } 
    strArray[0] = NULL; 

    if ((dir_ptr = opendir(dirname)) == NULL) { 
     fprintf(stderr, "ls1: cannot open %s\n", dirname); 
     exit(EXIT_FAILURE); 
    } 
    else { 
     while ((direntp = readdir(dir_ptr)) != NULL) { 
      if (strchr(direntp->d_name, '.') == NULL) { 
       strArray[count] = strdup(direntp->d_name); 
       if (strArray[count] == NULL) { 
        fprintf(stderr, "ls1: couldn't allocate memory"); 
        exit(EXIT_FAILURE); 
       } 

       printf("Table1: %s\n", strArray[count++]); 
       printf("Count: %zu\n\n", count); 

       strArray = realloc(strArray, sizeof(*strArray) * (count + 1)); 
       if (strArray == NULL) { 
        fprintf(stderr, "ls1: couldn't reallocate memory"); 
        exit(EXIT_FAILURE); 
       } 

       strArray[count] = NULL; 
      } 
     } 

     for (size_t s = 0; s < count; ++s) { 
      printf("Table3: %s\n", strArray[s]); 
     } 
     printf("Number of elements: %zu\n\n", count); 

     closedir(dir_ptr); 
    } 

    return strArray; 
} 

void free_ls_array(char ** strArray) { 
    size_t s = 0; 
    while (strArray[s]) { 
     free(strArray[s++]); 
    } 
    free(strArray); 
} 

int main(void) { 
    char ** strArray = do_ls("./"); 
    free_ls_array(strArray); 
    return 0; 
} 

et sorties:

[email protected]:~/Documents/src/scratch/dir_test$ ls 
README  ls1   ls1.c  nothing.txt 
[email protected]:~/Documents/src/scratch/dir_test$ ./ls1 
Table1: ls1 
Count: 1 

Table1: README 
Count: 2 

Table3: ls1 
Table3: README 
Number of elements: 2 

[email protected]:~/Documents/src/scratch/dir_test$ 
+0

Que puis-je obtenir la taille de tableau qui sont retournés par la fonction do_ls? Quand j'appelle char ** strArray = (char **) do_ls ("C:/PAP"); – user3245771

+0

Vous pouvez passer en boucle et compter jusqu'à ce que vous trouviez 'NULL'. C'est exactement ce que fait 'free_ls_array()', sauf qu'il ne compte pas réellement. –

1

Voici une autre méthode pour la façon de cultiver un tableau alloué dynamiquement:

char **do_ls(
     const char *dirname 
    ) 
    { 
    DIR *dir_ptr = NULL;  /* A handle to iterate the specified directory. */ 
    int tmp;     /* Used to iterate the array when printing it out. */ 

    char **strArray = NULL; /* Array of string pointers for directory names. */ 
    int count=0;    /* Number of elements in the array */ 


    /* Open the specified directory. */ 
    dir_ptr = opendir(dirname); 
    if(NULL == dir_ptr) 
     { 
     fprintf(stderr,"ls1: cannot open %s\n", dirname); 
     goto CLEANUP; 
     } 

    /* Scan directory entries. */ 
    while((direntp = readdir(dir_ptr))) 
     { 
     struct dirent *direntp; /* Pointer to a directory entry. */ 
     char **tmp;    /* Used to safely grow the array. */ 

     /* Ignore current & parent directories, and all files with an extension. */ 
     if(strchr(direntp->d_name, '.')) 
     continue; 

     /* Increase the size of the array. */ 
    tmp=realloc(strArray, count+1 * sizeof(*strArray)); 
    if(NULL == tmp) 
     { 
     fprintf(stderr, "realloc() failed.\n"); 
     goto CLEANUP; 
     } 
     strArray = tmp; 

     /* Store directory entry name into new array slot. */ 
     strArray[count] = strdup(direntp->d_name); 
     count++; 
     } 

    /* Print array entries. */ 
    for(tmp=0; tmp < count; ++tmp) 
     printf("Slot #%d: %s\n", tmp, strArray[tmp]); 

    /* Add a last "termination" entry to the array. */ 
    tmp=realloc(strArray, count+1 * sizeof(*strArray)); 
    if(NULL == tmp) 
     { 
     fprintf(stderr, "realloc() failed.\n"); 
     goto CLEANUP; 
     } 
    strArray = tmp; 
    strArray[count] = NULL; 

CLEANUP: 

    if(dir_ptr) 
     closedir(dir_ptr); 

    return(strArray); 
    } 
+0

Merci à tous pour votre aide. – user3245771

Questions connexes