一、将最近用到的glib字符串功能整理了下直接用程序记录比较好看懂

#define MAX_LEN 100
gchar * demo (char* msg, ...)
{
    gchar * pcfgfile = NULL,* para = NULL;
    va_list argp;
    va_start(argp,msg);//msg其实指的是第一个参数,这个函数是让argp指向demo实参的栈底,参数是按从右往左的顺序压入栈的,argp不包含msg
    pcfgfile = g_strdup_vprintf("%s %s %s %d",argp);
    va_end(argp);
    return pcfgfile;
}
int main(void){
    gchar * pfilename = "houjiao";
    gchar * strdouble = "11.11";
    gchar * strint = "123456;8910";
    gchar *test_str = NULL,* hj = NULL;
    gint len = 0;
    gchar buff_str[MAX_LEN+1];
    guint64 imsi = 123456789;
    gdouble test_duble = 0.0;
    gchar **str_array = NULL;

//----------------------------------------------------------一 ------------------------------------------------------------------------
    //下面的这些函数会返回一个新的字符串缓冲区的指针,所以你在使用完后必须要释放它们。
    //--------------------------------------------------------------------------------------------------------------------------------------
    /*
    gchar *g_strdup(const gchar *str)
    复制str并返回它的一个拷贝。并非返回原来字符串的指针而是重新申请一块内存将其指针返回。*/
    hj = g_strdup(pfilename);
    test_str = g_strdup(hj);
    g_free(hj);
    hj = NULL;
    g_print("%s\n",test_str); //输出good

    /*
    gchar *strnfill(gsize length, gchar *fill_char)
    创建一个长度为length并被fill_char填充的字符串。如果fill_char为0则创建一个空字符串 */
    test_str = g_strnfill(10,0);
    g_print("%s\n",test_str);
    g_free(test_str);
    test_str = NULL;

    /*
    gchar *g_strdup_printf(const gchar *format, ...)
    像sprintf()一样格式化字符串和参数。但是,你没必要像sprintf()一样创建和指定一个缓冲区,GLib将这些自动做了。适合用于字符串拼 */
    test_str = g_strdup_printf("%s_%u",pfilename,1);
    g_print("%s\n",test_str);

    /*测试g_strdup_vprintf的拼接功能 类似上面g_strdup_printf函数的功能*/
    test_str = demo("","hj","is","number",1);//输出this is a demo!
    g_print("%s\n",test_str);
    g_free(test_str);
    test_str = NULL;

    /*
    gchar *g_strconcat(const gchar *string1, ..., NULL)
    它接受任意数量的string作为参数,并返回它们的连接后的字符串。必须将NULL作为这个函数的最后一个参数 */
    hj = g_strdup(pfilename);
    test_str = g_strconcat("   ",hj,":","good person",NULL);//输出   houjiao:good person
    g_print("%s\n",test_str);
    g_free(test_str);
    test_str = NULL;

//----------------------------------------------------------二 ------------------------------------------------------------------------
    //在下面的函数中,你应该为返回的结果申请空间。GLib并不会返回一个拷贝给你。它们与C相对应的函数非常像,参数要包含一个足够大的缓冲区来进行字符串处理。
    //--------------------------------------------------------------------------------------------------------------------------------------
    /*
    gchar *g_stpcpy(gchar *dest, const gchar *src)
    拷贝src到dest,包括最后的NULL字符。如果它执行成功,会返回dest中结束符拷贝的指针。*/
    test_str = (gchar *)g_malloc0(strlen(hj));
    g_stpcpy(test_str,hj);//函数返回的是结束符拷贝的指针这里即返回空字符串
    g_print("%s\n",test_str);//输出,good
    g_slice_free1(strlen(hj),test_str);
    test_str = NULL;

    /*
    gint g_snprintf(gchar *string, gulong n, const gchar *format, ...)
    你必须确保string有足够大的空间。而且你必须要用n来指定这个缓冲区的大小。返回值是输出字符串的长度,也有可能这个输出字符串为了适应缓冲区的大小而被截断 */
    len += g_snprintf(buff_str+len,MAX_LEN-len,"%d,%d,%d,%"G_GINT64_FORMAT"",1,2,3,imsi);
    g_print("%s\n",buff_str);//输出1,2,3,123456789

    /*测试g_strchug删除字符串开始的空格*/
    test_str = g_strconcat("   ",hj,":","good person     ",NULL);
    test_str = g_strchug(test_str);//输出houjiao:good person     光标在这
    g_print("%s\n",test_str);

    /*
    gchar *g_strchomp(gchar *string)
    将string结尾的空格都删掉,返回string */
    test_str = g_strchomp(test_str);
    g_print("%s\n",test_str);//houjiao:good person
    g_free(test_str);
    test_str = NULL;

    /*
    gchar *g_strstrip(gchar *string)
    将string开头和结尾的空白字符都删掉,返回string。*/
    test_str = g_strconcat("   ",hj,":","good person     ",NULL);
    test_str = g_strstrip(test_str);
    g_print("%s\n",test_str);//输出houjiao:good person

    /*
    gchar *g_strdelimit(gchar *string, const gchar *delimiters, gchar *new_delimiter)
    将string中的delimiters各个字符都替换为new_delimiter这一个字符 */
    test_str = g_strdelimit(test_str,"good",'a');
    g_print("%s\n",test_str);//haujiaa:aaaa persan
    g_free(test_str);
    test_str = NULL;

    //----------------------------------------------------------三、 ------------------------------------------------------------------------
    //在下面的函数中,除了g_ascii_dtostr()之外,都不改变它们的参数。
    //--------------------------------------------------------------------------------------------------------------------------------------
    
    /*
    gchar *g_strstr_len(const gchar *haystack, gssize haystack_len, const gchar *needle)
    在haystack中遍历haystack_len长度,如果找到了needle字串,则返回这个位置的指针,如果没有找到则返回NULL。*/
    test_str = g_strstr_len(pfilename,strlen(pfilename),"jia");
    g_print("%s\n",test_str);//输出jiao
    test_str = NULL;

    /*  
    gchar *g_strrstr(const gchar *haystack, const gchar *needle)
    类似于g_strstr_len,这个函数将会从后面开始查找,但是它并没有haystack_len参数。 */
    test_str = g_strrstr(pfilename,"jia");
    g_print("%s\n",test_str);//输出jiao
    test_str = NULL;

    /*
    gchar *g_strrstr_len(gchar *haystack, gssize haystack_len, gchar *needle)
    与g_strrstr()相同,但是它只在前haystack_len个字符中查找,第二个参数是-1表示在整个字符串中找*/
    test_str = g_strrstr_len(pfilename,-1,"a");
    g_print("%s\n",test_str);
    test_str = g_strrstr_len(pfilename,5,"a");
    g_print("%s\n",test_str);//输出(null)

    /*
    gdouble g_ascii_strtod(const gchar *nptr, gchar **endptr)
    将string转为双字长度的浮点数。如果你提供了一个有效的endptr指针地址,这个函数会将指针设置到string中被转换的最后一个字符的位置*/
    test_duble = g_ascii_strtod(strdouble,NULL);
    g_print("%.2f\n",test_duble);//输出11.11

    /*
    gchar **g_strsplit(const gchar *string, const gchar *delimiter, gint max_tokens)
    使用delimiter来将string切割成至多max_tokens个部分。返回值是新申请的一个字符串数组,用来保存被切割的这些部分。
    这个字符串数组必须由你自己释放。 如果输入字符串是空的,这个返回值也是一个空的数组。 该法不改变原string */
    str_array = g_strsplit(strint,";",3);
    g_print("%s,%s\n",str_array[0],str_array[1]);//123456,8910
    
    /*
    gchar *g_str_joinv(const gchar *separator, gchar **str_array)
    将字符串数组组合成单个字符串,并将这个新申请的字符串返回。如果separator不空,g_str_joinv()会在每个字符串之间添加上一个separator分隔符。*/
    test_str = g_strjoinv(",",str_array);
    g_print("%s\n",test_str);//123456,8910    
    g_strfreev(str_array);
    str_array = NULL;
    g_free(test_str);
    test_str = NULL;

    /*测试g_ascii_strtoll将字符串转成对应整形的功能第三个参数是指的几进制*/
    test_str =strchr(strint,';');
    len = (gint)g_ascii_strtoll(strint,NULL,10);
    g_print("%d\n",len);//输出123456
    strint = test_str +1;
    len = (gint)g_ascii_strtoll(strint,NULL,10);
    g_print("%d\n",len);//输出8910
    g_free(test_str);
    test_str = NULL;
    return TRUE;
}
二、glib的主循环功能主要是为了看看主循环的串行

