亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > .NET > 正文

C標準庫源碼解剖(5):字符串處理函數string.h和wchar.h(續)

2024-07-10 13:27:15
字體:
來源:轉載
供稿:網友

 3、字符串復制strcpy,strncpy,wcscpy,wcsncpy:將字符串src(或其前n個字符)復制到dest中,覆蓋dest的內容。實現中先檢查指針是否越界,計算指針dest到src的偏移,然后開始做復制操作,復制到dest的開始位置處,以覆蓋dest的內容。對strncpy,也采用了每4個字符作為一組來進行復制的方法,以加快復制速度。

 

[cpp] view plaincopy
  1. /* strcpy.c:strcpy函數的實現 */  
  2. #include <stddef.h>   /* 用到了ptrdiff_t */  
  3. #include <string.h>  
  4. #include <memcopy.h>  
  5. #include <bp-checks.h>  /* 定義了CHECK_BOUNDS_LOW和CHECK_BOUNDS_HIGH */  
  6. #undef strcpy  
  7. /* 將SRC復制到DEST中,覆蓋DEST原先的內容 */  
  8. char *  
  9. strcpy (dest, src)  
  10.      char *dest;  
  11.      const char *src;  
  12. {  
  13.   reg_char c;  
  14.   /* 檢查指針src的值是否 >= low,返回原來的指針值 */  
  15.   char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);  
  16.   /* 計算出目的地dest到s的偏移 */  
  17.   const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;  
  18.   size_t n;  
  19.   do  
  20.     {  
  21.       c = *s++;   /* 把src中每個字符復制到目的地,覆蓋了dest中的內容 */  
  22.       s[off] = c;  
  23.     }  
  24.   while (c != '/0');  
  25.   n = s - src;  
  26.   (void) CHECK_BOUNDS_HIGH (src + n); /* 檢查指針src+n的值是否 < high,返回原來的指針值 */  
  27.   (void) CHECK_BOUNDS_HIGH (dest + n);  
  28.   return dest;  
  29. }  
  30. libc_hidden_builtin_def (strcpy)  

 

 

