Thread: Saving chars to array

  1. #1
    Registered User
    Join Date
    Mar 2006
    Posts
    24

    Saving chars to array

    I'm trying to save filenames into an array of chars.
    My code seems incorrect, but can't figure out what's wrong :\

    Code:
    char** get_categories(void)
    {
          DIR* dp;
          struct dirent* ds;
          char** cat;
          int i=1;
          
          dp = opendir("rubrieken/");
          ds = readdir(dp);
          
          while(ds!=NULL)
          {
               if ( (strcmp(ds->d_name, ".") > 0) && (strcmp(ds->d_name, "..") > 0))
               {
                    realloc(cat, (i++)*sizeof(char)*strlen(ds->d_name));
                    cat[i-1] = malloc(sizeof(char)*strlen(ds->d_name);
                    strcpy(cat[i-1], ds->d_name);
               }
               ds = readdir(dp);
          }  
          return cat;
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > if ( (strcmp(ds->d_name, ".") > 0) && (strcmp(ds->d_name, "..") > 0)
    Try != 0

    > realloc(cat, (i++)*sizeof(char)*strlen(ds->d_name));
    1. cat is uninitialised on the first call - char**cat = NULL
    2. you don't assign the result to any variable
    t = realloc( cat, (i++)*sizeof(char*) );
    if ( t != NULL ) cat = t;
    3. the sizeof should be sizeof(char*)
    4. you don't need the strlen() of a pointer in order to allocate just a pointer.

    > cat[i-1] = malloc(sizeof(char)*strlen(ds->d_name);
    You forgot to allocate space for the \0 as well.
    cat[i-1] = malloc(sizeof(char)*(strlen(ds->d_name)+1) ) ;
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Mar 2006
    Posts
    24
    Thnx for helping me out !

    2. you don't assign the result to any variable
    t = realloc( cat, (i++)*sizeof(char*) );
    if ( t != NULL ) cat = t;
    realloc returns void, so I guess there's no use to assign it to a variable ?

    I guess the error has something to do with the realloc. Can't debug, Dev-C++ refuses

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > realloc returns void
    Look again.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Mar 2006
    Posts
    24
    This is what I have now:
    Code:
    char** get_categories(void)
    {
          DIR* dp = NULL;
          struct dirent* ds;
          char** cat = NULL;
          int i=1;
          
          dp = opendir("rubrieken/");
          ds = readdir(dp);
          
          while(ds!=NULL)
          {
               if ( (strcmp(ds->d_name, ".") > 0) && (strcmp(ds->d_name, "..") > 0))
               {
                    cat = realloc(cat, (i++)*sizeof(ds->d_name));
                    cat[i-1] = malloc(sizeof(char*)*(strlen(ds->d_name)+1) );
                    strcpy(cat[i-1], ds->d_name);
               }
               ds = readdir(dp);
          }  
          return cat;
    }
    It returns some wheird characters.

    EDIT: printf("%d", sizeof(cat[i-1])); returns 4. Is that normal ?
    Last edited by ReggieBE; 03-24-2006 at 11:18 AM.

  6. #6
    Registered User
    Join Date
    Mar 2006
    Posts
    24
    Ok got it. Forgot to malloc cat the first time.

    Working code:

    Code:
    char** get_categories(void)
    {
          DIR* dp = NULL;
          struct dirent* ds;
          char** cat = NULL;
          char tmp[1024];
          int i=1;
          
          dp = opendir("rubrieken/");
          ds = readdir(dp);
          
          while(ds!=NULL)
          {
               if ( (strcmp(ds->d_name, ".") > 0) && (strcmp(ds->d_name, "..") > 0))
               {
                    strcpy(tmp, ds->d_name);
                    if (!cat)
                       cat = malloc(sizeof(char*)*strlen(tmp));
                    else
                       cat = realloc(cat, (i++)*strlen(tmp)); 
                    cat[i-1] = malloc(sizeof(char*)*(strlen(tmp)+1) );
                    strcpy(cat[i-1], ds->d_name);
               }
               ds = readdir(dp);
          }  
          return cat;
    }
    This helped me too: http://www.codecomments.com/archive2...-6-223662.html

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You didn't listen to much did you?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User OnionKnight's Avatar
    Join Date
    Jan 2005
    Posts
    555
    realloc() behaves like malloc() if the pointer is NULL so you don't have to do all that extra checking.

  9. #9
    Registered User
    Join Date
    Mar 2006
    Posts
    24
    @Salem: I did, but it didn't work when I just set cat = NULL .. when I malloced it it worked. Why is that ?

    EDIT: Oooooh ok, I did cat** = NULL. But I have to stel cat* to NULL also, right ?
    Last edited by ReggieBE; 03-24-2006 at 12:22 PM.

  10. #10
    Registered User
    Join Date
    Mar 2006
    Posts
    24
    2. you don't assign the result to any variable
    t = realloc( cat, (i++)*sizeof(char*) );
    if ( t != NULL ) cat = t;
    What's t ? char** ?

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    t is a temporary pointer, which you check before assigning to cat
    This is because realloc can return NULL, so assigning directly to the pointer risks a memory leak.

    Two versions -
    Code:
    char** get_categories(void)
    {
      DIR* dp = NULL;
      struct dirent* ds;
      char** cat = NULL;
      int i=1;
    
      dp = opendir("rubrieken/");
      while( (ds = readdir(dp)) != NULL )
      {
        if ( (strcmp(ds->d_name, ".") != 0) && (strcmp(ds->d_name, "..") != 0))
        {
          void *t = realloc( cat, (i++)*sizeof(char*) );
          if ( t != NULL ) {
            cat = t;
            cat[i-1] = malloc( sizeof(char)*(strlen(ds->d_name)+1) );
            if ( cat[i-1] != NULL ) {
              strcpy(cat[i-1], ds->d_name);
            }
          }
        }
      }
      closedir( dp );
      return cat;
    }
    
    char** get_categories(void)
    {
      DIR* dp = NULL;
      struct dirent* ds;
      char** cat = NULL;
      int i=0;
    
      dp = opendir("rubrieken/");
      while( (ds = readdir(dp)) != NULL )
      {
        if ( (strcmp(ds->d_name, ".") != 0) && (strcmp(ds->d_name, "..") != 0))
        {
          void *t = realloc( cat, (i+1) * sizeof(cat[0]) );
          if ( t != NULL ) {
            cat = t;
            cat[i] = malloc( sizeof(cat[i][0])*(strlen(ds->d_name)+1) );
            if ( cat[i] != NULL ) {
              strcpy( cat[i], ds->d_name);
              i++;
            }
          }
        }
      }
      closedir( dp );
      return cat;
    }
    The second one avoids sizeof on types, but instead goes for sizeof on objects.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Registered User
    Join Date
    Mar 2006
    Posts
    24
    Code:
    Oh ok thnx !
    Just one question .. I get the categories listed, but some junk comes along with it like "Categoryfile=c:\java\.."
    
    I checked ds->d_name. That's not it. Then I declared tmp with = { '\0' } .. Still no change.

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Maybe because you have no effective way of telling where the end of the list is, so when you print it, you just dereference junk pointers?

    Or maybe that you've introduced yet another fault into the code - but since you didn't post your latest effort we can't tell.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dirent.h>
    
    char** get_categories(int *howmany)
    {
      DIR* dp = NULL;
      struct dirent* ds;
      char** cat = NULL;
      int i=0;
    
      dp = opendir("/boot");
      while( (ds = readdir(dp)) != NULL )
      {
        if ( (strcmp(ds->d_name, ".") != 0) && (strcmp(ds->d_name, "..") != 0))
        {
          void *t = realloc( cat, (i+1) * sizeof(cat[0]) );
          if ( t != NULL ) {
            cat = t;
            cat[i] = malloc( sizeof(cat[i][0])*(strlen(ds->d_name)+1) );
            if ( cat[i] != NULL ) {
              strcpy( cat[i], ds->d_name);
              i++;
            }
          }
        }
      }
      closedir( dp );
      *howmany = i;
      return cat;
    }
    
    int main ( ) {
      int n;
      char **p = get_categories(&n);
      int i;
      for ( i = 0 ; i < n ; i++ ) {
        printf("%s\n", p[i] );
      }
      return 0;
    }
    
    // My output
    $ ls -1 /boot
    config-2.6.11-1.1369_FC4
    grub
    initrd-2.6.11-1.1369_FC4.img
    lost+found
    memtest86+-1.55.1
    System.map-2.6.11-1.1369_FC4
    vmlinuz-2.6.11-1.1369_FC4
    xen.gz
    xen-syms
    $ ./a.out
    xen-syms
    vmlinuz-2.6.11-1.1369_FC4
    config-2.6.11-1.1369_FC4
    grub
    lost+found
    initrd-2.6.11-1.1369_FC4.img
    memtest86+-1.55.1
    System.map-2.6.11-1.1369_FC4
    xen.gz
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  14. #14
    Registered User
    Join Date
    Mar 2006
    Posts
    24
    Kay found it. Forgot to add \0 to the last address in substr()

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting a 2 byte number from an array of char's
    By kzar in forum C Programming
    Replies: 20
    Last Post: 04-10-2005, 10:18 PM
  2. Code: An auto expanding array (or how to use gets() safely).
    By anonytmouse in forum Windows Programming
    Replies: 0
    Last Post: 08-10-2004, 12:13 AM
  3. Type and nontype parameters w/overloading
    By Mr_LJ in forum C++ Programming
    Replies: 3
    Last Post: 01-02-2004, 01:01 AM
  4. Array of pointers (chars)
    By Vber in forum C Programming
    Replies: 5
    Last Post: 02-08-2003, 04:29 AM
  5. Saving array of structs to file
    By |deep| in forum C++ Programming
    Replies: 2
    Last Post: 06-01-2002, 08:14 AM