文档章节

argz_create_sep函数

微笑不知慌张
 微笑不知慌张
发布于 2015/09/29 20:53
字数 1022
阅读 87
收藏 2

函数位于glibc源码中的../glibc-version/string/argz-ctsep.c中,其作用是将字符串以指定的字符进行分割,指定字符的位置替换成空字符串(\0),使整个字符串形成一个argz vector。

argz vector是存储在连续空间的一维字符数组,彼此之间以空字符(\0)进行分隔。

也就是说argz_create_sep函数的目的是将一个字符串按指定字符分割成多个字符串,存入一个连续空间中,彼此之间以空字符(\0)进行分隔,形成argz vector。

假如待分割字符串为“argz_create_sep”,以r作分割符,得到的argz vector应当如下所示:

函数声明如下:

// argz.h
/* Make a '\0' separated arg vector from a SEP separated list in
   STRING, returning it in ARGZ, and the total length in LEN.  If a
   memory allocation error occurs, ENOMEM is returned, otherwise 0.
   The result can be destroyed using free.  */
extern error_t __argz_create_sep (const char *__restrict __string,
								int __sep, char **__restrict __argz,
								size_t *__restrict __len) __THROW;
extern error_t argz_create_sep (const char *__restrict __string,
								int __sep, char **__restrict __argz,
								size_t *__restrict __len) __THROW;
/* */

函数的实现如下:

error_t
__argz_create_sep (const char *string, int delim, char **argz, size_t *len)
{
    size_t nlen = strlen (string) + 1;
    if (nlen > 1)
    {
        const char *rp;
        char *wp;
        *argz = (char *) malloc (nlen);
        if (*argz == NULL)
            return ENOMEM;
        rp = string;
        wp = *argz;
        do
            if (*rp == delim)
            {
                if (wp > *argz && wp[-1] != '\0')
                    *wp++ = '\0';
                else
                    --nlen;
            }
            else
                *wp++ = *rp;
        while (*rp++ != '\0');
        if (nlen == 0)
        {
            free (*argz);
            *argz = NULL;
            *len = 0;
        }
        *len = nlen;
    }
    else
    {
        *argz = NULL;
        *len = 0;
    }
    return 0;
}
weak_alias (__argz_create_sep, argz_create_sep)
/* */

代码相对比较简单,逐字符进行复制,遇到与delim相同的就替换成\0,然后继续复制。

需要注意的是如果待分割的字符串中存在连续的delim,那么形成的argz vector中该部分字符串只有一个\0,同时len也会相应的减小。完成这个操作的是下面这段代码,它主要是针对这类特殊情况的处理(假设以s进行分割)。

1、待分割字符串string的第一个字符就是delim相同(如:string Microsoft)

2、待分割字符串string中存在连续个delim(如:string Microsssoft,或者ssssssssss)

if (wp > *argz && wp[-1] != '\0')
    *wp++ = '\0';
else
    --nlen;
/* */

 

 调用__argz_create_sep函数的方式为:

const char *mystring = "string microsoft";
char delim = 's';
__argz_create_sep(mystring, delim, &argz, &len);
/* */

 

写个程序测试一下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ENOMEM  12
#define MYLEN   4
#ifndef __error_t_defined
typedef int error_t;
#endif
error_t __argz_create_sep (const char *string, int delim, char **argz, size_t *len)
{
    size_t nlen = strlen(string) + 1;
    if (nlen > 1)
    {
        const char *rp;
        char *wp;
        *argz = (char *) malloc (nlen);
        if (*argz == NULL)
            return ENOMEM;
        rp = string;
        wp = *argz;
        do
            if (*rp == delim)
            {
                if (wp > *argz && wp[-1] != '\0')
                    *wp++ = '\0';
                else
                    --nlen;
            }
            else
                *wp++ = *rp;
        while (*rp++ != '\0');
        if (nlen == 0)
        {
            free (*argz);
            *argz = NULL;
            *len = 0;
        }
        *len = nlen;
    }
    else
    {
        *argz = NULL;
        *len = 0;
    }
    return 0;
}
int main(void)
{
    int i, j;
    size_t len[MYLEN];
    char *argz[MYLEN];
    char *testString[MYLEN] = {
        "function  converts the argz",
        "tfunction converts the argz",
        "tttttttt",
        ""
    };
    /* 以t作分割符 */
    for(i=0; i<MYLEN; ++i){
        __argz_create_sep(testString[i], 't', &argz[i], &len[i]);
    }
	
    for(i=0; i<MYLEN; ++i)
    {
        printf("NO.%d, lenght: %d\n+", i, len[i]);
        for(j=0; j<len[i]; ++j){
            putchar('-');
        }
        printf("+\n|");
        for(j=0; j<len[i]; ++j){
            putchar(argz[i][j]);
        }
        printf("|\n+");
        for(j=0; j<len[i]; ++j){
            putchar('-');
        }
        printf("+\n\n");
    }
    for(i=0; i<MYLEN; ++i){
        if(argz[i]){
		free(argz[i]); argz[i]=NULL;
	}
    }
    return 0;
}

 程序输出如下:

 注意,输出结果中argz vector的字符串之间的“空格”并不是空格,而是\0的输出但是这个字符没法显示的结果。

 