[cpp] view plaincopy
  1. /* strncpy.c:strncpy函數的實現  */  
  2. #include <string.h>  
  3. #include <memcopy.h>  
  4. #undef strncpy  
  5. /* 將s2的前n個字符復制到s1中,覆蓋s1原先的內容,若s2不中n個字符, 
  6.     則填充null字符,直到寫入n個字符 */  
  7. char *  
  8. strncpy (s1, s2, n)  
  9.      char *s1;  
  10.      const char *s2;  
  11.      size_t n;  
  12. {  
  13.   reg_char c;  
  14.   char *s = s1;  
  15.   --s1; /* 指向首字符的前一個字符 */  
  16.   if (n >= 4)     /* 做復制操作,每4個字符作為一組來進行復制 */  
  17.     {  
  18.       size_t n4 = n >> 2; /* 讓n除以4,計算出循環次數 */  
  19.       for (;;)   /* 每次循環都復制4個字符,總共復制了4*n4個字符 */  
  20.     {  
  21.       c = *s2++;  
  22.       *++s1 = c;  
  23.       if (c == '/0'/* s2不足n個字符時,復制完畢,退出循環 */  
  24.         break;  
  25.       c = *s2++;  
  26.       *++s1 = c;  
  27.       if (c == '/0')  
  28.         break;  
  29.       c = *s2++;  
  30.       *++s1 = c;  
  31.       if (c == '/0')  
  32.         break;  
  33.       c = *s2++;  
  34.       *++s1 = c;  
  35.       if (c == '/0')  
  36.         break;  
  37.       if (--n4 == 0)  
  38.         goto last_chars; /* 循環終止,要對剩下的幾個字符(不超過3個)進行復制 */  
  39.     }  
  40.       n = n - (s1 - s) - 1;  
  41.       if (n == 0)  /* 若s1恰好到達s的終止符的前一個字符處 */  
  42.     return s;  /* 說明s與s2長度相等,均為n,復制操作恰好用s2覆蓋了s,終止符沒有覆蓋,直接返回s */  
  43.       goto zero_fill; /* 否則s1沒有到達s的末尾,說明s2不足n個字符,需要在s1末尾填充null字符,直到寫入n個字符 */  
  44.     }  
  45.  last_chars:  
  46.   n &= 3; /* 求出n除以4的余數 */  
  47.   if (n == 0)  /* 余數為0說明沒有剩余的未復制的字符,直接返回s */  
  48.     return s;  
  49.   do   /* 對剩下的幾個字符(最多3個)進行復制 */  
  50.     {  
  51.       c = *s2++;  
  52.       *++s1 = c;  
  53.       if (--n == 0)  
  54.     return s;  
  55.     }  
  56.   while (c != '/0');  
  57.  zero_fill:  
  58.   do  
  59.     *++s1 = '/0';  /* 在s1末尾填充null字符,直到寫入n個字符 */  
  60.   while (--n > 0);  
  61.   return s;  
  62. }  
  63. libc_hidden_builtin_def (strncpy)  

 

    4、字符串求長strlen,wcslen:返回str中終止符'/0'之前的字符個數。這里通過把指針移到終止符處,然后計算該指針與開始處指針的差值來獲取字符串的長度。為了加快移動速度,實現中把const char*型指針char_ptr轉換成了unsigned long*型指針longword_ptr,這樣一次就可以移動4個字節。算法關鍵是要辨別出longword_ptr指向的值(有4個字節)中有一個字節為0(它表示字符'/0'),這說明指針到達了終止符'/0'處,要停止移動,并轉換回const char*型指針,計算指針之間的差值。

 

[cpp] view plaincopy
  1. /* strlen.c:strlen函數的實現 */  
  2. #include <string.h>  
  3. #include <stdlib.h>  /* 用到abort()函數 */  
  4. #undef strlen  
  5. /* 返回以null終止的字符串str的長度。通過一次測試4個字節來迅速的掃描到null終止符 */  
  6. size_t  
  7. strlen (str)  
  8.      const char *str;  
  9. {  
  10.   const char *char_ptr;  
  11.   const unsigned long int *longword_ptr;  
  12.   unsigned long int longword, magic_bits, himagic, lomagic;  
  13.   /* 通過一次讀取一個字符來處理開頭的幾個字符,直到char_ptr中的值對齊到一個long型字的邊界, 
  14.       即直到char_ptr中的值是long的字節數(通常為4)的倍數 */  
  15.   for (char_ptr = str; ((unsigned long int) char_ptr  
  16.             & (sizeof (longword) - 1)) != 0;  
  17.        ++char_ptr)  
  18.     if (*char_ptr == '/0'/* 若到達null終止符,則直接返回長度 */  
  19.       return char_ptr - str;  
  20.   /* 所有這些說明性的注釋使用4字節的long型字,但本算法同樣也可以應用于8字節的long型字 */  
  21.     
  22.   longword_ptr = (unsigned long int *) char_ptr;  
  23.   /* magic_bits的第8,16,24,31位為0,稱這些位為“洞”。注意每個字節的左邊有一個洞, 
  24.       在最后的位置上也有一個洞。 
  25.      bits:  01111110 11111110 11111110 11111111 
  26.       比特1確保進位能傳播到后面的比特0上,比特0則提供洞,以便讓進位陷進去  */  
  27.   magic_bits = 0x7efefeffL;  
  28.   himagic = 0x80808080L;  /* 高位魔數,即第7,15,23,31位上為1 */  
  29.   lomagic = 0x01010101L;  /* 低位魔數,即第0,8,16,24位上為1 */  
  30.   if (sizeof (longword) > 4) /*  64位的平臺上 */  
  31.     {  
  32.       /* 魔數的64位版本 */  
  33.       /* 移位操作分兩步,以避免當long為32位時出現警告 */  
  34.       /* 位數的第8,16,24,32,40,48,56,63位上為0 */  
  35.       magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL;  
  36.       himagic = ((himagic << 16) << 16) | himagic; /* 第7,15,23,31,39,47,55,63位上為1 */  
  37.       lomagic = ((lomagic << 16) << 16) | lomagic; /* 第0,8,16,24,32,40,48,56位上為0 */  
  38.     }  
  39.   if (sizeof (longword) > 8) /* long類型大于8字節則終止程序 */  
  40.     abort ();  
  41.   /* 這里我們不使用傳統的對每個字符都進行測試的循環,而是一次測試一個long型字。技巧性的部分 
  42.       是測試當前long型字的各個字節是否為0 */  
  43.   for (;;)  
  44.     {      
  45.       longword = *longword_ptr++;  
  46.       if (  
  47. #if 0  
  48.       /* 讓longword加上魔數magic_bits  */  
  49.       (((longword + magic_bits)  
  50.         /* 設置那些通過加法而未改變的位 */  
  51.         ^ ~longword)  
  52.          
  53.        /* 只需看這些洞。如果任何的洞位都沒有改變,最有可能的是有一個字節值為0 */  
  54.        & ~magic_bits)  
  55. #else  
  56.       ((longword - lomagic) & himagic)  
  57. #endif  
  58.       != 0)  
  59.     {       
  60.       /* 長整型字的哪個字節為0?如果都不為0,則是一個非預期情況,繼續搜索 */  
  61.       const char *cp = (const char *) (longword_ptr - 1);  
  62.       if (cp[0] == 0)  
  63.         return cp - str;  
  64.       if (cp[1] == 0)  
  65.         return cp - str + 1;  
  66.       if (cp[2] == 0)  
  67.         return cp - str + 2;  
  68.       if (cp[3] == 0)  
  69.         return cp - str + 3;  
  70.       if (sizeof (longword) > 4) /* 如果long類型是8個字節,則還有4個字節需要判斷 */  
  71.         {  
  72.           if (cp[4] == 0)  
  73.         return cp - str + 4;  
  74.           if (cp[5] == 0)  
  75.         return cp - str + 5;  
  76.           if (cp[6] == 0)  
  77.         return cp - str + 6;  
  78.           if (cp[7] == 0)  
  79.         return cp - str + 7;  
  80.         }  
  81.     }  
  82.     }  
  83. }  
  84. libc_hidden_builtin_def (strlen)  

 

    解釋:
    (1)先移動char_ptr,使其值對齊到長整型字的邊界,即移動到使char_ptr中的值是4的倍數為止。在對齊過程中若到達了終止符處,則直接返回與開始處的指針str的差值。 
    (2)對longword_ptr指針進行移動時,指針指向的值為longword。為了判斷指針是否到達終止符,算法實現使用了兩個魔數lomagic和himagic,lomagic各個字節的最低位為1,其余位均為0;himagic各個字節的最高位為1,其余位均為0??幢磉_式(longword - lomagic) & himagic,若longword中有一個字節為00000000,則減00000001時要向高字節借一位,得到11111111或11111110(當借了一位給更低的字節時),與10000000做“與”運算后變成10000000,這時表達式的結果必定不為0??梢?,只有在表達式結果不等于0時,longword中才有可能有終止符。因此,在移動過程中,一旦表達式結果不等于0,只要逐一檢查一下每個字節,看哪個為0,這時就到達終止符,計算指針差值并返回。若都不為0,則繼續移動。
    (3)也可以只用一個魔數magic_bits來實現,即代碼中用#if 0注釋掉的那部分,它可以達到同樣的效果??幢磉_式((longword + magic_bits) ^ ~longword) & ~magic_bits,最后的“與”運算會使結果的其他位清零,只留下那4個洞位,因此我們只要看longword的洞位的變化即可。若longword中有一個字節為0,則做加法后它不可能向高字節(即左側字節)進位,左側字節的洞位沒有改變(因為magic_bits的對應洞位為0,加上0而又沒有低字節的進位,因此不會改變)。做異或運算后,必定使這個洞位變成1,因此表達式的結果必定不為0??梢?,這跟(2)用兩個魔數實現的效果是一樣的。
    5、字符搜索strchr,strrchr,wcschr,wcsrchr:在字符串s中查找字符c的第一次(或最后一次)出現,若沒找到則返回NULL指針。算法實現與strlen類似,只不過在strlen是搜索到終止符'/0'為止,這里是搜索到字符c為止。

 

[cpp] view plaincopy
  1. /* strchr.c:strchr函數的實現  */  
  2. #include <string.h>  
  3. #include <memcopy.h>  /* 非標準頭文件,要用到reg_char類型 */  
  4. #include <stdlib.h>   /* 要用到abort() */  
  5. #undef strchr  
  6. /* 在S中查找C的第一次出現,如果沒有找到,則返回NULL指針  */  
  7. char *  
  8. strchr (s, c_in)  
  9.      const char *s;  
  10.      int c_in;  
  11. {  
  12.   const unsigned char *char_ptr;  
  13.   const unsigned long int *longword_ptr;  
  14.   unsigned long int longword, magic_bits, charmask;  
  15.   unsigned reg_char c;  
  16.   c = (unsigned char) c_in;  
  17.   /* 通過一次讀取一個字符來處理開頭的幾個字符,直到char_ptr中的值對齊到一個long型字的邊界, 
  18.       即直到char_ptr中的值是long的字節數(通常為4)的倍數 */  
  19.   for (char_ptr = (const unsigned char *) s;  
  20.        ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0;  
  21.        ++char_ptr)  
  22.     if (*char_ptr == c)     /* 若到達字符c處,則直接返回其指針 */  
  23.       return (void *) char_ptr;  
  24.     else if (*char_ptr == '/0')  /* 沒找到c則返回NULL */  
  25.       return NULL;  
  26.   /* 所有這些說明性的注釋使用4字節的long型字,但本算法同樣也可以應用于8字節的long型字 */  
  27.   longword_ptr = (unsigned long int *) char_ptr;  
  28.   /* magic_bits的第8,16,24,31位為0,稱這些位為“洞”。注意每個字節的左邊有一個洞, 
  29.       在最后的位置上也有一個洞。 
  30.      bits:  01111110 11111110 11111110 11111111 
  31.       比特1確保進位能傳播到后面的比特0上,比特0則提供洞,以便讓進位陷進去  */  
  32.   switch (sizeof (longword))  
  33.     {  
  34.     case 4: magic_bits = 0x7efefeffL; break;  
  35.     case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break;  
  36.     default:  
  37.       abort ();  
  38.     }  
  39.   /* 設置一個長整型字,其每個字節都是字符c */  
  40.   charmask = c | (c << 8);  
  41.   charmask |= charmask << 16;  
  42.   if (sizeof (longword) > 4)  
  43.     /* 移位操作分兩步,以避免當long為32位時出現警告 */  
  44.     charmask |= (charmask << 16) << 16;  
  45.   if (sizeof (longword) > 8)   
  46.     abort ();  /* long類型大于8字節則終止程序 */  
  47.   /* 這里我們不使用傳統的對每個字符都進行測試的循環,而是一次測試一個long型字。技巧性的部分 
  48.       是測試當前long型字的各個字節是否為0 */  
  49.   for (;;)  
  50.     {      
  51.       longword = *longword_ptr++;  
  52.       /* 讓longword加上魔數magic_bits  */  
  53.       if ((((longword + magic_bits)  
  54.         /* 設置那些通過加法而未改變的位 */  
  55.         ^ ~longword)  
  56.        /* 只需看這些洞。如果任何的洞位都沒有改變,最有可能的是有一個字節值為0 */  
  57.        & ~magic_bits) != 0 ||  
  58.       /* 捕捉到值為0的字節后,測試字中是否含有字符c  */  
  59.       ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask))  
  60.        & ~magic_bits) != 0)  
  61.     {  
  62.       /* 長整型字的哪個字節為C或0?如果都不是,則是一個非預期情況,繼續搜索 */  
  63.       const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);  
  64.       if (*cp == c)  
  65.         return (char *) cp;  
  66.       else if (*cp == '/0')  
  67.         return NULL;  
  68.       if (*++cp == c)  
  69.         return (char *) cp;  
  70.       else if (*cp == '/0')  
  71.         return NULL;  
  72.       if (*++cp == c)  
  73.         return (char *) cp;  
  74.       else if (*cp == '/0')  
  75.         return NULL;  
  76.       if (*++cp == c)  
  77.         return (char *) cp;  
  78.       else if (*cp == '/0')  
  79.         return NULL;  
  80.       if (sizeof (longword) > 4) /* 如果long類型是8個字節,則還有4個字節需要判斷 */  
  81.         {  
  82.           if (*++cp == c)  
  83.         return (char *) cp;  
  84.           else if (*cp == '/0')  
  85.         return NULL;  
  86.           if (*++cp == c)  
  87.         return (char *) cp;  
  88.           else if (*cp == '/0')  
  89.         return NULL;  
  90.           if (*++cp == c)  
  91.         return (char *) cp;  
  92.           else if (*cp == '/0')  
  93.         return NULL;  
  94.           if (*++cp == c)  
  95.         return (char *) cp;  
  96.           else if (*cp == '/0')  
  97.         return NULL;  
  98.         }  
  99.     }  
  100.     }  
  101.   return NULL;  
  102. }  
  103. #ifdef weak_alias  
  104. #undef index  
  105. weak_alias (strchr, index)  
  106. #endif  
  107. libc_hidden_builtin_def (strchr)  

 

 