/*
自定义的事件源是一个继承 GSource 的结构体,即自定义事件源的结构体 的第一个成员是 GSource 结构体, 其后便可放置程序所需数据, 例如:*/
typedef struct _MySource MySource;
struct _MySource
{
    GSource source;
    gchar text[256];
};
/*
实现了事件源数据结构的定义之后,还需要实现事件源所规定的接口,主要为 prepare, check, dispatch, finalize 等事件处理函数(回调函数),它们包含于 GSourceFuncs 结构体中。
将 GSourceFuncs 结构以及事件源结构的存储空间宽度作为参数传给 g_source_new 便可构造一个新的事件源,继而可使用 g_source_attach 函数将新的事件源添加到主循环上下文中
*/
static gboolean prepare(GSource *source, gint *timeout)
{
    *timeout = 0;

return TRUE;
}

static gboolean check(GSource *source)
{
    return TRUE;
}

static gboolean dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
{
    int i = 0;
    MySource *mysource = (MySource *)source;

for (;i<6;i++)
    {
        g_print("%s%d\n", mysource->text,i);
    }

return TRUE;
}
/*
g_main_loop_run 函数运行时,会迭代访问 GMainContext 的事件源列表,步骤大致如下:
a. g_main_loop_run 通过调用事件源的 prepare 接口并判断其返回值以确定各事件源是否作好准备。如果各事件源的 prepare 接口的返回值为 TRUE,即表示该事件源已经作好准备,否则表示尚未做好准备。显然,上述程序所定义的事件源是已经作好了准备。
b. 若某事件源尚未作好准备 ,那么 g_main_loop 会在处理完那些已经准备好的事件后再次询问该事件源是否作好准备 ,这一过程是通过调用事件源的 check 接口而实现的,如果事件源依然未作好准备,即 check 接口的返回 FALSE,那么 g_main_loop_run 会让主事件循环进入睡眠状态。
主事件循环的睡眠时间是步骤 a 中遍历时间源时所统计的最小时间间隔 ,例如在 prepare 接口中可以像下面这样设置时间间隔。到达一定时间后, g_main_loop_run 会唤醒主事件循环,再次询问。如此周而复始,直至事件源的 prepare 接口返回值为 TRUE。*/
int main1(void)
{
    GMainLoop *loop = g_main_loop_new(NULL, TRUE);
    GMainContext *context = g_main_loop_get_context(loop);
    GSourceFuncs source_funcs = {prepare, check, dispatch, NULL};
    GSource *source = g_source_new(&source_funcs, sizeof(MySource));

g_sprintf(((MySource *)source)->text, "Hello world");

g_timeout_add(100, timeout_func, loop);
    g_source_attach(source, context);
    g_source_unref(source);

g_main_loop_run(loop);

g_main_context_unref(context);
    g_main_loop_unref(loop);

return 0;
}
/*
该函数执行结果是大致上可以看出来事件源是串行的即单线程
*/
三、glib的xml解析功能顺便使用简单的回调函数

