4_01_GLib库入门与实践_字符串

简介

字符串是一种非常常见的数据类型,为了便于操作字符串,GLib首先将字符串封装成类似C++ CString对象的一个结构体,又对字符串的一系列操作进行了封装,使用起来非常便捷,又避免了很多内存泄露的风险。
对非封装的简单字符串的处理见通用工具集章的字符串处理函数一节。

数据结构

struct GString {
  gchar  *str;  //数据,以null结尾,可以作为普通字符串使用
  gsize len;    //字符串长度,不包括null字节
  gsize allocated_len;  //在重新分配之前,本节点所能存储的最大内存长度。已分配内存长度。
};

函数列表

GString *	g_string_new ()
GString *	g_string_new_len ()
GString *	g_string_sized_new ()
GString *	g_string_assign ()
void	g_string_vprintf ()
void	g_string_append_vprintf ()
void	g_string_printf ()
void	g_string_append_printf ()
GString *	g_string_append ()
GString *	g_string_append_c ()
GString *	g_string_append_unichar ()
GString *	g_string_append_len ()
GString *	g_string_append_uri_escaped ()
GString *	g_string_prepend ()
GString *	g_string_prepend_c ()
GString *	g_string_prepend_unichar ()
GString *	g_string_prepend_len ()
GString *	g_string_insert ()
GString *	g_string_insert_c ()
GString *	g_string_insert_unichar ()
GString *	g_string_insert_len ()
GString *	g_string_overwrite ()
GString *	g_string_overwrite_len ()
GString *	g_string_erase ()
GString *	g_string_truncate ()
GString *	g_string_set_size ()
gchar *	g_string_free ()
GBytes *	g_string_free_to_bytes ()
GString *	g_string_up ()
GString *	g_string_down ()
guint	g_string_hash ()
gboolean	g_string_equal ()

函数功能分类

创建

GString *	g_string_new ()
GString *	g_string_new_len ()
GString *	g_string_sized_new ()

释放

gchar *	g_string_free ()
GBytes *	g_string_free_to_bytes ()

插入

GString *	g_string_append ()
GString *	g_string_append_c ()
GString *	g_string_append_unichar ()
GString *	g_string_append_len ()
GString *	g_string_append_uri_escaped ()
GString *	g_string_prepend ()
GString *	g_string_prepend_c ()
GString *	g_string_prepend_unichar ()
GString *	g_string_prepend_len ()
GString *	g_string_insert ()
GString *	g_string_insert_c ()
GString *	g_string_insert_unichar ()
GString *	g_string_insert_len ()

访问

GString->str;

格式化

void	g_string_vprintf ()
void	g_string_append_vprintf ()
void	g_string_printf ()
void	g_string_append_printf ()

覆盖

GString *	g_string_overwrite ()
GString *	g_string_overwrite_len ()

拷贝

GString *	g_string_assign ()

擦除

GString *	g_string_erase ()

截短

GString *	g_string_truncate ()

设置长度

GString *	g_string_set_size ()

大小写转换

GString *	g_string_up ()
GString *	g_string_down ()

哈希函数

guint	g_string_hash ()
gboolean	g_string_equal ()

函数功能说明及综合演示

GString字符串是一种内存随文本长度增加而自动增长的数据结构。其数据结构如下:

struct GString {
  gchar  *str;
  gsize len;
  gsize allocated_len;
};
  • str:实际存放的字符串,以’\0’结尾
  • len:字符串的实际长度,不包括结尾的’\0’
  • allocated_len:重新申请内存前分配的内存空间,如果存的字符比这个长度大,将会自动重新申请内存

由于GString包含一个len长度,因此str可以存任何字符,甚至是二进制数据。

创建和释放

创建相关的函数及简介:

//g_string_new将给定的init字符串拷贝到GString内,如果init为空,则创建出的GString是一个包含空字符串的变量。
GString * g_string_new (const gchar *init);

//将指定长度的数据拷贝到GString,由于指定了长度,init可以不以'\0'结尾,中间也允许包含空字符。
//由于本函数执行结束时不以遇到'\0'而结束,因此要求调用者保证init的实际总长度不应该小于len
GString * g_string_new_len (const gchar *init, gssize len);

//如果不想频繁重新申请内存,可以在创建时预留好字节大小。注意,此处已经预留了结尾空字符,如果我们dfl_size为256,则实际上分配的大小是512
GString * g_string_sized_new (gsize dfl_size);

释放相关的函数及简介:

