Odstraňování prvků z datových souprav
#define g_dataset_id_remove_data(l, k) #define g_dataset_remove_data(l, k)
Tyto makra slouží ke zrušení položek soupravy dat napojených na data l
. Rušenou položku můžete určit buď číselnou ( GQuark
ovou) konstantou k
(v případě g_dataset_id_remove_data()
) nebo řetězcovým klíčem k
(u makra g_dataset_remove_data()
). Má-li rušená položka přiřazenou dealokovací funkci, její data se navíc automaticky uvolní z paměti.
Podobně jako v klíčovaných seznamech i u datových souprav máte možnost odstranit položku bez automatického volání dealokovací funkce. Provede se to jedním z následujících dvou způsobů:
void g_dataset_id_remove_no_notify(gconstpointer dataset_location, GQuark key_id); #define g_dataset_remove_no_notify(l, k)
Přístupy se opět liší pouze způsobem adresace rušené položky. dataset_location
a l
je lokace „hlavních“ dat v paměti, key_id
GQuark
ový klíč a k
řetězcový klíč odstraňované položky. I kdyby rušená položka měla asociovánu dealokovací funkci, voláním těchto dvou rutin se proces uvolnění dat nikdy neprovede.
Konstrukce „foreach“
void g_dataset_foreach(gconstpointer dataset_location, GDataForeachFunc func, gpointer user_data); void(*GDataForeachFunc)(GQuark key_id, gpointer data, gpointer user_data);
Pokud čtete články o knihovně GLib pravidelně, musí vás už (stejně jako mě) dost nudit znovu a znovu číst o funkcích „foreach“. Aby ale tento seriál mohl sloužit také trochu jako referenční příručka, nezbývá mi než poznamenat, že také soupravy dat disponují tímto voláním a ještě jednou zopakovat, jak funkce „foreach“ fungují:
Funkce g_dataset_foreach()
zavolá na každý prvek soupravy dat, jejíž rozpoznávacím znakem je pointer dataset_location
, uživatelskou funkci func
, které předá GQuark
ový klíč key_id
prvku, jeho data data
a uživatelská data user_data
. Vykoná se tak něco jako příkaz „pro každou položku soupravy dat udělej __něco__“.
Uvolnění soupravy dat z paměti
void g_dataset_destroy(gconstpointer dataset_location);
…voláním této funkce se souprava dat, která je napojena na dataset_location
, uvolní z paměti. Na všechny její prvky budou zavolány (pokud existují) příslušné dealokovací funkce, takže se uvolní i uložená data. S „hlavními“ daty dataset_location
se pochopitelně nestane nic – to musíte obstarat sami.
Příklad
Následující příklad simuluje typické použití souprav dat. Sestává ze tří souborů: libclovek.c
a libclovek.h
je jakási knihovna funkcí pro práci s databází kontaktů (opravdu primitivní – jen pro ukázku). Soubor main.c
je pak hlavní program, který tuto knihovnu používá.
/************** Soubor: libclovek.h ***************/ /* struktura definujici jednoho cloveka */ typedef struct { gchar *jmeno; gchar *prijmeni; } LibClovek; /* deklarace funkce */ extern LibClovek* lib_cti_cloveka(void); /************** Soubor: libclovek.c ***************/ /* Vnejsi knihovna pracujici s databazi kontaktu */
#include <glib.h>
#include „libclovek.h“
/* Funkce, ktera cte jednoho cloveka z databaze */ LibClovek* lib_cti_cloveka(void) { LibClovek *clovek; clovek = g_malloc(sizeof(LibClovek)); /* Tady by spravne melo byt cteni z databaze. * Pro jednoduchost vsak promennou clovek jen nejak * inicializujeme: */ clovek->jmeno = "Karel"; clovek->prijmeni = "Novak"; return clovek; } /* Nacteni dalsiho cloveka :-) */ LibClovek* lib_cti_dalsiho_cloveka(void) { LibClovek *clovek; clovek = g_malloc(sizeof(LibClovek)); clovek->jmeno = "Josef"; clovek->prijmeni = "Kvetinac"; return clovek; } /**************** Soubor: main.c ******************/ /* Hlavni program */
#include <glib.h>
#include „libclovek.h“
#define ADRESA 1 #define TELEFON 2 gint main(void) { LibClovek *clovek, *clovek2; /* Nacteni cloveka z databaze */ clovek = lib_cti_cloveka(); /* Struktura LibClovek nam nestaci. Chteli bychom u kazdeho * cloveka uchovavat jeste jeho telefonni cislo a adresu. */ g_dataset_id_set_data(clovek, ADRESA, "Polni 22, Praha 8"); g_dataset_id_set_data(clovek, TELEFON, "02/321321"); /* Nacteni dalsiho cloveka */ clovek2 = lib_cti_dalsiho_cloveka(); g_dataset_id_set_data(clovek2, ADRESA, "Zahradni 1, Liberec"); g_dataset_id_set_data(clovek2, TELEFON, "0386/111222"); /* ... nejake zpracovani ... */ /* Kontrolni tisk */ printf("%s %s, %s; telefon: %s\n", clovek->jmeno, clovek2->prijmeni, g_dataset_id_get_data(clovek, ADRESA), g_dataset_id_get_data(clovek, TELEFON)); printf("%s %s, %s; telefon: %s\n", clovek2->jmeno, clovek2->prijmeni, g_dataset_id_get_data(clovek2, ADRESA), g_dataset_id_get_data(clovek2, TELEFON)); g_dataset_destroy(clovek); g_dataset_destroy(clovek2); g_free(clovek); g_free(clovek2); }
Soubor libclovek.h
definuje strukturu LibClovek
jejímiž prvky jsou řetězce jmeno
a prijmeni
.
Soubor libclovek.c
obsahuje dvě funkce, které toho opravdu moc nedělají – slouží jen k demonstraci. V reálném programu by načítaly z databáze jeden záznam a ve struktuře LibClovek
jej předávaly jako návratovou hodnotu. Pro naši ukázku stačí, když alokují místo pro jeden záznam a inicializují ho nějakými statickými hodnotami.
Dostáváme k hlavnímu programu, souboru main.c
. Jeho úkolem by v reálné situaci bylo nějakým způsobem údaje o lidech zpracovávat. Program využívá knihovnu libclovek
, ale struktura LibClovek
jeho účelům nestačí. Bylo by třeba u každého záznamu uchovávat ještě nějaké další údaje: třeba adresu a telefonní číslo. Do „standardní“ knihovny libclovek
zasahovat nemůžeme, proto použijeme soupravy dat.
Ve zdrojovém kódu můžete vidět, jak se k adrese paměti, kterou uchovávají pointery clovek
a clovek2
asociují řetězcové položky s klíči ADRESA
a TELEFON
.
Následuje kontrolní tisk všech údajů na obrazovku a dealokování veškerých dynamických dat.
V příkladu jsem záměrně nepoužil řetězcové konstanty – dokonce jsem vypustil celý mechanizmus kvarků. Chtěl jsem totiž ukázat, že k použití souprav dat, ale i klíčovaných seznamů dat je vůbec nepotřebujeme. Stačí, když si uvědomíme, že GQuark
y nejsou nic jiného než přirozená čísla (1..???). A tak místo řetězců můžeme jednoduše používat konstantní makra (viz ADRESA
a TELEFON
).
Ukázka by po zkompilování měla vypsat:
Karel Novak, Polni 22, Praha 8; telefon: 02/321321 Josef Kvetinac, Zahradni 1, Liberec; telefon: 0386/111222