The pointer returned by readdir()
points to a statically allocated structure, so you should not retain references to it after making subsequent calls, since every time you call readdir()
again it'll just get overwritten.
You'll want to change:
strArray[count] = (char*)direntp->d_name;
to something like:
strArray[count] = strdup(direntp->d_name);
to make a copy of what it points to, rather than just trying to retain the pointer. Don't forget to call free()
when you're done with it, since strdup()
malloc()
s the memory for you.
An alternative is to use readdir_r()
which uses a caller-allocated structure, but for what you're doing this is likely not necessary, since you just want to store the name.
As always, don't cast the return from malloc()
in C.
strlen(strArray)
is wrong, since strArray
is not a string, and strlen()
only works for strings. You already maintain a count
variable to keep track of the length of it, so just use that. This whole block:
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]);
is an obvious candidate for a loop, and can be replaced by:
for ( int s = 0; s < count; ++s ) {
printf("\nTable3: %s \n", strArray[s]);
}
or:
int s = 0;
while ( strArray[s] ) {
printf("\nTable3: %s \n", strArray[s++]);
}
since you set the last element to NULL
.
Here's a fixed version:
#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;
}
and outputs:
paul@MacBook:~/Documents/src/scratch/dir_test$ ls
README ls1 ls1.c nothing.txt
paul@MacBook:~/Documents/src/scratch/dir_test$ ./ls1
Table1: ls1
Count: 1
Table1: README
Count: 2
Table3: ls1
Table3: README
Number of elements: 2
paul@MacBook:~/Documents/src/scratch/dir_test$