You can use realloc
:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
extern char *strdup(const char *src);
int scandir(char ***list, char dirname[], char const *ext)
/* Scans a directory and retrieves all files of given extension */
{
DIR *d = NULL;
struct dirent *dir = NULL;
size_t n = 0;
d = opendir(dirname);
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if (has_extension(dir->d_name, ext))
{
*list = realloc(*list, sizeof(**list) * (n + 1));
(*list)[n++] = strdup(dir->d_name);
}
}
closedir(d);
}
return n;
}
int main(void)
{
char **list = NULL;
size_t i, n = scandir(&list, "/your/path", "jpg");
for (i = 0; i < n; i++) {
printf("%s\n", list[i]);
free(list[i]);
}
free(list);
return 0;
}
Note that strdup()
is not a standard function but its available on many implementations.
As an alternative to realloc
you can use a singly linked list of strings.
EDIT: As pointed out by @2501, is better to return an allocated array of strings from scandir
and pass elems
as param:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
extern char *strdup(const char *src);
char **scandir(char dirname[], char const *ext, size_t *elems)
/* Scans a directory and retrieves all files of given extension */
{
DIR *d = NULL;
struct dirent *dir = NULL;
char **list = NULL;
d = opendir(dirname);
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if (has_extension(dir->d_name, ext))
{
list = realloc(list, sizeof(*list) * (*elems + 1));
list[(*elems)++] = strdup(dir->d_name);
}
}
closedir(d);
}
return list;
}
int main(void)
{
size_t i, n = 0;
char **list = scandir("/your/path", "jpg", &n);
for (i = 0; i < n; i++) {
printf("%s\n", list[i]);
free(list[i]);
}
free(list);
return 0;
}
Finally, do you really need an array? Consider using a call-back function:
#include <stdio.h>
#include <string.h>
#include <dirent.h>
void cb_scandir(const char *src)
{
/* do whatever you want with the passed dir */
printf("%s\n", src);
}
int scandir(char dirname[], char const *ext, void (*callback)(const char *))
/* Scans a directory and retrieves all files of given extension */
{
DIR *d = NULL;
struct dirent *dir = NULL;
size_t n = 0;
d = opendir(dirname);
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if (has_extension(dir->d_name, ext))
{
callback(dir->d_name);
n++;
}
}
closedir(d);
}
return n;
}
int main(void)
{
scandir("/your/path", "jpg", cb_scandir);
return 0;
}