Thread: malloced 2d array passed to qsort

  1. #1
    Registered User
    Join Date
    Mar 2004
    Posts
    66

    malloced 2d array passed to qsort

    I have the following code to add directory contents to a malloc'ed array of pointers to arrays.

    However, after passing the 2d array to qsort, qsort returns nothing in the array.

    array here = (null)

    If i take the qsort out, the print_dir() prints the array nicely.

    Am i missing something?

    Code:
    	
    	int  n = 100;
    	char **names_array;
    
    	names_array = malloc(num_of_files * sizeof(char *));
    	if(names_array == NULL)
    	{
    		fprintf(stderr, "out of memory\n");
    	}
    	for(i = 0; i < nrows; i++)
    	{
    		names_array[i] = malloc(n * sizeof(char));
    		if(names_array[i] == NULL)
    		{
    			fprintf(stderr, "out of memory\n");
    		}
    	}
    
    
    	if ( (dirp = opendir(current_dir)) != NULL )
    	{
    		i = 0;
    	  	while ( (direntp = readdir( dirp )) != NULL )
    		{
    			names_array[i][n-1] = '\0';
    
    		    strcpy(names_array[i], direntp->d_name);
    		
    			printf("array here = %s\n", names_array[i]);
    
    			i++;
    	     }
    			
    	     qsort(names_array,num_of_files ,1024, qsort_contents);
    		 printf("array here = %s\n", names_array[0]);
    		 print_dir(names_array, num_of_files, 1, flags);
    
    	}
    Last edited by Salem; 11-25-2005 at 12:23 PM. Reason: Use code, not php tags

  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
    > qsort(names_array,num_of_files ,1024, qsort_contents);
    1. You didn't post your compare function. Getting compare functions right can be a tricky problem

    2. You specified the wrong number of elements - it should be the 'i' variable which you counted with.
    Ditto for when you print them out - only print what's valid.

    3. You specified the wrong size for each element of the array - where did 1024 come from???

    Try for example
    Code:
    qsort(names_array, i, sizeof names_array[0], qsort_contents );

  3. #3
    Registered User
    Join Date
    Aug 2005
    Posts
    1,267
    Code:
    names_array[i][n-1] = '\0';
    The above line is unnecessary -- strcpy() will null-terminate the string. And if you use strdup() instead of strcpy() it not necessary to allocate the memory ahead of time, so you can delete the previous loop that calls malloc() entirely. strdup() will allocate the required amount of space, copy the string into that memory, and return the pointer.

  4. #4
    Registered User
    Join Date
    Mar 2004
    Posts
    66
    cheers Ancient Dragon nice tip.

    Quote Originally Posted by Salem
    > qsort(names_array,num_of_files ,1024, qsort_contents);
    1. You didn't post your compare function. Getting compare functions right can be a tricky problem

    2. You specified the wrong number of elements - it should be the 'i' variable which you counted with.
    Ditto for when you print them out - only print what's valid.

    3. You specified the wrong size for each element of the array - where did 1024 come from???

    Try for example
    Code:
    qsort(names_array, i, sizeof names_array[0], qsort_contents );

    PHP Code:
    int qsort_contents(const voidname1, const voidname2)
    {
      
    /* check the first file names first characted so we know if we need 
         to skip this characted when comparing the strings*/

     
      
    int i 0;

      
    /* if the first names 1st char is not a letter */
        
    if (( ( (char *)name1)[0] < 'A') || ( ((char *)name1)[0] > 'z' ) )
        {
          
    /* if the second names 1st char is also not a letter */
            
    if (( ( (char *)name2)[0] < 'A') || ( ((char *)name2)[0] > 'z' ) )
          {
            return 
    strcmp( &((char *)name1)[1], &((char *)name2)[1]);
          }
        
    /* if just the first names 1st char is not a letter*/
        
    else
          {
            
            return 
    strcmp( &((char *)name1)[1], ((char *)name2));
          }
        }
        
    /* if the second names 1st char is not a letter */
      
    else if (( ( (char *)name2)[0] < 'A') || ( ((char *)name2)[0] > 'z' ) )
        {
          return 
    strcmp(((char *)name1), &((char *)name2)[1]);
        }

        return 
    strcmp( (char*)name1, (char *)name2);


    I changed the call to qsort, however its not returned the contents in sorted order.
    Last edited by jamie85; 11-25-2005 at 12:55 PM.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Here
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /* we get here, the equivalent of char** */
    /* since qsort effectively calls  cmp(&a[x],&a[y]) */
    int cmp ( const void *a, const void *b ) {
      const char *const *pa = a;
      const char *const *pb = b;
      return strcmp ( *pa, *pb );
    }
    
    void show ( char *arr[], int n ) {
      int i;
      for ( i = 0 ; i < n ; i++ ) {
        printf( "%s\n", arr[i] );
      }
      printf( "--\n\n" );
    }
    
    int main ( ) {
      char *test[] = {
        "this", "is", "an", "example"
      };
      show ( test, 4 );
      qsort ( test, 4, sizeof test[0], cmp );
      show ( test, 4 );
      return 0;
    }
    And please use code tags, not php tags in future.

    > strdup() will allocate the required amount of space, copy the string into that memory, and return the pointer.
    strdup() is not a standard function.

  6. #6
    Registered User
    Join Date
    Aug 2005
    Posts
    1,267
    Code:
    int cmp ( const void *a, const void *b ) {
      return strcmp ( (const char*)a, (const char*)b);
    }
    The compare function only needs to be like this.

  7. #7
    Registered User
    Join Date
    Mar 2004
    Posts
    66
    Quote Originally Posted by Salem
    Here
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /* we get here, the equivalent of char** */
    /* since qsort effectively calls  cmp(&a[x],&a[y]) */
    int cmp ( const void *a, const void *b ) {
      const char *const *pa = a;
      const char *const *pb = b;
      return strcmp ( *pa, *pb );
    }
    
    void show ( char *arr[], int n ) {
      int i;
      for ( i = 0 ; i < n ; i++ ) {
        printf( "%s\n", arr[i] );
      }
      printf( "--\n\n" );
    }
    
    int main ( ) {
      char *test[] = {
        "this", "is", "an", "example"
      };
      show ( test, 4 );
      qsort ( test, 4, sizeof test[0], cmp );
      show ( test, 4 );
      return 0;
    }
    And please use code tags, not php tags in future.

    > strdup() will allocate the required amount of space, copy the string into that memory, and return the pointer.
    strdup() is not a standard function.

    Thanks salem very helpful of you

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > The compare function only needs to be like this.
    Look again - I put your code into my program, and ....

    nothing happened - I guess my pointers are already in order.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Treating a 2D array as a 1D array....
    By John_L in forum C Programming
    Replies: 6
    Last Post: 10-18-2007, 02:38 PM
  2. question about multidimensional arrays
    By richdb in forum C Programming
    Replies: 22
    Last Post: 02-26-2006, 09:51 AM
  3. how to pass 2D array into function..?
    By IngramGc in forum C++ Programming
    Replies: 2
    Last Post: 10-21-2001, 08:41 AM
  4. Hi, could someone help me with arrays?
    By goodn in forum C Programming
    Replies: 20
    Last Post: 10-18-2001, 09:48 AM
  5. 2d Array access by other classes
    By deaths_seraphim in forum C++ Programming
    Replies: 1
    Last Post: 10-02-2001, 08:05 AM