Its an extension of my previous question: How can I get only txt files from directory in c? . Now I want to save those filenames (I dont really know how many of them are in the dir) to char **
array. I figured out a solution (kind of) but then I realized that I need not a char*
but char **
(I know, stupid me :])
Anyway, I got segmentation fault [core dumped] with this code:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdbool.h>
char* allocMemory(int n)
{
char *tab = (char *) malloc(n*sizeof(char));
return tab;
}
void freeMemory(char **tab, int n, int m)
{
int i=0;
for(i=0; i<m; i++)
free(tab[i]);
free(tab);
tab = NULL;
}
bool hasTxtExtension(char const *filename)
{
size_t len = strlen(filename);
return len > 4 && strcmp(filename + len - 4, ".txt") == 0;
}
char** getTxtFilenames(const char *dirname)
{
DIR *directory = NULL;
struct dirent *ent = NULL;
int fileCounter = 0;
char **txtFiles = allocMemory(1);
char **moreTxtFiles = allocMemory(1);
directory = opendir (dirname);
if(directory == NULL)
return NULL;
int i = 0;
while ((ent = readdir (directory)) != NULL)
{
if(hasTxtExtension(ent->d_name))
{
fileCounter ++;
moreTxtFiles = (char**) realloc (txtFiles, fileCounter * sizeof(char*));
if(moreTxtFiles[i] != NULL)
{
txtFiles = moreTxtFiles;
txtFiles[i] = allocMemory(strlen(ent->d_name));
txtFiles[i][fileCounter - 1] = ent->d_name;
}
else
{
freeMemory(txtFiles, 1, fileCounter);
return NULL;
}
}
i ++;
}
if(closedir(directory) < 0)
return NULL;
return txtFiles;
}
int main(int argc, char **argv)
{
char **txtFilenames = getTxtFilenames("dir");
if(txtFilenames == NULL)
return -1;
printf("%s\n", txtFilenames[0][1]);
return 0;
}
EDIT:
I also tried this: (notice that Im a little bit confused with those not-lovely char arrays in C, argh :/)
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdbool.h>
char* allocMemory(int n)
{
char *tab = (char *) malloc(n*sizeof(char));
return tab;
}
void freeMemory(char *tab)
{
free(tab);
tab = NULL;
}
bool hasTxtExtension(char const *filename)
{
size_t len = strlen(filename);
return len > 4 && strcmp(filename + len - 4, ".txt") == 0;
}
char* getTxtFilenames(const char *dirname)
{
DIR *directory = NULL;
struct dirent *ent = NULL;
int fileCounter = 0;
char *txtFiles = NULL;
char *moreTxtFiles = NULL;
directory = opendir (dirname);
if(directory == NULL)
return NULL;
while ((ent = readdir (directory)) != NULL)
{
if(hasTxtExtension(ent->d_name))
{
fileCounter ++;
moreTxtFiles = (char*) realloc (txtFiles, fileCounter * sizeof(char));
if(moreTxtFiles != NULL)
{
txtFiles = moreTxtFiles;
txtFiles[fileCounter - 1] = ent->d_name;
}
else
{
freeMemory(txtFiles);
return NULL;
}
}
}
if(closedir(directory) < 0)
return NULL;
return txtFiles;
}
int main(int argc, char **argv)
{
char **txtFilenames = getTxtFilenames("dir");
if(txtFilenames == NULL)
return -1;
printf("%s\n", txtFilenames[0]);
return 0;
}
txtFilenames[0][1]
is a character, not a string. txtFiles[i][fileCounter - 1]
is a character, but ent->d_name
is a string. I don't understand why you are using two index ( i
and fileCounter
). Just use an array of strings. You should also include <string.h>
.
The solution is simpler:
#include <direct.h>
#include <stdlib.h>
#include <string.h>
char **f(const char *s)
{
char **p = NULL;
DIR *dir;
struct dirent *ent;
size_t i = 0;
dir = opendir(s);
while ((ent = readdir(dir)) != NULL) {
if (hasTxtExtension(ent->d_name)) {
p = realloc(p, (i + 1) * sizeof(char *));
p[i] = malloc(strlen(ent->d_name) + 1);
strcpy(p[i], ent->d_name);
++i;
}
}
closedir(dir);
return p;
}
Here is a non-exhaustive list to improve this code:
realloc
fail, there is a memory leak. s
is a bad directory path. realloc
with each iteration). Aside from the questionable indexing Kirilenko pointed out, your first (and core) error is:
char **txtFiles = allocMemory(1);
char **moreTxtFiles = allocMemory(1);
Which seems innocent enough, but allocMemory is defined as:
char* allocMemory(int n)
{
char *tab = (char *) malloc(n*sizeof(char));
return tab;
}
Both txtFiles and moreTxtFiles are pointers to pointers ; not pointers to chars. You're returning a pointer to a single allocated char, then storing it in a pointer that expects it to be a pointer to a pointer .
For your case, don't use allocMemory for allocating list entries. Just use it for allocating your strings.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.