Hlavní navigace

GLib: Práce s řetězci (3)

17. 4. 2000
Doba čtení: 5 minut

Sdílet

Práce s řetězci je ve standardním céčku trochu nemotorná. Musíte si neustále hlídat, kolik jste alokovali paměti. GLib přichází s novým řetězcovým typem GString, který vás rázem zbaví všech nepříjemností. GString je vlastně takový "nafukovací řetězec", který v paměti automaticky roste s tím, jak do něj přidáváte text.

GLib definuje nový datový typ, strukturu GString. Je to textový buffer, který v paměti roste automaticky s přidáváním znaků. Alokované místo se zvětšuje s mocninou dvojky; řetězce tedy zabírají 2, 4, 8, 16, 32, 64 atd. znaků. Jinými slovy, GString představuje něco jako „nafukovací řetězec“, který si bere tolik paměti, kolik je potřeba k uložení veškerého textu.

Struktura GString je definována takto:

struct GString
{
  gchar *str;
  gint len;
}

Řetězec str je v tomto případě obyčejný céčkovský řetězec ukončený nulovým znakem ( ‚\0‘) a takto k němu můžete i přistupovat. Pokud si nejste opravdu jisti tím, co děláte, používejte jej přímým voláním jen ke čtení. K zápisu využijte výhradně funkcí popsaných níže.

Položka len vždy obsahuje délku řetězce str bez ukončovacího znaku ‚\0‘.

Jelikož se řetězec automaticky realokuje, jak do něj přidáváte text, je velice pravděpodobné, že se bude v paměti stěhovat. Nelze tedy spoléhat na to, že pointer str bude ukazovat vždy na stejné místo v paměti.

Vytvoření nového GString u

Knihovna GLib definuje dvě funkce pro dynamické vytvoření GString u v pa­měti. Obě tyto rutiny používají pro alokaci paměti funkce, které jsme si popsali v minulém díle. Nemusíte proto testovat úspěšnost operace – v případě neúspěchu aplikace okamžitě končí.

GString* g_string_new(const gchar *init); 

…tato funkce vytvoří nový GString, tedy alokuje místo pro strukturu GString a přiřadí do ní řetězec init. Vrátí pointer na nově vzniklý GString.

Druhou možností vytvoření nového GString u je použití funkce

GString* g_string_sized_new(guint dfl_size); 

…která vytvoří nový GString s dostatkem místa pro dfl_size znaků. To je užitečné, když do řetězce hodláte mnohokrát přidávat text a nechcete, aby se realokoval příliš často.

Vkládání textu

Pro vkládání textu do GString u existuje řada jednoduchých funkcí. Pro všechny platí, že před vložením textu do řetězce uloženého v  GString u tento řetězec podle potřeby realokují na správnou velikost. Ve všech případech je návratovou hodnotou pointer na upravovaný GString.

GString* g_string_append(GString *string, const gchar *val); 

…tato funkce přidá do textového bufferu string řetězec  val.

Chcete-li na konec GString u přidat pouze jeden znak, zavolejte místo toho funkci:

GString* g_string_append_c(GString *string, gchar c); 

Obdobou předchozích dvou funkcí jsou

GString* g_string_prepend(GString *string, const gchar *val); 

…která uloží na začátek GString u string  řetě­zec val a funkce

GString* g_string_prepend_c(GString *string, gchar c); 

…která na počátek GString u string  uloží znak c.

GString* g_string_insert(GString *string,
                         gint pos, const gchar *val);

…tato funkce vloží do textového bufferu string na pozici pos řetězec  val.

GString* g_string_insert_c(GString *string,
                           gint pos, gchar c);

…vloží do GString u string  na pozici pos znak c.

Nahrazování textu

GString* g_string_assign(GString *lval, const gchar *rval); 

Funkce g_string_assign() zkopíruje obsah řetězce rval do textového bufferu lval. Původní obsah GStringlval se zruší.

