Указатель, возвращаемый readdir()
указывает на статически размещенную структуру, так что вы не должны сохранять ссылки на него после выполнения последующих вызовов, так как каждый раз, когда вы звоните readdir()
снова это будет просто получить перезаписаны ,
Вы хотите изменить:
strArray[count] = (char*)direntp->d_name;
к чему-то вроде:
strArray[count] = strdup(direntp->d_name);
сделать копию того, что он указывает на, а не просто пытается сохранить указатель. Не забудьте позвонить free()
, когда вы закончите с этим, так как strdup()
malloc()
s память для вас.
Альтернативой является использование readdir_r()
, который использует структуру, выделенную вызывающим, но для того, что вы делаете это, вероятно, не нужно, поскольку вы просто хотите сохранить имя.
Как всегда, не отбрасывают возвращения из malloc()
в С.
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$
Просьба представить полностью воспроизводимый пример, включая скомпилируемый код и минимальный набор имен файлов, который показывает проблему. – merlin2011