//程序功能:使用回调函数的方式调用xml和txt两种文件的读取函数。
xml文件里面的内容如下
<?xml version="1.0" encoding="UTF-8"?>
  <NM id="15009244480" name="houjiao">
      <title>name ege sex what emotion</title>
        <v>hq 24 female friend love</v>
        <v>ld 24 female friend love</v>
        <v>wj 25 female friend love</v>
        <v>wff 25 female friend love</v>
  </NM>
txt文件里面内容如下
hq is 24 years older,and she is my friend.
ld is 24 years older,and she is my friend.
wj is 25 years older,and she is my friend.
wff is 25 years older,and she is my friend.
然后程序如下,注释已经很清晰了

#include "glib.h"
#include "string.h"
#include "stdio.h"
//定义函数指针即回调函数的类型
typedef gboolean (*CallBackFileRead)(gchar *);
typedef struct _FriendNode
{
    gchar * myname;
    gchar * hername;
    gchar * what;
    gchar * emotion;
    guint8 ege;
    guint64 tel_id;
    gboolean txt_pasre_flag;
}FriendNode;

/*当遇到元素开始时,将其属性名全存到attribute_name数组中,对应的属性值存入value_cursor数组中,所以属性名和属性值是同时++然后就会取到下一个属性直到取完*/
static void start( GMarkupParseContext * context,
                  const gchar * element_name,
                  const gchar * * attribute_names,
                  const gchar * * attribute_values,
                  gpointer user_data,
                  GError * * error )
{
    const gchar * * name_cursor = attribute_names;
    const gchar * * value_cursor = attribute_values;
    FriendNode * friend_node =(FriendNode *)user_data ;
    if (g_strcmp0(element_name,"v") == 0)
    {    
        friend_node->txt_pasre_flag = TRUE;        
    }
    else if (g_strcmp0(element_name,"NM") == 0)
    {
        while (*name_cursor)
        {
            if (g_strcmp0(*name_cursor, "id") == 0)
            {
                friend_node->tel_id = (guint64)g_ascii_strtoull(*value_cursor,NULL,10);

}
            else if (g_strcmp0(*name_cursor, "name") == 0)
            {
                friend_node->myname = g_strdup (*value_cursor);
            }
            name_cursor++;
            value_cursor++;
        }
        g_print("My name is %s,my telphone num is %"G_GUINT64_FORMAT" \n",friend_node->myname,friend_node->tel_id);
    }
}
//一个元素结束时调用,一般可以在你想要取值的元素设置标记。
static void end( GMarkupParseContext * context,
                const gchar * element_name,
                gpointer user_data,
                GError * * error )
{
    FriendNode * friendnode = (FriendNode*)user_data;
    if (g_strcmp0(element_name,"v") == 0)
    {
        friendnode->txt_pasre_flag = FALSE;
    }
}