void g_string_sprintf(GString* string,
                      const gchar *format, ...);

…tato funkce je podobná funkci sprintf() ze standardního céčka (na podrobnosti se podívejte do manuálu k jazyku C). g_string_sprintf() uloží do GString u string  formá­tovaný řetězec daný formátem format a volitelnými parametry funkce. GString samozřejmě podle potřeby zvětší svou velikost tak, aby v sobě mohl uchovat celý výsledný formátovaný řetězec. Předchozí obsah textového bufferu string bude zrušen.

Funkce

void g_string_sprintfa(GString* string,
                       const gchar *format, ...);

…je podobná předchozí funkci. Liší se tím, že formátovaný řetězec daný formátem format přidá na konec textového bufferu  string.

Odstraňování textu

GString* g_string_erase(GString *string, gint pos, gint len); 

Tato funkce odstraní len znaků z  GString u string  po­čínaje znakem na pozici pos (první znak má index 0). Zbytek řetězce je posunut dolů tak, aby vyplnil mezeru.

GString* g_string_truncate(GString *string, gint len); 

…odstraní konec řetězce, uloženého v  GString u string  tak, že ponechá jen prvních len  znaků.

Ostatní funkce

Než si probereme způsob dealokace GString u z pa­měti, zmíním se ještě o dvou jednoduchých funkcích, které jsou pro GString implementovány. Jsou to:

GString* g_string_up(GString *string); 

První z nich, g_string_up(), zkonvertuje veškerý text uložený v  GString u string  na velká písmena abecedy. Naproti tomu g_string_down() provede konverzi na malá písmena. Česká písmena jsou ovšem problémem.

Odstranění GString u z paměti

Po ukončení práce s  GString em je třeba jej z paměti dealokovat. K tomu slouží funkce

void g_string_free(GString* string, gint free_segment); 

Tato funkce uvolní z paměti GString. Je-li navíc free_segment nastaven na TRUE, dealokují se také textová data udržovaná GString em (položka str struktury GString  – viz. výše). Je-li free_segment FALSE, text zůstane v paměti, takže jej můžete dále používat jako obyčejný řetězec ukončený nulovým znakem.

root_podpora

Příklad:

#include <glib.h> 
int main(void) {
   GString *s, *t;
   gchar *u; /* pomocny pointer (retezec) */

   /* inicializace novych retezcu */
   s = g_string_new("ahoj");     /* vytvoreni s prirazenim */
   t = g_string_sized_new(10);   /* retezec v t zabira 10 bajtu */
   g_string_assign(t, "nazdar"); /* prirazeni */
   g_string_up(s);               /* konverze na velka pismena */

   /* kontrolni vypis */
   printf("obsah s: %s; delka s: %d\n", s->str, s->len);
   printf("obsah t: %s; delka t: %d\n", t->str, t->len);

   u = s->str; /* u nyni ukazuje na retezec ulozeny v s */

   /*dealokace */
   g_string_free(s, FALSE); /* data z s zustavaji v pameti */
   g_string_free(t, TRUE);  /* dealokuj veskery obsah t */

   /* kontrolni vypis - data pochazejici z GStringu s existuji! */
   printf("obsah u: %s\n", u);

   g_free(u); /* dealokuj retezec, ktery pochazi z s */

   return(0);
}

Věřím, že tento příklad pomohl přinést do věci jasno, a s ním se také pro dnešek rozloučíme. V příštím díle budeme pokračovat ve výkladu o práci s řetězci pomocí knihovny GLib. Probereme si funkce zaměřené na tzv. String Chunks (struktura GStringChunk), čímž výklad o řetězcích uzavřeme.

Byl pro vás článek přínosný?

Autor článku

Michal Burda vystudoval informatiku a aplikovanou matematiku a nyní pracuje na Ostravské univerzitě jako odborný asistent. Zajímá se o data mining, Javu a Linux.