Управление ассоциативным массивом (хэш-таблицей)
#include <search.h>int hcreate( size_t nel );int hcreate_r( size_t nel, struct hsearch_data *table );void hdestroy( void );void hdestroy1( void (*freekey)( void * ), void (*freedata)( void * ) );void hdestroy_r( struct hsearch_data *table );void hdestroy1_r( struct hsearch_data *table, void (*freekey)( void * ), void (*freedata)( void * ) );ENTRY * hsearch( ENTRY item, ACTION action );int hsearch_r( ENTRY item, ACTION action, ENTRY **itemp, struct hsearch_data *table );
ENTRY
содержит два указателя: ACTION
определяет следующие значения: libc
Функции hcreate*(), hdestroy*() и hsearch*() управляют хэш-таблицей.
Функция hcreate() выделяет память и инициализирует хэш-таблицу. Параметр nel указывает оценку максимального количества записей, которые должны хранится в хэш-таблице. Если дополнительное выделение памяти не приведет к сбою, задание недостаточного значения nel не приведет к нерабочему состоянию, однако может привести к снижению производительности. Инициализация с помощью функции hcreate() обязательна перед любыми операциями с использованием функции hsearch().
Функция hdestroy() уничтожает хэш-таблицу ранее созданную с помощью hcreate(). После вызова hdestroy() данные больше не могут быть доступны.
Функция hsearch() используется для поиска в хэш-таблице и возвращает указатель на запись в хэш-таблице. Параметр item имеет тип ENTRY
, определенный в <search.h>
. Для сравнения ключей в hsearch() используется strcmp().
Функции hdestroy() и hdestroy_r() не освобождают данные, связанные с ключем и значением каждой записи, так как они не выделяли их. Поскольку функция «итератор» не предусмотрена, функции hdestroy1() и hdestroy1_r() позволяют управлять освобождением ключа или значения с помощью предоставленных в параметрах функций freekey() и freedata().
Если freekey() и freedata() равны NULL , то ключ и значение не освобождаются, что может привести к утечкам памяти. |
Функции hcreate_r(), hdestroy_r(), hdestroy1_r(), hsearch_r() являются реентерабельными версиями соответствующих функций, которые могут оперировать с хэш-таблицей, предоставленной пользователем. Функция hsearch_r() возвращает 0
если параметр action имеет значение ENTER
и новая запись не может быть создана, иначе возвращается 1
. Если запись уже существует или может быть создана, она помещается в itemp, иначе itemp устанавливается в NULL
.
ЗОСРВ
«Нейтрино»
редакции 2021
В случае успеха, функции hcreate() и hcreate_r() возвращают ненулевое значение. Иначе возвращается значение 0
и errno устанавливается для индикации ошибки.
Функции hdestroy() и hdestroy_r() не возвращают значение.
В случае успеха, функция hsearch() возвращает указатель на запись в хэш-таблице, соответствующую предоставленному ключу. Если параметр action имеет значение FIND
и запись не была найдена, или если параметр action имеет значение ENTER
и новая запись не может быть создана, возвращается NULL
и errno устанавливается для индикации ошибки. Если параметр action имеет значение ENTER
и в хэш-таблице уже существует запись, соответствующая предоставленному ключу, существующая запись возвращается.
Функция hsearch_r() возвращает 1
если хеш-таблица не заполнена, иначе возвращает 0
. Если функция hsearch_r() возвращает 0
или запись не найдена, errno устанавливается для индикации ошибки.
По крайней мере, можно упомянуть следующие ограничения:
|
Функции hcreate(), hcreate_r(), hsearch() и hsearch_r() могут завершаться со следующей ошибкой:
Функции hsearch() и hsearch_r() могут также завершиться с ошибкой если параметр action имеет значение FIND
и запись не была найдена:
Пример ниже читает строки, завершающиеся двумя числами, и помещает их в хэш таблицу, отбрасывая дубликаты. Затем он читает строки, находит соответствующую запись в таблице и выводит ее.
#include <stdio.h>#include <search.h>#include <string.h>#include <stdlib.h>struct info { /* this is the info stored in table */int age, room; /* other than the key */};#define NUM_EMPL 5000 /* # of elements in search table */int main( void ){char string_space[NUM_EMPL*20]; /* space to store strings */struct info info_space[NUM_EMPL]; /* space to store employee info */char *str_ptr = string_space; /* next avail space in string_space */struct info *info_ptr = info_space; /* next avail space in info_space */ENTRY item, *found_item;char name_to_find[30]; /* name to look for in table */int i = 0;/* create table */(void)hcreate( NUM_EMPL );while ( scanf( "%s%d%d", str_ptr, &info_ptr->age, &info_ptr->room ) != EOF && i++ < NUM_EMPL ){/* put info in structure, and structure in item */item.key = str_ptr;item.data = (void *)info_ptr;str_ptr += strlen( str_ptr ) + 1;info_ptr++;/* put item into table */(void)hsearch( item, ENTER );}freopen( "/dev/tty", "r", stdin );/* access table */item.key = name_to_find;while ( scanf( "%s", item.key ) != EOF ){if ( (found_item = hsearch( item, FIND )) != NULL )/* if item is in the table */(void)printf( "found %s, age = %d, room = %d\n", found_item->key,((struct info *)found_item->data)->age,((struct info *)found_item->data)->room );else(void)printf( "no such employee %s\n", name_to_find );}hdestroy();return (0);}
POSIX 1003.1 X/Open Systems Interfaces Extension
bsearch(), free() lsearch() malloc() strcmp()
Предыдущий раздел: Описание API системной библиотеки