//一般xml里面要取得最重要的是内容,因此按照内容格式不同,拆分字符串的方式不同。
static void text( GMarkupParseContext * context,
                 const gchar * text,
                 gsize text_len,
                 gpointer user_data,
                 GError * * error )
{
    const gchar * s = text;
    gchar * ss = NULL;
    int i=0;    //列索引
    FriendNode * friendnode = (FriendNode *)user_data;

if (friendnode->txt_pasre_flag)
    {
        while ((ss = strchr((gchar *)s,' ')) && i<=3)
        {
            switch (i)
            {
            case 0:                
                friendnode->hername = g_strndup(s,ss-s);
                break;
            case 1:
                friendnode->ege =(gint8)g_ascii_strtoull(s,NULL,10);
                break;
            case 3:                
                friendnode->what = g_strndup(s,ss-s);
                break;

default:
                break;
            }
            s = ss + 1;
            i++;
        }
        if (i == 4)
        {
            friendnode->emotion =g_strdup(s);
        }
        g_print("%s is %d years older,and she is my %s who I %s\n",friendnode->hername,friendnode->ege,friendnode->what,friendnode->emotion);
        g_free(friendnode->hername);
        g_free(friendnode->what);
        g_free(friendnode->emotion);
    }
}
//xml解析类回调函数的实现
gboolean ReadXmlFile(gchar * filename){
    GMarkupParser gparser = {0};               //GMarkup解析器
    GMarkupParseContext *gparsecontext = NULL; //GMarkup解析上下文
    FriendNode friend_node = {0};
    char * buf;
    gsize length;
    /*创建解析器上下文第三个参数是用来传给 GMarkupParser解析器函数即start,text和end里面用的 */
    gparsecontext = g_markup_parse_context_new(&gparser,(GMarkupParseFlags)0, &friend_node, NULL);

if (gparsecontext == NULL)
    {
        return FALSE;
    }
    /*给gparser的函数指针赋值*/
    gparser.start_element = start;
    gparser.text = text;
    gparser.end_element =end;

    /* g_file_get_contents(const gchar *filename,gchar **contents,gsize *length,GError **error);
    是用于将文件的内容读入到一个buf中,length是用来存储字符串长度的变量可设为null,读取成功返回ture读取失败返回false和最后一个参数 */
    if ((FALSE == g_file_get_contents(filename, &buf, &length,NULL)))
    {
        return FALSE;
    }

    /*开始解析buf里面的字符串,调用gparser的三个函数,xml文件里面一个元素包括,元素名,属性值和元素内容,一个元素的start标志为:<元素名[属性]>,元素的end标志为:</元素名> 包含在元素开始和元素结束之间的变是该元素的text*/
    if (g_markup_parse_context_parse(gparsecontext, buf, length, NULL) == FALSE)
    {
        g_message("load xml file failed!");
        g_free(buf);
        g_markup_parse_context_free(gparsecontext);
        gparsecontext = NULL;
        return FALSE;
    }
}
//csv解析类回调函数实现
gboolean ReadTxtFile(gchar * filename){
    FILE * ftxt_file = NULL;
    gchar buf[100] = {'\0'};
    if (fopen_s(&ftxt_file,filename,"rb") != 0)
    {
        g_print("open file error");
        return FALSE;
    }
    //fgets遇到文件结束或读取错误时返回null
    while(fgets(buf, 100, ftxt_file))
    {
       g_print("%s",buf);
    }
    fclose(ftxt_file);
    return TRUE;
}

