Hlavní navigace

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

Michal Burda

V minulém díle jsme začali rozebírat možnosti, které přináší knihovna GLib pro práci se standardními céčkovskými řetězci ukončenými nulovým znakem. Dnes toto povídání dokončíme. Budeme se bavit o odstraňování bílých znaků, spojování řetězců dohromady a rozdělování řetězce na pole řetězců. Látky je víc než dost, takže hurá do toho.

Odstraňování bílých znaků

Bílé znaky, anglicky white spaces, je posloupnost znaků, které nejsou vidět na obrazovce. Jsou to oddělovací znaky jako mezera, tabulátor, nový řádek a podobně. Někdy je nežádoucí, aby se v řetězci vyskytovaly (dostanou se tam třeba čtením ze souboru) a pak je nutno je odstranit. Právě k tomu slouží následující funkce.

gchar* g_strchug(gchar *string); 

…odstraní všechny bílé znaky (white spaces) ze začátku řetězce string. Zbývající znaky posune na začátek tak, aby vyplnily vzniklou mezeru. Vrátí string.

gchar* g_strchomp(gchar *string); 

…odstraní všechny bílé znaky (white spaces) z konce řetězce string. Vrátí string.

A konečně makro:

#define g_strstrip(string) 

…které odstraní všechny bílé znaky (white spaces) ze začátku i konce řetězce.

Spojování řetězců dohromady

gchar* g_strconcat(const gchar *string1, ...); 

…spojí všechny řetězce, zapsané jako argumenty funkce, dohromady. Řetězce zapisujte jako argumenty postupně za sebou v takovém pořadí, v jakém je chcete spojit. Posledním prvkem musí být vždy NULL. Výsledný, nově alokovaný řetězec funkce použije jako návratovou hodnotu. Vrácený řetězec je třeba po použití dealokovat. Vstupní řetězce zůstanou nedotčeny.

gchar* g_strjoin(const gchar *separator, ...); 

…tato funkce spojí všechny řetězce, zadané jako argumenty ..., dohromady. Mezi každé dva vloží volitelný řetězec separator. Je-li separator roven NULL, mezi řetězce se nebude vkládat nic (analogie s funkcí g_strconcat). Posledním prvkem v seznamu argumentů (řetězců) musí být NULL. Vrácený řetězec je výsledek operace sloučení. Je nově alokovaný v paměti a proto by měl být po použití dealokován.

Příklad:

/* ukazka spojovani retezcu */

#include <glib.h>

gint main(void) {
  gchar *s;

  s = g_strconcat("Toto", "je", "prvni", "retezec.", NULL);
  puts(s);
  g_free(s);
  s = g_strjoin(" ", "Toto", "je", "druhy", "retezec.", NULL);
  puts(s);
  g_free(s);

  return(0);
}

Po spuštění této malé ukázky by se na výstupu mělo objevit doslova toto:

Totojeprvniretezec.
Toto je druhy retezec.

Rozdělování řetězce na pole řetězců

GLib definuje pár funkcí zabývajících se rozdělením řetězce podle určitých kritérií na pole řetězců. První z nich je funkce:

gchar* g_strdelimit(gchar *string, const gchar *delimiters,
                    gchar new_delimiter);

…která nahradí rozdělovací znaky v řetězci string novým znakem new_delimiter. Každý znak řetězce string, který bude nalezen v řetězci delimiters, bude nahrazen znakem new_delimiter. Je-li delimiters rovno NULL, použijí se rozdělovací znaky definované jako makro  G_STR_DELIMITERS:

#define G_STR_DELIMITERS "_-|> <." 

Změny se provedou přímo v řetězci string. Funkce g_strdelimit jako návratovou hodnotu použije vstupní argument string.

Pro rozdělení řetězce podle rozdělovacího znaku na pole řetězců použijte funkci:

gchar** g_strsplit(const gchar *string, const gchar *delimiter,
                   gint max_tokens);

Tato rutina se postará o alokování pole řetězců, které předá jako návratovou hodnotu. Pole řetězců vytvoří z řetězce string tak, že jej rozdělí na maximálně max_tokens částí v místech specifikovaných řetězcem delimiter.

Každý znak řetězce delimiter bude v řetězci string chápán jako místo, kde má dojít k rozdělení. Je-li max_tokens menší než 1, rozdělí se celý řetězec. Je-li však max_tokens kladná nenulová hodnota a počet rozdělení dosáhne tohoto čísla, poslední řetězec ve vráceném poli řetězců bude obsahovat zbytek řetězce string (nezáleží na tom, že třeba ještě obsahuje nějaké rozdělovací znaky z  delimiter).

