Hlavní navigace

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

Michal Burda

Dnešním dílem pokračujeme v popisu knihovny jazyka C - GLib. Zaměříme se na funkce usnadňující práci s řetězci ukončenými nulovým znakem \0.

Vytvoření nového řetězce

gchar* g_strdup(const gchar *str); 

Funkce g_strdup() vyrobí duplikát řetězce str  – vrátí nově alokovanou kopii řetězce str. Je-li str rovno NULL, vrátí také NULL. Vrácený řetězec by měl být po použití dealokován (třeba funkcí g_free()).

gchar* g_strndup(const gchar *str, guint n); 

…alokuje v paměti nový řetězec a zkopíruje do něj prvních n znaků z řetězce str. Jestliže je str NULL, jednoduše vrátí NULL. Vrácený řetězec by měl být dealokován, když už nebude potřeba.

gchar* g_strnfill(guint length, gchar fill_char); 

Tato funkce se postará o vytvoření řetězce délky length a celého vyplněného znakem fill_char. Po použití by měl být řetězec dealokován.

gchar* g_strdup_printf(const gchar *format, ...); 

…vytvoří nový řetězec, jehož formát je dán řetězcem format a dalšími případnými parametry. Rutina je podobná funkci sprintf() ze standardního jazyka C. g_strdup_printf() je však bezpečnější, protože si vypočítává maximální velikost výsledku a podle toho alokuje potřebnou paměť. Vrácený řetězec by měl být po použití dealokován.

gchar* g_strdup_vprintf(const gchar *format, va_list args); 

…tato funkce je podobná standardní vsprintf(), je však bezpečnější, protože si vypočítává délku výsledku a podle toho alokuje paměť pro nový řetězec formátu format. Vrácený řetězec vždy nakonec dealokujte.

Pro úplnost je zde třeba doplnit ještě tři funkce, pracující s existujícími řetězci. Jejich podobnost s předchozími funkcemi je natolik velká, že bude lepší, uvedu-li je na tomto místě:

gint g_snprintf(gchar *string, gulong n,
                const gchar *format, ...);

…toto je bezpečnější náhrada standardní funkce sprintf(). Je garantováno, že výstup nebude delší než n znaků (včetně ukončovacího ‚\0‘ znaku). Nemůže tedy dojít k zápisu mimo vyhrazenou paměť. Funkce vrací délku výstupního řetězce string (včetně ukončovacího nulového znaku).

gint g_vsnprintf(gchar *string, gulong n,
                 const gchar *format, va_list args);

…tato funkce je bezpečnější formou funkce vsprintf(). Výstup včetně ukončovacího nulového znaku ( ‚\0‘) nebude delší než n znaků, takže nemůže nastat zápis mimo vyhrazenou paměť. Funkce vrátí délku výstupního řetězce string (včetně ukončovacího nulového znaku).

guint g_printf_string_upper_bound(const gchar *format,
                                  va_list args);

…vypočítá a vrátí maximální velikost paměti, které je třeba k uložení výstupu funkce vsprintf() (viz manuál k jazyku C).

Porovnávání

gint g_strcasecmp(const gchar *s1, const gchar *s2); 

Tato funkce implementuje tzv. case-insensitive porovnání (velká a malá písmena jsou chápána jako stejná). Rutina porovná řetězec s1 s řetězcem s2 a vrátí 0, jsou-li řetězce shodné, zápornou hodnotu, jestliže s1 < s2 (lexikograficky), nebo kladnou hodnotu, je-li s1 > s2.

gint g_strncasecmp(const gchar *s1, const gchar *s2, guint n); 

…je podobná předchozí funkci s tím rozdílem, že porovnává pouze prvních n znaků. Při porovnávání se nerozlišují velká a malá písmena. Funkce vrátí 0, jestliže jsou řetězce shodné, zápornou hodnotu, jestliže s1 < s2 (lexikograficky), nebo kladnou hodnotu, je-li s1 > s2.

Příklad:

/* zkouska case-insensitive porovnavani */

#include <glib.h>

gint main(void) {

  if (g_strcasecmp("Ahoj!", "AHOJ!") == 0)
    puts("Retezce jsou stejne!");
  if (g_strncasecmp("Ahoj, jak se mame?", "AHOJ!", 4) == 0)
    puts("Retezce jsou stejne!");

  return(0);
}

Spustíte-li si tento příklad, mělo by se dvakrát vypsat hlášení „ Retezce jsou stejne!“.

Různé konverze

void g_strup(gchar *string); 

…zkonvertuje znaky v řetězci string na velká písmena abecedy.

void g_strdown(gchar *string); 

…provede konverzi znaků ve string u na malá písmena abecedy.