void XmlTxtParseCallBack(gchar* filename, CallBackFileRead pFun)  //模拟API函数  
{
    //回调解析文件类函数
    if (!pFun(filename))
    {
        g_print("parse error");
    }
}
//1.在main中的XmlTxtParseCallBack接口函数调用了回调函数,当然xml解析和txt解析的两个函数可以像普通函数一样被调用,但是当它作为参赛传递给被调函数时就称为回调函数了。
//2.回调函数实际上就是在调用某个函数(通常是API函数时),将自己的一个函数(这个函数叫回调函数)的地址作为参数传递给那个函数,那个函数在需要的时候利用传递的地址调用回调函数,这种模式很适合异步模块之间的调用。
//3.用计算机原理来说,回调函数就是一个中断处理函数,由系统在符合你设定条件时自动调用,你要做的只有三步,一声明回调函数类型,二实现回调函数,三,设置触发条件(即把你的回调函数名转化为函数指针作为参数用于调用)。
int main()
{
    gchar * filename = "F:\\test\\input\\hj.txt";
    if (g_str_has_suffix(filename,".xml"))
    {
        XmlTxtParseCallBack(filename,ReadXmlFile);
    }
    else if (g_str_has_suffix(filename,".txt"))
    {
        XmlTxtParseCallBack(filename,ReadTxtFile);
    }
    else
    {
        g_print("can't parse this file type");
    }
    return 0;

}

执行结果是:

当filename是**hj.txt时,

当file那么是**hj.xml时,

over,glib待续。。。