Znaky, které jsou chápány jako rozdělovací, ve výsledném poli nebudou nikdy obsaženy, ledaže bychom dosáhli max_tokens rozdělení – v takovém případě se znaky z  delimiter mohou objevit v posledním řetězci. Posledním prvkem vráceného pole je pointer s hodnotou NULL  – podle toho se také pozná konec pole.

Původní řetězec string zůstane nezměněn, takže jestliže jste ho vytvořili dynamicky, je třeba jej nakonec dealokovat – například funkcí  g_free().

K uvolnění pole řetězců vytvořeného funkcí g_strsplit() používejte:

void g_strfreev(gchar **str_array); 

…která odstraní z paměti všechny prvky pole (nulovým znakem ukončené řetězce) i samotné pole str_array.

Pro práci s poli řetězců je zde ještě jedna funkce. Její funkční prototyp je:

gchar* g_strjoinv(const gchar *separator, gchar **str_array); 

Funkce spojí řetězce, uložené v poli str_array. Je-li separator různý od NULL, vloží řetězec separator mezi každé dva spojované řetězce pole. Pole str_array musí být ukončeno NULL em (tzn. poslední prvek pole musí být NULL). Funkce vrátí nově alokovaný řetězec vytvořený spojením řetězců pole str_array.

Příklad:

/* Rozdelovani retezce na pole retezcu */

#include <glib.h>

gint main(void) {
  gchar *s, *spojeny, *pomocny;
  gchar **pole;
  gint x = 0;

  /* vytvoreni noveho retezce */
  s = g_strdup("Ahoj|jak_se_mas?");
  printf("Puvodni s = %s\n", s);

  /* nahrada oddelovacich znaku (G_STR_DELIMITERS) mezerou */
  g_strdelimit(s, NULL, ' ');
  printf("Upraveny s = %s\n", s);

  /* rozdeleni s na pole retezcu */
  pole = g_strsplit(s, " ", 0);

  /* kontrolni vypis pole */
  pomocny = pole[0];
  while (pomocny != NULL) {
    puts(pomocny);
    pomocny = pole[++x];
  }

  /* spojeni pole */
  spojeny = g_strjoinv("...", pole);
  printf("spojeny = %s\n", spojeny);

  /* dealokace */
  g_strfreev(pole);
  g_free(s);
  g_free(spojeny);

  return(0);
}

Po spuštění by se mělo vypsat:

Puvodni s = Ahoj|jak_se_mas?
Upraveny s = Ahoj jak se mas?
Ahoj
jak
se
mas?
spojeny = Ahoj...jak...se...mas?

A to je z mé strany o standardních céčkovských řetězcích vše – ale u řetězců ještě zůstaneme. Budeme si povídat o novém typu „nafukovacího řetězce“ GString, u kterého se nemusíte bát, že vám data přetečou mimo alokovanou paměť – GString se sám realokuje s přidáváním textu; ale o tom až příště.

Našli jste v článku chybu?
Podnikatel.cz: Změny v cestovních náhradách 2017

Změny v cestovních náhradách 2017

Vitalia.cz: Taky věříte na pravidlo 5 sekund?

Taky věříte na pravidlo 5 sekund?

120na80.cz: 5 nejčastějších mýtů o kondomech

5 nejčastějších mýtů o kondomech

Lupa.cz: Kdo pochopí vtip, může jít do ČT vyvíjet weby

Kdo pochopí vtip, může jít do ČT vyvíjet weby

DigiZone.cz: TV Philips a Android verze 6.0

TV Philips a Android verze 6.0

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Podnikatel.cz: Chaos u EET pokračuje. Jsou tu další návrhy

Chaos u EET pokračuje. Jsou tu další návrhy

Lupa.cz: Insolvenční řízení kvůli cookies? Vítejte v ČR

Insolvenční řízení kvůli cookies? Vítejte v ČR

Měšec.cz: Jak levně odeslat balík přímo z domu?

Jak levně odeslat balík přímo z domu?

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Vitalia.cz: Jmenuje se Janina a žije bez cukru

Jmenuje se Janina a žije bez cukru

Vitalia.cz: Pamlsková vyhláška bude platit jen na základkách

Pamlsková vyhláška bude platit jen na základkách

Vitalia.cz: Potvrzeno: Pobyt v lese je skvělý na imunitu

Potvrzeno: Pobyt v lese je skvělý na imunitu

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

Vitalia.cz: Mondelez stahuje rizikovou čokoládu Milka

Mondelez stahuje rizikovou čokoládu Milka

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání

Vitalia.cz: Spor o mortadelu: podle Lidlu falšovaná nebyla

Spor o mortadelu: podle Lidlu falšovaná nebyla

Měšec.cz: Air Bank zruší TOP3 garanci a zdražuje kurzy

Air Bank zruší TOP3 garanci a zdražuje kurzy

Podnikatel.cz: Snížení DPH na 15 % se netýká všech

Snížení DPH na 15 % se netýká všech

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?