glib provides a number of functions for string handling; some are unique to glib, and some solve portability concerns. They all interoperate nicely with the glib memory allocation routines.
For those interested in a better string than gchar*, there’s also a GString type. It isn’t covered in this book, but documentation is available at http://www.gtk.org/.
[code lang="cpp"]#include <glib.h>
gint g_snprintf(gchar* buf, gulong n, const gchar* format, ...);
gint g_strcasecmp(const gchar* s1, const gchar* s2);
gint g_strncasecmp(const gchar* s1, const gchar* s2, guint n);
[/code]
Figure 2-7. Portability Wrappers
One of the annoying things about C is that it provides the crash-causing, security- hole-creating, generally evil sprintf()
, but the relatively safe and widely implemented snprintf()
is a vendor extension. g_snprintf()
wraps native snprintf()
on platforms that have it, and provides an implementation on those that don’t. So you can say goodbye to sprintf()
forever. Even better: classically, snprintf()
does not guarantee that it will NULL-terminate the buffer it fills. g_snprintf()
does.
g_strcasecmp()
and g_strncasecmp()
perform a case-insensitive comparison of two strings, optionally with a maximum length. strcasecmp()
is available on many platforms but not universally, so using glib instead is advisable.
The functions in Figure 2-8 modify a string in-place: the first two convert the string to lowercase or uppercase, respectively, while g_strreverse()
reverses its characters. g_strchug()
and g_strchomp()
"chug" the string (remove leading spaces), or "chomp" it (remove trailing spaces). These last two return the string, in addition to modifying it in-place; in some cases it may be convenient to use the return value. There is a macro, g_strstrip()
, which combines both functions to remove both leading and trailing spaces; it is used just as the individual functions are.
[code lang="cpp"]
#include <glib.h>
void g_strdown(gchar* string);
void g_strup(gchar* string);
void g_strreverse(gchar* string);
gchar* g_strchug(gchar* string);
gchar* g_strchomp(gchar* string);
[/code]
Figure 2-8. In-place string modifications
Figure 2-9 shows a few more semi-standard functions glib wraps. g_strtod
is like strtod()—it converts string nptr to a double—with the exception that it will also at- tempt to convert the double in the "C" locale if it fails to convert it in the user ’s default locale. *endptr is set to the first unconverted character, i.e. any text after the number representation. If conversion fails, *endptr is set to nptr. endptr may be NULL, causing it to be ignored.
g_strerror() and g_strsignal() are like their non-g_ equivalents, but portable. (They return a string representation for an errno or a signal number.)
[code lang="cpp"]
#include <glib.h>
gdouble g_strtod(const gchar* nptr, gchar** endptr);
gchar* g_strerror(gint errnum);
gchar* g_strsignal(gint signum);
[/code]
Figure 2-9. String Conversions
Figure 2-10 shows glib’s rich array of functions for allocating strings. Unsurprisingly, g_strdup()
and g_strndup()
produce an allocated copy of str or the first n characters of str. For consistency with the glib memory allocation functions, they return NULL if passed a NULL pointer. The printf()
variants return a formatted string. g_strescape
escapes any \ characters in its argument by inserting another \ before them, returning the escaped string. g_strnfill()
returns a string of size length filled with fill_char
. g_strdup_printf()
deserves a special mention; it is a simpler way to handle this common piece of code:
[code lang="cpp"]
gchar* str = g_malloc(256);
g_snprintf(str, 256, "%d printf-style %s", 1, "format");
[/code]
Instead you could say this, and avoid having to figure out the proper length of the buffer to boot:
[code lang="cpp"]
gchar* str = g_strdup_printf("%d printf-style %s", 1, "format");
[/code]
[code lang="cpp"]
#include <glib.h>
gchar* g_strdup(const gchar* str);
gchar* g_strndup(const gchar* format, guint n);
gchar* g_strdup_printf(const gchar* format, ...);
gchar* g_strdup_vprintf(const gchar* format, va_list args);
gchar* g_strescape(gchar* string);
gchar* g_strnfill(guint length, gchar fill_char);
[/code]
Figure 2-10. Allocating Strings
glib provides some convenient functions for concatenating strings, shown in Figure
2-11. g_strconcat() returns a newly-allocated string created by concatenating each
of the strings in the argument list. The last argument must be NULL, so g_strconcat()
knows when to stop. g_strjoin() is similar, but separator is inserted between each
string. If separator is NULL, no separator is used.
[code lang="cpp"]
#include <glib.h>
gchar* g_strconcat(const gchar* string1, ...);
gchar* g_strjoin(const gchar* separator, ...);
[/code]
Figure 2-11. Concatenating strings
Finally, Figure 2-12 summarizes a few routines which manipulate NULL-terminated arrays of strings. g_strsplit() breaks string at each delimiter, returning a newly- allocated array. g_strjoinv() concatenates each string in the array with an optional separator, returning an allocated string. g_strfreev() frees each string in the array and then the array itself.
[code lang="cpp"]
#include <glib.h>
gchar** g_strsplit(const gchar* string, const gchar* delimiter, gint max_tokens);
gchar* g_strjoinv(const gchar* separator, gchar** str_array);
void g_strfreev(gchar** str_array);
[/code]
Figure 2-12. Manipulating NULL-terminated string vectors
Source: Havoc Pennington. 1999. GTK Gnome Application Development. New York: New Riders Publishing