glib简单记录包括字符串,主循环,回调函数和xml解析的更多相关文章

  1. RCF的简单使用教程以及什么是回调函数

    RCF的使用教程 RCF(Remote Call Framework)是一个使用C++编写的RPC框架,在底层RCF支持多种传输实现方式(transport implementations). 包括T ...

  2. android中回调函数机制完全解析

    1.在要调用的业务操作中,创建一个接口,在接口中创建方法,这个方法表示的是我们原先要在业务类中执行的操作 public interface BackUpSmsListener { /** * 设置总进 ...

  3. Cocos2d-x 3.2 学习笔记(十六)保卫萝卜 游戏主循环与定时器

    保卫萝卜~想法一直存在于想法,实战才是硬道理!有想法就去实现,眼高手低都是空谈.   一.游戏主循环GameSchedule      主循环是游戏处理逻辑,控制游戏进度的地方,处理好主循环是很重要的 ...

  4. libevent源码学习(13):事件主循环event_base_loop

    目录开启事件主循环执行事件主循环校对时间 阻塞/非阻塞处理激活队列中的event事件主循环的退出event_base_loopexitevent_base_loopbreak开启事件主循环       ...

  5. wxWidgets源码分析(2) - App主循环

    目录 APP主循环 MainLoop 消息循环对象的创建 消息循环 消息派发 总结 APP主循环 MainLoop 前面的wxApp的启动代码可以看到,执行完成wxApp::OnInit()函数后,接 ...

  6. jQuery 源码解析(八) 异步队列模块 Callbacks 回调函数详解

    异步队列用于实现异步任务和回调函数的解耦,为ajax模块.队列模块.ready事件提供基础功能,包含三个部分:Query.Callbacks(flags).jQuery.Deferred(funct) ...

  7. 理解和使用 JavaScript 中的回调函数

    理解和使用 JavaScript 中的回调函数 标签: 回调函数指针js 2014-11-25 01:20 11506人阅读 评论(4) 收藏 举报  分类: JavaScript(4)    目录( ...

  8. 关于js的callback回调函数的理解

    回调函数的处理逻辑理解:所谓的回调函数处理逻辑,其实就是先将回调函数的代码 冻结(或者理解为闲置),接着将这个回调函数的代码放到回调函数管理器的队列里面. 待回调函数被触发调用的时候,对应的回调函数的 ...

  9. 理解javascript中的回调函数(callback)【转】

    在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Object类的对象一样用于内置对象的管理.因为function实 ...

随机推荐

  1. ci框架简单出现的错误[Undefined property: MContacts::$db]

    出现这样的错误时说明自己忘记加载数据库了, application/config/aotuload.php     $autoload['libraries'] = array('database') ...

  2. 如果输入参数采用“指针传递”,那么加 const 修饰可以防止意外地改动该指针,起 到保护作用

    如果输入参数采用“指针传递”,那么加 const 修饰可以防止意外地改动该指针,起 到保护作用. #include <iostream> /* run this program using ...

  3. Unity获取文件夹下指定类型的文件数量

    有个文件夹里面有很多的图片,都是.png格式的,要是一个一个的拖到脚本上觉得很麻烦,就写了一个遍历添加的cars,变量是List<Sprite> 代码如下: using UnityEngi ...

  4. PHP的只是结构图

  5. HDU2586.How far away ?——近期公共祖先(离线Tarjan)

    http://acm.hdu.edu.cn/showproblem.php?pid=2586 给定一棵带权有根树,对于m个查询(u,v),求得u到v之间的最短距离 那么仅仅要求得LCA(u,v),di ...

  6. JQuery------实现点击左右按钮,切换图片功能

    如图: 代码: html @*商品主图片*@ <div class="product-img" style="display:table-cell;width:40 ...

  7. Android之MessageQueue、Looper、Handler与消息循环

    在android的activity中有各种各样的事件,而这些事件最终是转换为消息来处理的.android中的消息系统涉及到: *  消息发送 *  消息队列 *  消息循环 *  消息分发 *  消息 ...

  8. 在用VMware虚拟机的时候,有时会发现打开虚拟机时提示“该虚拟机似乎正在使用中。如果该虚拟机未在使用,请按“获取所有权(T)”按钮获取它的所有权。否则,请按“取消(C)”按钮以防损坏。配置文件: D:\win10x64\Windows 10 x64.vmx。”这是由于虚拟机未正常关闭引起的,下面看看解决办法

    我们首先点击“获取所有权(T)”按钮,会发现弹出一个窗口,显示“ 无法打开虚拟机: D:\win10x64\Windows 10 x64.vmx获取该虚拟机的所有权失败.主机上的某个应用程序正在使用该 ...

  9. Django学习笔记第二篇--关于请求获取

    #细节都在代码段里面讲解 零.绪论: HTTP协议是一种请求响应的协议,一次请求一次响应.所以这部分的讲解将分为三个部分:请求获取,分析处理.返回响应. 一.获取请求数据: 1.POST和GET类型 ...

  10. 【BZOJ4598】[Sdoi2016]模式字符串 树分治+hash

    [BZOJ4598][Sdoi2016]模式字符串 Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每 ...