4
#include <stdio.h>
#include <stdlib.h>
#include <search.h>
#include <assert.h>

char *data[] = { "alpha", "bravo", "charlie", "delta",
      "echo", "foxtrot", "golf", "hotel", "india", "juliet",
      "kilo", "lima", "mike", "november", "oscar", "papa",
      "quebec", "romeo", "sierra", "tango", "uniform",
      "victor", "whisky", "x-ray", "yankee", "zulu"
       };

int
main(void)
{
    ENTRY e, **ep;
    struct hsearch_data *htab;
    int i;
    int resultOfHcreate_r;
    resultOfHcreate_r=hcreate_r(30,htab);
    assert(resultOfHcreate_r!=0);
    hdestroy_r(htab);
    exit(EXIT_SUCCESS);
}

error in hcreate_r

How to use this hcreate_r?

and other question is that :

Could you privde the GNU extension C library examples ? I think the document of GNU extension C library is not enough knowledge to write.

and I have many questions of how to use the extension C library .

Pavan Manjunath
  • 27,404
  • 12
  • 99
  • 125
wei
  • 65
  • 2
  • 7

2 Answers2

5

First off, you will need to add the #define _GNU_SOURCE macro in order to access the GNU extensions properly. ie:

#define _GNU_SOURCE
#include <search.h>

Then you need to understand the documentation:

Function: int hcreate_r (size_t nel, struct hsearch_data *htab)

The hcreate_r function initializes the object pointed to by htab to contain a 
hashing table with at least nel elements. So this
function is equivalent to the hcreate function except that the
initialized data structure is controlled by the user.

This allows having more than one hashing table at one time. 
The memory necessary for the struct hsearch_data object can be allocated
dynamically. It must be initialized with zero before calling this
function.

The return value is non-zero if the operation was successful. 
If the return value is zero, something went wrong, which probably means
the programs ran out of memory.


So unlike hcreate, you are providing the hashing table data structures. Further, those structures should be initialised to zero. So then you probably want to do something like this:

//dynamically create a single table of 30 elements 
htab=calloc(1,sizeof(struct hsearch_data));
resultOfHcreate_r=hcreate_r(30,htab);

//do some stuff

//dispose of the hash table and free heap memory
hdestroy_r(htab);
free(htab)
violet313
  • 1,912
  • 1
  • 15
  • 19
  • hi violet313 , thanks . the code works. but htab=calloc(30,sizeof(struct hsearch_data)); just alloc the memory ,not initialised to zero. don't need to initialised to 0 ? – wei May 12 '12 at 00:59
  • 1
    ah, thats the beauty of [calloc](http://linux.die.net/man/3/calloc); it zeros the memory for you ~& *iff* you're lucky with your `calloc` implementation *&* the moon is full *&* it's a thursday *&* you saw a magpie that day *&* your allocation is large enough to require whole pages,,, *then it might even be faster* than `malloc` + `memset` ~but in any case it's less to type so i like it ;) – violet313 May 12 '12 at 04:03
  • 1
    Why don't you just go `struct hsearch_data htab; memset(&htab, 0, sizeof(htab)); result = hcreate_r(30, &htab);`? – Jack Kelly May 13 '12 at 00:42
0

Here's an hcreate_r variation of the hcreate example from the man page.

It should compile and run and uses some of the ideas discussed here.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define _GNU_SOURCE
#include <search.h>

char *data[] = { "alpha", "bravo", "charlie", "delta",
      "echo", "foxtrot", "golf", "hotel", "india", "juliet",
      "kilo", "lima", "mike", "november", "oscar", "papa",
      "quebec", "romeo", "sierra", "tango", "uniform",
      "victor", "whisky", "x-ray", "yankee", "zulu"
       };

int
main(void)
{
    ENTRY e, *ep;
    struct hsearch_data *htab;
    int i;
    
    /*dynamically allocate memory for a single table.*/ 
    htab = (struct hsearch_data*) malloc( sizeof(struct hsearch_data) );
    /*zeroize the table.*/
    memset(htab, 0, sizeof(struct hsearch_data) );
    /*create 30 table entries.*/
    assert( hcreate_r(30,htab) != 0 );
    
    /*add data to 24 entries.*/
    for (i = 0; i < 24; i++) {
        e.key = data[i];
        /* data is just an integer, instead of a
           pointer to something */
        e.data = (void *) i;
        
        /* there should be no failures */
        if (hsearch_r(e, ENTER, &ep, htab) == 0) {
            fprintf(stderr, "entry failed\n");
            exit(EXIT_FAILURE);
        }
    }

    for (i = 22; i < 26; i++) {
        /* print two entries from the table, and
           show that two are not in the table */
        e.key = data[i];
        
        if (hsearch_r(e, FIND, &ep, htab) == 0) {
            ep = NULL;
        }
        printf("%9.9s -> %9.9s:%d\n", e.key,
               ep ? ep->key : "NULL", ep ? (int)(ep->data) : 0);
    }
    
    //dispose of the hash table and free heap memory
    hdestroy_r(htab);
    free(htab);
    
    exit(EXIT_SUCCESS);
}
NorthStar
  • 81
  • 9
  • 1
    These examples will throw warnings on x86_64 machines and most probably on 32 bit machines as well. An address is 8 bytes on x86_64, but an int is usually 4 bytes. You can suppress the warning by changing the int datatypes to long datatypes, which are also 8 bytes. %ld is the printf format specifier for a long. – NorthStar Mar 28 '22 at 01:46
  • For a much more versatile, although nonstandard, solution check out [uthash](https://troydhanson.github.io/uthash/), which is just a header file, no library linking, but provides many of the functions one would expect from a hash table implementation. – NorthStar Mar 28 '22 at 01:55