void g_strreverse(gchar *string); 

…zrcadlově převrátí řetězec string (jakoby se četl pozpátku). Například volání g_strreverse() na řetězec "Abcdef" bude mít za následek text  "fedcbA".

Chcete-li zkonvertovat řetězec na číselnou hodnotu typu gdouble, zavolejte raději místo standardní funkce strtod()  funkci

gdouble g_strtod(const gchar *nptr, gchar **endptr); 

Tato funkce se pokusí voláním strtod() zkonvertovat řetězec nptr na návratovou hodnotu gdouble. Není-li řetězec kompletně zkonvertován, pokusí se o konverzi ještě jednou s použitím C locales a vrátí lepší výsledek. V případě neúplné konverze vrátí v  endptr pointer na první znak, který nebyl v konverzi použit. Jinak endptr nastaví na  NULL.

Příklad:

/* zkouska funkce g_strtod */

#include <glib.h>

gint main(void) {
  gchar *s;    /* zdrojovy retezec */
  gchar *t;    /* pomocny retezec */
  gdouble num; /* zkonvertovane cislo */

  s = "311211234.23 kilometru";
  num = g_strtod(s, &t); /* konverze - promenna t nyni ukazuje
                          * na 1. neciselny znak retezce s */

  printf("Cislo: %lf, za nim je: %s\n", num, t);

  return(0);
}

Zkompilujete-li a spustíte tento program, měl by v pořádku zkonvertovat řetězec s  na číslo a to uložit do proměnné num. Proměnná t by po volání g_strtod() měla ukazovat na první nečíselný znak řetězce s. Kontrolní výpis by měl vypsat:

Cislo: 311211234.230000, za nim je:  kilometru

…přičemž mezi „ je:“ a „ kilometru“ by měly být dvě mezery.

gchar* g_strescape(gchar *string); 

…tato funkce nahradí všechny výskyty zpětného lomítka ( '\') v řetězci string dvojicí zpětných lomítek ( "\\"). Funkce vrátí nově alokovaný řetězec s provedenou konverzí. Původní řetězec string zůstane nedotčen. Vrácený řetězec byste měli po použití dealokovat funkcí g_free() (viz předchozí díl).

A to je pro dnešek vše. V příštím díle povídání o řetězcích ukončených nulou dokončíme.

Našli jste v článku chybu?

13. 4. 2000 8:53

Michal Burda (neregistrovaný)

Spolehat se na to, ze na nejakem BSD uz existuji int32 apod, nezni take zrovna moc prenositelne. Urcite je sposta systemu, kde takove typy definovany nemaji. Proc by tedy GLib nemohla byt onim prvkem, na ktery se lze spolehnout?

Funkce g_strcasecmp() skutecne vola standardni funkci strcasecmp() - ovsem jen v pripade, ze na danem systemu existuje! Pokud se pri instalaci knihovny GLib zjisti, ze na dane platformne strcmp() neni, podminenym prekladem se pouzije alternativa implementujici vlastni v…

11. 4. 2000 19:32

Jaromir Dolecek (neregistrovaný)

ad gint32 & spol: opet vynalezli kolo a udelali to jinak nez to co jiz existuje - *BSD uz nejaky ten patek ma int32_t, u_int32_t apod. primo v (sys/types.h). I na nekterych ne-BSD systemech se tyto typy vyskytuji. IMHO tyto typy musi byt definovany ve standardnich hlavickach operacniho systemu - jiste je nesmysle, aby program zavisel na glibc v pripade, ze jen potrebuje urcitou velikos typu.
strcasecmp() _je_ standardni soucast ANSI C (stejne jako napr. setlocate(), strxfrm() atd).
Pokud kaz…

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

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č?

DigiZone.cz: TV Philips a Android verze 6.0

TV Philips a Android verze 6.0

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

Jmenuje se Janina a žije bez cukru

Podnikatel.cz: Změny v cestovních náhradách 2017

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

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

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

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

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

Mondelez stahuje rizikovou čokoládu Milka

120na80.cz: Horní cesty dýchací. Zkuste fytofarmaka

Horní cesty dýchací. Zkuste fytofarmaka

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

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

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: Proč vás každý zubař posílá na dentální hygienu

Proč vás každý zubař posílá na dentální hygienu

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

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

Root.cz: Certifikáty zadarmo jsou horší než za peníze?

Certifikáty zadarmo jsou horší než za peníze?

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

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

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

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

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

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

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

Vitalia.cz: Když přijdete o oko, přijdete na rok o řidičák

Když přijdete o oko, přijdete na rok o řidičák

Měšec.cz: mBank cenzuruje, zrušila mFórum

mBank cenzuruje, zrušila mFórum