函数位于glibc源码中的../glibc-version/string/argz-ctsep.c中,其作用是将字符串以指定的字符进行分割,指定字符的位置替换成空字符串(\0),使整个字符串形成一个argz vector。
argz vector是存储在连续空间的一维字符数组,彼此之间以空字符(\0)进行分隔。
也就是说argz_create_sep函数的目的是将一个字符串按指定字符分割成多个字符串,存入一个连续空间中,彼此之间以空字符(\0)进行分隔,形成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,然后继续复制。
需要注意的是下面这句。这段主要是针对特殊情况的处理。
1、待分割字符串string的第一个字符就是delim相同
2、待分割字符串string全部由delim构成
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 #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; size_t len; char *argz = NULL; char delim = ‘s‘; const char *mystring = "string microsoft"; __argz_create_sep(mystring, delim, &argz, &len); puts(argz); for(i=0; i<len; ++i){ putchar(argz[i]); } putchar(‘\n‘); free(argz); return 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; }
原文:http://my.oschina.net/saiy/blog/512511