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?