2014-05-03 59 views
0

J下面有一個代碼顯示給定目錄中的目錄或文件的名稱(這是char []/string)。我想把這個名字動態地放到數組中。在打印表格1中顯示迭代的正確值(目錄或文件的名稱)。但在其他打印表格3中顯示不正確的值。有人可以幫我嗎?這是內存還是其他問題?如何將動態字符串放入數組中使用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

請充分提供可重現的例子,包括可編譯的代碼和一組顯示問題的文件名。 – merlin2011

回答

0

通過readdir()點返回到靜態分配的結構,所以你不應該做後續調用後保留對它的引用指針,因爲每一次你再打電話readdir()它只會被覆蓋。

你會想改變:

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

喜歡的東西:

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

做什麼它指向一個副本,而不是隻是想保留指針。當你完成它時,不要忘記撥打free(),因爲strdup()malloc()是你的記憶。

另一種方法是使用readdir_r(),它使用調用者分配的結構,但由於您只想存儲名稱,因此您可能不需要這樣做。

與往常一樣,沒有從malloc()在C.把返回

strlen(strArray)是錯誤的,因爲strArray不是字符串,並strlen()僅適用於字符串。您已經保留了一個count變量來跟蹤它的長度,所以請使用它。這整個塊:

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]); 

是一個循環的明顯的候選人,並且可以被替換爲:

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

或:

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

,因爲你的最後一個元素設置爲NULL

這裏的一個固定的版本:

#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; 
} 

和輸出:

[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

什麼可以獲得由函數do_ls返回的數組的大小?當我調用char ** strArray =(char **)do_ls(「C:/ PAP」); – user3245771

+0

您可以遍歷它並計數,直到找到NULL。這正是'free_ls_array()'所做的,除非它實際上不算。 –

1

下面是如何成長動態分配的數組的替代方法:

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

感謝evrybody的幫助。 – user3245771

相關問題