[cpp] view plaincopy
  1. /* strrchr.c:strrchr函數的實現 */  
  2. #include <string.h>  
  3. #undef strrchr  
  4. /* 在S中查找C的最后一次出現  */  
  5. char *  
  6. strrchr (const char *s, int c)  
  7. {  
  8.   register const char *found, *p;  
  9.   c = (unsigned char) c;  
  10.   /* 因為strchr非常地快,我們直接使用它來實現strrchr */  
  11.   if (c == '/0')  
  12.     return strchr (s, '/0');  
  13.   found = NULL;  
  14.   while ((p = strchr (s, c)) != NULL)  
  15.     {  
  16.       found = p;  
  17.       s = p + 1;  
  18.     }  
  19.   return (char *) found;  
  20. }  
  21. #ifdef weak_alias  
  22. #undef rindex  
  23. weak_alias (strrchr, rindex)  
  24. #endif  
  25. libc_hidden_builtin_def (strrchr)  

 

    解釋:
    (1)算法中,有可能搜索到字符c,也有可能搜索到終止符(當字符串中沒有c時)。對于搜索到終止符,與strlen中一樣,對于搜索到字符c,要判斷longword中是否有一個字節為c,看表達式(((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask)) & ~magic_bits,長整型字charmask的每個字節都是字符c。strlen的對應表達式中的longword換成了這里的longword ^ charmask,而這里的longword中有一個字節為c,恰好等價于longword ^ charmask中有一個字節為0,因此具體的分析過程是一樣的。
    (2)strrchr的實現直接使用strchr。用strchr不停地向前搜索,直到搜索到最后一個c為止。
    6、子串的無順序匹配strspn,strcspn,strpbrk,wcsspn,wcscspn,wcspbrk:strspn和strcspn在s的開頭查找一個最長子串,使其所有字符都在accept中(或都不在reject中),返回這個子串的長度。strspn的實現中直接對s中開頭的每個字符搜索accept,看其是否在accept中。strcspn的實現則使用了strchr來查找字符。strpbrk在s中搜索第一個出現在accept中的字符,返回其指針。

 

[cpp] view plaincopy
  1. /* strspn.c:strspn函數的實現 */  
  2. #include <string.h>  
  3. #undef strspn  
  4. /* 返回S中的第一個子串長度,這個子串的所有字符都在ACCEPT中  */  
  5. size_t  
  6. strspn (s, accept)  
  7.      const char *s;  
  8.      const char *accept;  
  9. {  
  10.   const char *p;  
  11.   const char *a;  
  12.   size_t count = 0;  
  13.   for (p = s; *p != '/0'; ++p) /* 對s開頭的各個字符,搜索accept */  
  14.     {  
  15.       for (a = accept; *a != '/0'; ++a)  
  16.     if (*p == *a)  /* 若該字符在accept中,則子串長度加1 */  
  17.       break;  
  18.       if (*a == '/0'/* 若在accept中沒有找到該字符,則子串匹配結束,直接返回count */  
  19.     return count;  
  20.       else  
  21.     ++count;  
  22.     }  
  23.   return count;  
  24. }  
  25. libc_hidden_builtin_def (strspn)  

 

 

[cpp] view plaincopy
  1. /* strcspn.c:strcspn函數的實現 */  
  2. #if HAVE_CONFIG_H  
  3. # include <config.h>  
  4. #endif  
  5. #if defined _LIBC || HAVE_STRING_H  
  6. # include <string.h>  
  7. #else  
  8. # include <strings.h>  
  9. # ifndef strchr  
  10. #  define strchr index  
  11. # endif  
  12. #endif  
  13. #undef strcspn  
  14. /* 返回S中的第一個子串長度,這個子串的所有字符都不在REJECT中  */  
  15. size_t  
  16. strcspn (s, reject)  
  17.      const char *s;  
  18.      const char *reject;  
  19. {  
  20.   size_t count = 0;  
  21.   while (*s != '/0')  /* 對s開頭的各個字符,搜索reject */  
  22.     if (strchr (reject, *s++) == NULL) /* 若不在reject,則子串長度加1 */  
  23.       ++count;  
  24.     else  
  25.       return count;  
  26.   return count;  
  27. }  
  28. libc_hidden_builtin_def (strcspn)  

 

 

[cpp] view plaincopy
  1. /* strpbrk.c:strpbrk函數的實現  */  
  2. #ifdef HAVE_CONFIG_H  
  3. # include <config.h>  
  4. #endif  
  5. #if defined _LIBC || defined HAVE_CONFIG_H  
  6. # include <string.h>  
  7. #endif  
  8. #undef strpbrk  
  9. /* 在s中搜索第一個出現在accept中的字符,返回其指針 */  
  10. char *  
  11. strpbrk (s, accept)  
  12.      const char *s;  
  13.      const char *accept;  
  14. {  
  15.   while (*s != '/0'/* 對s開頭的各個字符,看其是否在accept中 */  
  16.     {  
  17.       const char *a = accept;  
  18.       while (*a != '/0')  
  19.     if (*a++ == *s) /* 若在accept,則返回,否則繼承向前搜索 */  
  20.       return (char *) s;  
  21.       ++s;  
  22.     }  
  23.   return NULL;  
  24. }  
  25. libc_hidden_builtin_def (strpbrk)  

 

    7、模式匹配及字符串解析strstr,strtok,wcsstr,wcstok:strstr(src,sub)在src中搜索子串sub,返回其第一次出現的位置。strtok(str,set)用set中的字符作為分隔符把str分解為多個標號。
    strstr的實現用了最新的二路模式匹配算法,可以達到最好的效率。由于算法比較復雜,涉及到很多內部函數,這里就不解剖了,我們平時一般使用KMP算法來進行模式匹配,這個效率也已經非常不錯了。strtok實現如下:

 

[cpp] view plaincopy
  1. /* strok.c:strok函數的實現  */  
  2. #include <string.h>  
  3. static char *olds; /* 下一記號的開始處,若到達字符串末尾,則olds指向終止符'/0' */  
  4. #undef strtok  
  5. /* 用DELIM中的字符作為分隔符把S解析成多個記號,返回當前的記號。如果S為NULL, 
  6.     則strtok從即下一記號的開始處開始解析。例如: 
  7.     char s[] = "-abc-=-def"; 
  8.     x = strtok(s, "-");     // x = "abc" 
  9.     x = strtok(NULL, "-=");     // x = "def" 
  10.     x = strtok(NULL, "=");      // x = NULL 
  11.         // s = "abc/0=-def/0" 
  12. */  
  13. char *  
  14. strtok (s, delim)  
  15.      char *s;  
  16.      const char *delim;  
  17. {  
  18.   char *token;  
  19.   if (s == NULL) /* s指定為NULL,則使用olds */  
  20.     s = olds;  
  21.   /* 從s開始搜索分隔符,跳過分隔符,讓s移動到記號開始處  */  
  22.   s += strspn (s, delim);  
  23.   if (*s == '/0'/* 若s到達字符串末尾,則返回NULL表示記號解析過程完畢 */  
  24.     {  
  25.       olds = s;  
  26.       return NULL;  
  27.     }  
  28.   /* 找到當前記號的末尾處(即下一分隔符處)  */  
  29.   token = s; /* token指向記號的首個字符 */  
  30.   s = strpbrk (token, delim); /* 從token開始找到下一分隔符,讓s指向它 */  
  31.   if (s == NULL) /* 如果到達的是字符串末尾,說明當前記號是最后一個記號 */  
  32.     /* 從token開始,找到終止符,并賦給olds,表示記號解析結束  */  
  33.     olds = __rawmemchr (token, '/0');  
  34.   else  /* 否則s指向了下一分隔符 */  
  35.     {  
  36.       /* 把分隔符替換成'/0',以解析出當前記號,讓OLDS指向下一記號的開始處  */  
  37.       *s = '/0';  
  38.       olds = s + 1;  
  39.     }  
  40.   return token;  
  41. }  

 

    算法先用strspn函數使s路過分隔符,移到當前記號的開始處;接著讓token指向當前記號開始處,s移到下一個分隔符處(通過strpbrk函數);然后把這個分隔符替換成終止符'/0',以解析出當前記號,olds指向下一記號的開始處。下一次解析時,若指定s為NULL,則從olds處開始新的解析。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲免费视频一区二区| 日韩电影视频免费| 日韩久久午夜影院| 国产中文欧美精品| 日韩经典一区二区三区| 国产精品久久久久久久久| 国产在线久久久| 欧美日韩国产综合视频在线观看中文| 日韩精品亚洲视频| 亚洲成人av在线播放| 国产精品日韩在线观看| 亚洲老头老太hd| 亚洲国产小视频在线观看| 日韩在线观看电影| 欧美激情啊啊啊| 欧美性猛交xxxx乱大交| 国产精品一区二区久久| 国产一区二区三区18| 国产一区二区在线播放| 亚洲摸下面视频| 成人午夜高潮视频| 欧美专区第一页| 国产精品成人av性教育| 欧美成人在线免费视频| 国产精品亚发布| 高清欧美一区二区三区| 国产精品亚洲第一区| 日韩精品福利网站| 午夜精品在线观看| 影音先锋欧美在线资源| 亚洲成人久久网| 国产精品18久久久久久首页狼| 成人免费在线视频网站| 久久久精品2019中文字幕神马| 久久久亚洲欧洲日产国码aⅴ| 久久综合88中文色鬼| 久久天天躁狠狠躁夜夜躁2014| 欧美日本高清视频| 亚洲欧美视频在线| 欧美一级免费看| 久久久噜噜噜久久中文字免| 亚洲伊人久久综合| 欧美在线观看网址综合| 亚洲一区国产精品| 欧美性生交大片免费| 亚洲精品乱码久久久久久金桔影视| 亚洲国产日韩欧美在线99| 57pao精品| 亚洲美女视频网站| 色在人av网站天堂精品| 久久久最新网址| 欧美精品手机在线| 国产精品欧美在线| 日韩在线视频网| 激情成人在线视频| 中文国产成人精品久久一| 97免费视频在线播放| 日韩美女在线观看| 亚洲欧洲在线视频| 日韩视频中文字幕| 久久久久久有精品国产| 欧美精品电影免费在线观看| 精品动漫一区二区| 欧美日韩免费在线观看| 青青精品视频播放| 久久不射电影网| 国产精品一区二区电影| 亚洲成人三级在线| 91精品在线一区| 伊人久久久久久久久久| 川上优av一区二区线观看| 91精品久久久久久久久不口人| 日韩av中文在线| 欧美日韩视频免费播放| 国产精品老女人视频| 97在线视频精品| 成人福利在线观看| 久久久久免费精品国产| 欧美国产日韩视频| 欧美激情国产高清| 日韩在线精品视频| 日韩亚洲精品视频| 久久中文精品视频| 国产视频久久久久久久| 日韩欧美国产成人| 国产美女精品视频免费观看| 韩国福利视频一区| 91最新国产视频| 亚洲国产91精品在线观看| 亚洲大胆人体在线| 国外成人在线直播| 都市激情亚洲色图| 亚洲欧美日韩精品久久亚洲区| 97视频在线观看网址| 91精品视频在线免费观看| 欧美福利视频在线| 精品国产老师黑色丝袜高跟鞋| 亚洲福利视频免费观看| 日韩电影视频免费| 国产综合在线看| 国产精品日韩在线播放| 日韩精品亚洲元码| 亚洲毛片在线观看.| 精品自拍视频在线观看| 国产欧美日韩综合精品| 91老司机在线| 欧美最猛黑人xxxx黑人猛叫黄| 欧美激情综合色综合啪啪五月| 久久久国产精品视频| 日韩av在线精品| 欧美性猛交xxxx免费看久久久| 66m—66摸成人免费视频| 日本精品免费观看| 久久成人人人人精品欧| 日韩在线www| 成人精品视频久久久久| 欧美中文字幕精品| 97在线观看免费| 久久久久久69| 国产99久久精品一区二区 夜夜躁日日躁| 欧美—级a级欧美特级ar全黄| 国产精品女主播| 日本一区二区三区四区视频| 久久人人爽人人爽爽久久| 久久视频在线免费观看| 欧美高清在线视频观看不卡| 日韩一区二区三区在线播放| 欧美极品少妇全裸体| 最近2019中文字幕在线高清| 久久久久久一区二区三区| 992tv在线成人免费观看| 黑人极品videos精品欧美裸| 欧美成人午夜剧场免费观看| 日韩欧美国产一区二区| 在线播放日韩av| 国产xxx69麻豆国语对白| 国产人妖伪娘一区91| 亚洲精品视频播放| 久久视频在线免费观看| 97人人模人人爽人人喊中文字| 久久色免费在线视频| 久久久爽爽爽美女图片| 日韩欧美在线看| 精品久久在线播放| 国产精品三级在线| 九九久久久久久久久激情| 亚洲欧洲国产精品| 疯狂做受xxxx欧美肥白少妇| 96sao精品视频在线观看| 亚洲а∨天堂久久精品9966| 成人午夜两性视频| 日韩久久免费电影| 亚洲天堂开心观看| 中文字幕成人精品久久不卡| 午夜精品久久久99热福利| 亚洲最大成人网色| 91在线视频一区| 国产精品一二区| 国模精品视频一区二区| 国产一区二区三区视频免费| 欧美另类第一页| 亚洲自拍偷拍色图| 亚洲精品国产福利| 日本久久久久久久|