附:我觉得那个函数写的太蛋疼了。。果然我还是喜欢用for啊。。。

error_t __argz_create_sep (const char *string, int delim, char **argz, size_t *len)
{
	size_t nlen = strlen (string) + 1;
	const char *rp;
	char *wp;
	if(nlen <= 1)
	{
		*argz = NULL;
		*len = 0;
		return 0;
	}
	*argz = (char *) malloc (nlen);
	if (*argz == NULL)	return ENOMEM;
	for(rp = string, wp = *argz; *rp; ++rp)
	{
		if(*rp == delim)
		{
			if(wp > *argz && wp[-1] != '\0'){
				*wp++ = '\0';
			}
			else{
				--nlen;
			}
		}
		else{
			*wp++ = *rp;
		}
	}
	if (nlen == 0)
	{
		free (*argz);
		*argz = NULL;
	}
	*len = nlen;
	return 0;
}

现在是2017年4月14日,看到以前写的这一段内容,仔细思考了一下,果然还是源码厉害。for并不能完全的处理由delim组成的字符串。如string="ssss", delim='s',当处理到最后一个字符时,源码很可靠的让nlen=1,并且argz[0]='\0'。但是我上面那个用for写的,则没有处理argz[0]='\0',直接导致argz中len=1,但是却什么都没有。

© 著作权归作者所有

上一篇: argz_count()函数
下一篇: argz_create函数
微笑不知慌张
粉丝 1
博文 7
码字总数 3082
作品 0
西安
私信 提问
argz_create函数

函数位于glibc源码中的../glibc-version/string/argz-create.c中,其作用是将Unix-style的参数数组argv转换成一个argz vector。 argz vector是存储在连续空间的一维字符数组,彼此之间以空字...

微笑不知慌张
2015/09/29
191
0
argz_extract()函数,argz_stringify()函数

函数分别位于glibc源码中的../glibc-version/string/argz-extract.c和../glibc-version/string/argz-stringify.c中。 函数声明如下: // argz.h /* Puts pointers to each string in ARGZ in......

微笑不知慌张
2015/10/07
80
0
argz_count()函数

函数位于glibc源码中的../glibc-version/string/argz-cout.c中,其作用统计一个argz vector中元素(字符串)的个数。 argz vector是存储在连续空间的一维字符数组,元素(字符串)彼此之间以...

微笑不知慌张
2015/10/07
12
0
tomcat7 jdk7 ubuntu tomcat经常报下面的异常,什么原因?

log4j:WARN No appenders could be found for logger (org.springframework.web.context.support.XmlWebApplicationContext). log4j:WARN Please initialize the log4j system properly. log......

7哥
2015/09/28
630
2
oracle FIND_IN_SET函数

create or replace FUNCTION FINDINSET(pivstr1 varchar2, pivstr2 varchar2, p_sep varchar2 := ';') RETURN NUMBER IS lidx number:=0; -- 用于计算pivstr2中分隔符的位置 str varchar2(5......

诗和_远方
2018/07/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

你知道多少this,new,bind,call,apply?那我告诉你

那么什么是this,new,bind,call,apply呢?这些你都用过吗?掌握这些内容都是基础中的基础了。如果你不了解,那还不赶快去复习复习,上网查阅资料啥的! 通过call,apply,bind可以改变thi...

达达前端小酒馆
今天
4
0
设计模式之命令模式

命令模式的类图 其中的角色有: Client 客户端。只依赖于调用者Invoker、接收者Receiver、以及Command(网上找的图片这里没有画出来),不用关注接收者如何执行命令,只需要告诉调用者需要执行...

陈年之后是青葱
今天
7
0
2. 彤哥说netty系列之IO的五种模型

你好,我是彤哥,本篇是netty系列的第二篇。 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识。 简介 本文将介绍linux中的五种IO模型,同时也会介绍阻塞/非阻塞与同步/异步的区别。 何...

彤哥读源码
今天
5
0
OSChina 周四乱弹 —— 喵的波粒二象性

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @ 小小编辑推荐:《水墨兰亭》- 李志辉 《水墨兰亭》- 李志辉 手机党少年们想听歌,请使劲儿戳(这里) @巴拉迪维 :卧室里采光要足够好,这样...

小小编辑
今天
34
1
前后端分离接口规范

最近在开发,遇到前后端关于Boolean类型的参数传参和接收的问题: 场景:后台会根据用户是否出车/是否出司机(Boolean类型)来决定后端的业务逻辑(比如费用的计算),前端使用JSON字符串类型...

code-ortaerc
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部