1

I have problem with my array of char*-

char *original_file_name_list[500];

while(dp=readdir(dir)) != NULL) {
   original_file_name = dp->d_name;
   original_file_name_list[counter] = original_file_name;
   printf("%s\n",original_file_name_list[0]);
   printf("%d\n",counter); 
   counter++;
}

The problem is, that it prints all files fine. It should print only first file, right? And if I try printf("%s\n",original_file_name_list[1]); It doesn't work , which means that it is writing only in 1st string. Any idea why?

edit: There is no syntax error due to compiler.

user3036674
  • 143
  • 2
  • 3
  • 7

2 Answers2

3

You're not copying the string at all - also your file_name_list array hasn't enough space for a list of filenames - just for a list of pointers. But dp->d_name is just a pointer to a char* - you can't know for how long the memory behind the pointer is valid. Because of that you have to make a copy for yourself.

#include <string.h>
#include <dirent.h>

int main(int argc, char** argv){
  char original_file_name_list[50][50];
  size_t counter = 0;
  while(dp=readdir(dir)) != NULL) // does work fine (ordinary reading files from dir)
  {
    size_t len = strlen(dp->d_name);
    if(len >= 50) len = 49;
    strncpy(original_file_name_list[counter], dp->d_name, len);
    original_file_name_list[counter][len] = '\0';
    printf("%d\n",counter); 
    counter++;
  }
  printf("%s\n",original_file_name_list[1]); // <- will work if you have at least 2 files in your directory
  return 0;
}
Constantin
  • 8,721
  • 13
  • 75
  • 126
  • why not to use strndup()? – Michael Nov 29 '13 at 13:09
  • @Michael Because it's evil. See also: http://stackoverflow.com/questions/12984948/why-is-strdup-considered-to-be-evil But you're free to post an answer with `strndup()` if you're feeling like it – Constantin Nov 29 '13 at 13:13
  • @unwind I think he's talking about `char *strndup(const char *s, size_t size);` (which he used in his answer), but the problems from `strdup()` also apply to `strndup()`. – Constantin Nov 29 '13 at 13:56
  • 1
    @Constantin It is unportable, and it may "hide" its allocaltion (although it is not uncommon for a function to return allocated memory), but I wouldn't call that "evil". – glglgl Nov 29 '13 at 14:29
0

I'm not sure about purpose of counter2 (I have replaced it with counter) but I can propose the following code with strdup() call to store the file names:

char *original_file_name_list[500] = {0}; // it is better to init it here

while(dp=readdir(dir)) != NULL) {
   original_file_name_list[counter] = strdup(dp->d_name); // strdup() is ok to use
                                                          // here, see the comments
   printf("%s\n%d\n",original_file_name_list[counter], counter);
   counter++;
}

/* some useful code */

/* don't forget to free the items of list (allocated by strdup(..) )*/
for (int i = 0; i < 500; ++i) {
   free(original_file_name_list[i]);
}
Michael
  • 1,505
  • 14
  • 26
  • the counter2 should be just counter...my mistake, sorry. I'll try it because the Constantin's version doesn't work. – user3036674 Nov 29 '13 at 13:19
  • 1
    "d_name in linux has a length of 256" - so why not use `sizeof dp->d_name` instead of `256`? – glglgl Nov 29 '13 at 13:37
  • @glglgl Oh, it's you again... And again with useful remarks. :-) Thanks. Fixed! – Michael Nov 29 '13 at 13:49
  • @Michael It's a bad habit of me :-) – glglgl Nov 29 '13 at 14:26
  • And why `strndup()` instead of `strdup()`? Cut off file names aren't very useful, are they? – alk Nov 29 '13 at 17:39
  • @alk If path contains more than 256 symbols than it will not suit into this d_name field. Moreover I'm not sure about zero in the end. Sure it must be there... But, who knows? So strndup() is a kind of reassurance here. – Michael Nov 29 '13 at 23:03
  • 1
    From the POSIX specs at http://pubs.opengroup.org/onlinepubs/9699919799/functions/readdir.html: "*...dirent with an array of char d_name members containing at least {NAME_MAX}+1 elements.*" From the Linux Man Page at http://man7.org/linux/man-pages/man3/readdir.2.html: "*... d_name is a null-terminated filename.*" So 1st: I's `0`-terminated and 2nd it's not `256` but `NAME_MAX`. – alk Nov 30 '13 at 08:43
  • @alk Thanks for clarification! I had seen linux man and saw that, but didn't checked out POSIX. According to [dirent.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/dirent.h.html): "_The array d_name is of unspecified size, but shall contain a filename of at most `{NAME_MAX}` bytes followed by a terminating null byte._". Thus, using `sizeof` is not correct here, because `d_name` is a type of `char d_name[];`. I should replace it with strlen and it must be ok. Or, as you mention above, just use strdup(). But latter variant will be simpler. – Michael Nov 30 '13 at 09:18