//如果free_segment为TRUE,则内存会自动释放,如果free_segment为FALSE,则会返回字符串的地址,此时需要调用者自行释放内存。
gchar * g_string_free (GString *string, gboolean free_segment);

//将一个GString对象转换成GBytes对象,GString对象销毁,但其所指内存空间不会消失,需要在GBytes对象处自行释放。
GBytes * g_string_free_to_bytes (GString *string);

字符串创建和释放的示例代码如下:
源码见glib_examples\glib_gstring\glib_gstring_new_free

#include <glib.h>

gint main(gint argc, gchar **argv)
{
    GString *string1, *string2, *string3;
    char *str = NULL;
    GBytes *bytes = NULL;
    gconstpointer data = NULL;
    gsize size = 0;

    string1 = g_string_new("hello");
    string2 = g_string_new_len("hello", 3);
    string3 = g_string_sized_new(256);

    g_print("string1:%s, len:%d, allocated_len:%d \n", string1->str, (gint)string1->len, (gint)string1->allocated_len);
    g_print("string2:%s, len:%d, allocated_len:%d \n", string2->str, (gint)string2->len, (gint)string2->allocated_len);
    g_print("string3:%s, len:%d, allocated_len:%d \n", string3->str, (gint)string3->len, (gint)string3->allocated_len);

    str = g_string_free(string1, FALSE);
    g_print("str:%s \n", str);
    g_free(str);

    bytes = g_string_free_to_bytes(string2);
    data = g_bytes_get_data(bytes, &size);
    g_print("bytes: %s \n", (gchar *)data);
    g_bytes_unref(bytes);
    
    g_string_free(string3, TRUE);

    return 0;
}

运行结果:

string1:hello, len:5, allocated_len:8 
string2:hel, len:3, allocated_len:4 
string3:, len:0, allocated_len:512 
str:hello 
bytes: hel
插入和访问

插入
字符串插入函数有很多,可以分为头插、尾插和中间插入三大类。

// 字符串追加,如果GString内存不足,则会自动扩展
GString *	g_string_append ()
//追加一个字符
GString *	g_string_append_c ()
//Unicode转utf-8并存入GString,更多字符集转换见Unicode Manipulation
GString *	g_string_append_unichar ()
//将len个字节的长度追加到GString,val中可能包含空字符
GString *	g_string_append_len ()
GString *	g_string_prepend ()
GString *	g_string_prepend_c ()
GString *	g_string_prepend_unichar ()
GString *	g_string_prepend_len ()
GString *	g_string_insert ()
GString *	g_string_insert_c ()
GString *	g_string_insert_unichar ()
GString *	g_string_insert_len ()

访问
GString字符串的访问没有专门函数,可以直接访问其结构体成员变量
Gstring->str;

下面是插入和访问的代码示例:
源码见glib_examples\glib_gstring\glib_gstring_insert

#include <glib.h>

gint main(gint argc, gchar **argv)
{
    GString *string;
    gunichar wc = 0x007E;

    string = g_string_sized_new(256);

    g_string_append(string, "app");
    g_string_append_c(string, '\t');
    g_string_append_unichar(string, wc);
    g_string_append_len(string, "end", 3);

    g_string_prepend(string, "pend");
    g_string_prepend_c(string, '\\');
    g_string_prepend_unichar(string, wc);
    g_string_prepend_len(string, "pre", 3);

    g_string_insert(string, 4, "sert");
    g_string_insert_c(string, 4, '\'');
    g_string_insert_unichar(string, 4, wc);
    g_string_insert_len(string, 4, "in", 2);
    
    g_print("string: %s \n", string->str);

    g_string_free(string, TRUE);

    return 0;
}

运行结果:

string: pre~in~'sert\pendapp	~end

