📄 book.html
字号:
<tr><td> <font color="black"><pre>gintg_strncasecmp(const gchar* s1, const gchar* s2, guint n)</pre></font> </td></tr></table></p><p> Function Listing 2.2 shows some substitutes glib provides for commonly-implemented but unportable extensions to ANSI C.</p> <p> One of the annoying things about C is that it provides the crash-causing, security-hole-creating, generally evil <tt>sprintf()</tt>, but the relatively safe and widely implemented <tt>snprintf()</tt> is a vendor extension. <tt>g_snprintf()</tt> wraps native <tt>snprintf()</tt> on platforms that have it, and provides an implementation on those that don't. So you can say goodbye to <tt>sprintf()</tt> forever. Even better: classically, <tt>snprintf()</tt> does not guarantee that it will <tt>NULL</tt>-terminate the buffer it fills. <tt>g_snprintf()</tt> does.</p> <p> <tt>g_strcasecmp()</tt> and <tt>g_strncasecmp()</tt> perform a case-insensitive comparison of two strings, optionally with a maximum length. <tt>strcasecmp()</tt> is available on many platforms but not universally, so using glib instead is advisable.</p> <p> The functions in Function Listing 2.3 modify a string in-place: the first two convert the string to lowercase or uppercase, respectively, while <tt>g_strreverse()</tt> reverses its characters. <tt>g_strchug()</tt> and <tt>g_strchomp()</tt> "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, <tt>g_strstrip()</tt>, which combines both functions to remove both leading and trailing spaces; it is used just as the individual functions are.</p> <p><table bgcolor="#EEEEFF" width="100%"><caption><b>Function Listing 2.3:</b> In-place string modifications</caption><tr align="right"><td> <font color="black"> <tt>#include <glib.h></tt> </font> </td></tr><tr><td> <font color="black"><pre>voidg_strdown(gchar* string)</pre></font> </td></tr><tr><td> <font color="black"><pre>voidg_strup(gchar* string)</pre></font> </td></tr><tr><td> <font color="black"><pre>voidg_strreverse(gchar* string)</pre></font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strchug(gchar* string)</pre></font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strchomp(gchar* string)</pre></font> </td></tr></table></p><p> Function Listing 2.4 shows a few more semi-standard functions glib wraps. <tt>g_strtod</tt> is like <tt>strtod()</tt>---it converts string <tt>nptr</tt> to a double---with the exception that it will also attempt to convert the double in the <tt>"C"</tt> locale if it fails to convert it in the user's default locale. <tt>*endptr</tt> is set to the first unconverted character, i.e. any text after the number representation. If conversion fails, <tt>*endptr</tt> is set to <tt>nptr</tt>. <tt>endptr</tt> may be <tt>NULL</tt>, causing it to be ignored.</p> <p> <tt>g_strerror()</tt> and <tt>g_strsignal()</tt> are like their non-<tt>g_</tt> equivalents, but portable. (They return a string representation for an <tt>errno</tt> or a signal number.)</p> <p><table bgcolor="#EEEEFF" width="100%"><caption><b>Function Listing 2.4:</b> String Conversions</caption><tr align="right"><td> <font color="black"> <tt>#include <glib.h></tt> </font> </td></tr><tr><td> <font color="black"><pre>gdoubleg_strtod(const gchar* nptr, gchar** endptr)</pre></font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strerror(gint errnum)</pre></font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strsignal(gint signum)</pre></font> </td></tr></table></p><p> Function Listing 2.5 shows glib's rich array of functions for allocating strings. Unsurprisingly, <tt>g_strdup()</tt> and <tt>g_strndup()</tt> produce an allocated copy of <tt>str</tt> or the first <tt>n</tt> characters of <tt>str</tt>. For consistency with the glib memory allocation functions, they return <tt>NULL</tt> if passed a <tt>NULL</tt> pointer. The <tt>printf()</tt> variants return a formatted string. <tt>g_strescape</tt> escapes any <tt>\</tt> characters in its argument by inserting another <tt>\</tt> before them, returning the escaped string. <tt>g_strnfill()</tt>returns a string of size <tt>length</tt> filled with <tt>fill_char</tt>.</p> <p> <tt>g_strdup_printf()</tt> deserves a special mention; it is a simpler way to handle this common piece of code:</p> <pre> gchar* str = g_malloc(256); g_snprintf(str, 256, "%d printf-style %s", 1, "format");</pre><p> Instead you could say this, and avoid having to figure out the proper length of the buffer to boot:</p> <pre> gchar* str = g_strdup_printf("%d printf-style %s", 1, "format");</pre><p><table bgcolor="#EEEEFF" width="100%"><caption><b>Function Listing 2.5:</b> Allocating Strings</caption><tr align="right"><td> <font color="black"> <tt>#include <glib.h></tt> </font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strdup(const gchar* str)</pre></font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strndup(const gchar* format, guint n)</pre></font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strdup_printf(const gchar* format, ...)</pre></font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strdup_vprintf(const gchar* format, va_list args)</pre></font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strescape(gchar* string)</pre></font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strnfill(guint length, gchar fill_char)</pre></font> </td></tr></table></p><p> glib provides some convenient functions for concatenating strings, shown in Function Listing 2.6. <tt>g_strconcat()</tt> returns a newly-allocated string created by concatenating each of the strings in the argument list. The last argument must be <tt>NULL</tt>, so <tt>g_strconcat()</tt> knows when to stop. <tt>g_strjoin()</tt> is similar, but <tt>separator</tt> is inserted between each string. If <tt>separator</tt> is <tt>NULL</tt>, no separator is used.</p> <p><table bgcolor="#EEEEFF" width="100%"><caption><b>Function Listing 2.6:</b> Concatenating strings</caption><tr align="right"><td> <font color="black"> <tt>#include <glib.h></tt> </font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strconcat(const gchar* string1, ...)</pre></font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strjoin(const gchar* separator, ...)</pre></font> </td></tr></table></p><p> Finally, Function Listing 2.7 summarizes a few routines which manipulate <tt>NULL</tt>-terminated arrays of strings. <tt>g_strsplit()</tt> breaks <tt>string</tt> at each <tt>delimiter</tt>, returning a newly-allocated array. <tt>g_strjoinv()</tt> concatenates each string in the array with an optional <tt>separator</tt>, returning an allocated string. <tt>g_strfreev()</tt> frees each string in the array and then the array itself.</p> <p><table bgcolor="#EEEEFF" width="100%"><caption><b>Function Listing 2.7:</b> Manipulating <tt>NULL</tt>-terminated string vectors</caption><tr align="right"><td> <font color="black"> <tt>#include <glib.h></tt> </font> </td></tr><tr><td> <font color="black"><pre>gchar**g_strsplit(const gchar* string, const gchar* delimiter, gint max_tokens)</pre></font> </td></tr><tr><td> <font color="black"><pre>gchar*g_strjoinv(const gchar* separator, gchar** str_array)</pre></font> </td></tr><tr><td> <font color="black"><pre>voidg_strfreev(gchar** str_array)</pre></font> </td></tr></table></p><h2>2.2: Data Structures</h2><p> glib implements many common data structures, so you don't have to reinvent the wheel every time you want a linked list. This section covers glib's implementation of linked lists, sorted binary trees, N-ary trees, and hash tables.</p> <h3>2.2.1: Lists</h3><p> glib provides generic single and doubly linked lists, <tt>GSList</tt> and <tt>GList</tt>, respectively. These are implemented as lists of <tt>gpointer</tt>; you can use them to hold integers with the <tt>GINT_TO_POINTER</tt> and <tt>GPOINTER_TO_INT</tt> macros. <tt>GSList</tt> and <tt>GList</tt> have identical API's, except that there is a <tt>g_list_previous()</tt> function and no <tt>g_slist_previous()</tt>. This section will discuss <tt>GSList</tt> but everything also applies to the doubly linked list.</p> <p> In the glib implementation, the empty list is simply a <tt>NULL</tt> pointer. It's always safe to pass <tt>NULL</tt> to list functions since it's a valid list of length 0. Code to create a list and add one element might look like this:</p> <pre>GSList* list = NULL;gchar* element = g_strdup("a string");list = g_slist_append(list, element);</pre><p> glib lists have a noticeable Lisp influence; the empty list is a special "nil" value for that reason. <tt>g_slist_prepend()</tt> works much like <tt>cons</tt>---it's a constant-time operation that adds a new cell to the front of the list.</p> <p> Notice that you must replace the list passed to list-modifying functions with their return value, in case the head of the list changes. glib will handle memory issues, deallocating and allocating list links as needed.</p> <p> For example, the following code would remove the above-added element and empty the list:</p> <pre>list = g_slist_remove(list, element);</pre><p> <tt>list</tt> is now <tt>NULL</tt>. You still have to free <tt>element</tt> yourself, of course. To clear an entire list, use <tt>g_slist_free()</tt>, which removes all the links in one fell swoop. <tt>g_slist_free()</tt> has no return value because it would always be <tt>NULL</tt>, and you can simply assign that value to your list if you like. Obviously, <tt>g_slist_free()</tt> frees only the list cells; it has no way of knowing what to do with the list contents.</p> <p> To access a list element, you refer to the <tt>GSList</tt> struct directly:</p> <pre>gchar* my_data = list->data;</pre><p> To iterate over the list, you might write code like this:</p> <pre>GSList* tmp = list;while (tmp != NULL) { printf("List data: %p\n", tmp->data); tmp = g_slist_next(tmp); }</pre><p> Function Listing 2.8 shows the basic functions for changing <tt>GSList</tt> contents. For all of these, you must assign the return value to your list pointer in case the head of the list changes. Note that glib does <i>not</i> store a pointer to the tail of the list, so prepending is a constant-time operation, while append, insert, and remove are proportional to the list's size.</p> <p> In particular, this means that constructing a list using <tt>g_slist_append()</tt> is a <i>terrible</i> idea; use <tt>g_slist_prepend()</tt> and then call <tt>g_slist_reverse()</tt> if you need items in a particular order. If you anticipate frequently appending to a list, you can also keep a pointer to the last element. The following code can be used to perform efficient appends:</p> <pre>voidefficient_append(GSList** list, GSList** list_end, gpointer data){ g_return_if_fail(list != NULL); g_return_if_fail(list_end != NULL); if (*list == NULL) { g_assert(*list_end == NULL); *list = g_slist_append(*list, data); *list_end = *list; } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -