argz_create_sep函数
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
函數(shù)位于glibc源碼中的../glibc-version/string/argz-ctsep.c中,其作用是將字符串以指定的字符進行分割,指定字符的位置替換成空字符串(\0),使整個字符串形成一個argz vector。
argz vector是存儲在連續(xù)空間的一維字符數(shù)組,彼此之間以空字符(\0)進行分隔。
也就是說argz_create_sep函數(shù)的目的是將一個字符串按指定字符分割成多個字符串,存入一個連續(xù)空間中,彼此之間以空字符(\0)進行分隔,形成argz vector。
假如待分割字符串為“argz_create_sep”,以r作分割符,得到的argz vector應當如下所示:
函數(shù)聲明如下:
//?argz.h /*?Make?a?'\0'?separated?arg?vector?from?a?SEP?separated?list?inSTRING,?returning?it?in?ARGZ,?and?the?total?length?in?LEN.??If?amemory?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; /*?*/函數(shù)的實現(xiàn)如下:
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;doif?(*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,然后繼續(xù)復制。
需要注意的是如果待分割的字符串中存在連續(xù)的delim,那么形成的argz vector中該部分字符串只有一個\0,同時len也會相應的減小。完成這個操作的是下面這段代碼,它主要是針對這類特殊情況的處理(假設以s進行分割)。
1、待分割字符串string的第一個字符就是delim相同(如:string Microsoft)
2、待分割字符串string中存在連續(xù)個delim(如:string Microsssoft,或者ssssssssss)
if?(wp?>?*argz?&&?wp[-1]?!=?'\0')*wp++?=?'\0'; else--nlen; /*?*/?
?調(diào)用__argz_create_sep函數(shù)的方式為:
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;doif?(*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; }?程序輸出如下:
?注意,輸出結(jié)果中argz vector的字符串之間的“空格”并不是空格,而是\0的輸出但是這個字符沒法顯示的結(jié)果。
?
附:我覺得那個函數(shù)寫的太蛋疼了。。果然我還是喜歡用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; }現(xiàn)在是2017年4月14日,看到以前寫的這一段內(nèi)容,仔細思考了一下,果然還是源碼厲害。for并不能完全的處理由delim組成的字符串。如string="ssss", delim='s',當處理到最后一個字符時,源碼很可靠的讓nlen=1,并且argz[0]='\0'。但是我上面那個用for寫的,則沒有處理argz[0]='\0',直接導致argz中l(wèi)en=1,但是卻什么都沒有。
轉(zhuǎn)載于:https://my.oschina.net/saiy/blog/512511
總結(jié)
以上是生活随笔為你收集整理的argz_create_sep函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国内常见的电子地图坐标介绍
- 下一篇: 移动端利用-webkit-box水平垂直