g_string_append_len不但可以处理字符串中间包含0字符问题,还可以处理只截取某一部分数据的情况,举例如下:
源码见`glib_examples\glib_gstring\glib_gstring_append_len

#include <glib.h>

gint main(gint argc, gchar **argv)
{
    GString *string;
    
    string = g_string_new ("firsthalf");
    
    g_print("original string: %s \n", string->str);

    g_string_append_len (string, "lasthalfjunkjunk", strlen ("lasthalf"));
    
    g_print("after append: %s \n", string->str);  // value is firsthalflasthalf

    g_string_free (string, TRUE);

    return 0;
}

运行结果:

original string: firsthalf
after append: firsthalflasthalf
格式化

格式化

void	g_string_printf ()
void	g_string_append_printf ()
void	g_string_vprintf ()
void	g_string_append_vprintf ()

g_string_printf,类似于sprintf,但不需要考虑内存越界问题。且如果原字符串有内容,则原内容会自动清空。
g_string_append_printf,和g_string_printf相似,但只是追加,不会清空原有内容。
g_string_vprintf、g_string_append_vprintf和前面两个类似,不过参数是var_args。
代码举例如下:
源码见glib_examples\glib_gstring\glib_gstring_printf

#include <glib.h>

static void _string_vprintf (GString *string, const gchar *format, ...)
{
  va_list args;

  va_start (args, format);
  g_string_vprintf (string, format, args);
  va_end (args);
}

static void _string_append_vprintf (GString *string, const gchar *format, ...)
{
  va_list args;

  va_start (args, format);
  g_string_append_vprintf (string, format, args);
  va_end (args);
}

gint main(gint argc, gchar **argv)
{
    GString *string;

    string = g_string_new("hello");

    g_print("string: %s \n", string->str);

    g_string_printf(string, "new str %s %d", "world", 100);

    g_print("printf string: %s \n", string->str);

    g_string_append_printf(string, "%s %s %d", "==", "append str", 200);

    g_print("append printf string: %s \n", string->str);

    _string_vprintf(string, "%s %d", "foo", 300);

    g_print("vprintf string: %s \n", string->str);

    _string_append_vprintf(string, "%s %d", "-append vprintf ", 400);

    g_print("append vprintf string: %s \n", string->str);

    g_string_free(string, TRUE);

    return 0;
}

运行结果:

string: hello 
printf string: new str world 100 
append printf string: new str world 100== append str 200 
vprintf string: foo 300 
append vprintf string: foo 300-append vprintf  400
覆盖-拷贝-擦除-截短-设置长度

覆盖

GString *	g_string_overwrite ()
GString *	g_string_overwrite_len ()
// 字符串覆盖,如果被覆盖的部分长度不够,则字符串所占内存会自动增加
// 如果带长度,还可以支持中间包括'\0'字符的字符串覆盖

拷贝

GString *	g_string_assign ()
// 将一个char*类型的字符串拷贝到GString中,如果字符串原来有内容,则原有内容会被清空,再进行拷贝操作,本函数与strcpy类似,但不必担心空间不足问题

擦除

GString *	g_string_erase ()
// 擦除从pos位置开始的len个字符,后面的字符前移

截短

GString *	g_string_truncate ()
// 按照指定长度截短字符串,如果len大于实际长度,则字符串仍为实际长度,如果len为0,则相当于清空字符串

设置长度

GString *	g_string_set_size ()
// 设置GString长度,如果len小于目前长度,则GString会被截断,如果大于当前长度,则新增加的内存内容不确定。

覆盖-拷贝-擦除-截短-设置长度代码演示程序:
源码见glib_examples\glib_gstring\glib_gstring_multi

#include <glib.h>

gint main(gint argc, gchar **argv)
{
    GString *string;

    string = g_string_new("hello");
    g_print("ori string: %s \n", string->str);

    g_string_overwrite(string, 1, "aaa");
    g_print("overwrite(1) string: %s \n", string->str);

    g_string_overwrite_len(string, 1, "a\0a", 3);
    g_print("overwrite_len(1,3)string(len:%d): %s \n", (gint)string->len, string->str);

    g_string_printf(string, "%s", "aabbccdd");
    g_string_assign(string, "abcd");
    g_print("assign string(len:%d): %s \n", (gint)string->len, string->str);

    g_string_truncate(string, 2);
    g_print("truncate(2) string(len:%d): %s \n", (gint)string->len, string->str);

    g_string_truncate(string, 0);
    g_print("truncate(0) string(len:%d): %s \n", (gint)string->len, string->str);

    g_string_printf(string, "%s", "aabbccdd");
    g_string_erase(string, 2, 4);
    g_print("erase(2,4) string(len:%d): %s \n", (gint)string->len, string->str);

    g_string_truncate(string, 0);
    g_print("truncate(0) string(len:%d): %s \n", (gint)string->len, string->str);
    g_string_set_size(string, 8);
    g_print("set_size(8)string(len:%d): %s \n", (gint)string->len, string->str);

    g_string_free(string, TRUE);

    return 0;
}

运行结果:

ori string: hello 
overwrite(1) string: haaao 
overwrite_len(1,3)string(len:5): ha 
assign string(len:4): abcd 
truncate(2) string(len:2): ab 
truncate(0) string(len:0):  
erase(2,4) string(len:4): aadd 
truncate(0) string(len:0):  
set_size(8)string(len:8): 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值