string.h中包含了所有的字符串處理函數,也包含了內存處理函數,因為這些內存處理函數(如比如、復制、搜索)的功能與字符串處理函數功能類似。我們是用通用指針來指向內存塊的,通用指針可以用char*類型(傳統C語言),也可以用void*類型(標準C語言)。每個函數都有對應的寬字符版本,在wchar.h中。
string.h中包含的標準庫函數:strcat,strncat,strcmp,strncmp,strcpy,strncpy,strlen,strchr,strrchr,strspn,strcspn,strpbrk, strstr,strok,strcoll,strxfrm,strerror; memcpy,memmove,memcmp,memchr,memeset。GNU還提供了很多非標準的擴展,如memccpy,rawmemchr,memrchr, strdup,strndup等。
-
- #ifndef _STRING_H
- #define _STRING_H 1
- #include <features.h> /* 非標準頭文件,定義了一些編譯選項 */
- __BEGIN_DECLS
-
- #define __need_size_t
- #define __need_NULL
- #include <stddef.h>
- __BEGIN_NAMESPACE_STD
-
- extern void *memcpy (void *__restrict __dest,
- __const void *__restrict __src, size_t __n)
- __THROW __nonnull ((1, 2));
-
- extern void *memmove (void *__dest, __const void *__src, size_t __n)
- __THROW __nonnull ((1, 2));
- __END_NAMESPACE_STD
-
-
- #if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN
- extern void *memccpy (void *__restrict __dest, __const void *__restrict __src,
- int __c, size_t __n)
- __THROW __nonnull ((1, 2));
- #endif /* SVID. */
- __BEGIN_NAMESPACE_STD
-
- extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));
-
- extern int memcmp (__const void *__s1, __const void *__s2, size_t __n)
- __THROW __attribute_pure__ __nonnull ((1, 2));
-
- extern void *memchr (__const void *__s, int __c, size_t __n)
- __THROW __attribute_pure__ __nonnull ((1));
- __END_NAMESPACE_STD
- #ifdef __USE_GNU
-
- extern void *rawmemchr (__const void *__s, int __c)
- __THROW __attribute_pure__ __nonnull ((1));
-
- extern void *memrchr (__const void *__s, int __c, size_t __n)
- __THROW __attribute_pure__ __nonnull ((1));
- #endif
- __BEGIN_NAMESPACE_STD
-
- extern char *strcpy (char *__restrict __dest, __const char *__restrict __src)
- __THROW __nonnull ((1, 2));
-
- extern char *strncpy (char *__restrict __dest,
- __const char *__restrict __src, size_t __n)
- __THROW __nonnull ((1, 2));
-
- extern char *strcat (char *__restrict __dest, __const char *__restrict __src)
- __THROW __nonnull ((1, 2));
-
- extern char *strncat (char *__restrict __dest, __const char *__restrict __src,
- size_t __n) __THROW __nonnull ((1, 2));
-
- extern int strcmp (__const char *__s1, __const char *__s2)
- __THROW __attribute_pure__ __nonnull ((1, 2));
-
- extern int strncmp (__const char *__s1, __const char *__s2, size_t __n)
- __THROW __attribute_pure__ __nonnull ((1, 2));
-
- extern int strcoll (__const char *__s1, __const char *__s2)
- __THROW __attribute_pure__ __nonnull ((1, 2));
-
- extern size_t strxfrm (char *__restrict __dest,
- __const char *__restrict __src, size_t __n)
- __THROW __nonnull ((2));
- __END_NAMESPACE_STD
- #ifdef __USE_GNU
-
-
- # include <xlocale.h>
-
- extern int strcoll_l (__const char *__s1, __const char *__s2, __locale_t __l)
- __THROW __attribute_pure__ __nonnull ((1, 2, 3));
-
- extern size_t strxfrm_l (char *__dest, __const char *__src, size_t __n,
- __locale_t __l) __THROW __nonnull ((2, 4));
- #endif
- #if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED
-
- extern char *strdup (__const char *__s)
- __THROW __attribute_malloc__ __nonnull ((1));
- #endif
-
-
- #if defined __USE_GNU
- extern char *strndup (__const char *__string, size_t __n)
- __THROW __attribute_malloc__ __nonnull ((1));
- #endif
- #if defined __USE_GNU && defined __GNUC__
-
- # define strdupa(s) /
- (__extension__ /
- ({ /
- __const char *__old = (s); /
- size_t __len = strlen (__old) + 1; /
- char *__new = (char *) __builtin_alloca (__len); /
- (char *) memcpy (__new, __old, __len); /
- }))
-
- # define strndupa(s, n) /
- (__extension__ /
- ({ /
- __const char *__old = (s); /
- size_t __len = strnlen (__old, (n)); /
- char *__new = (char *) __builtin_alloca (__len + 1); /
- __new[__len] = '/0'; /
- (char *) memcpy (__new, __old, __len); /
- }))
- #endif
- __BEGIN_NAMESPACE_STD
-
- extern char *strchr (__const char *__s, int __c)
- __THROW __attribute_pure__ __nonnull ((1));
-
- extern char *strrchr (__const char *__s, int __c)
- __THROW __attribute_pure__ __nonnull ((1));
- __END_NAMESPACE_STD
- #ifdef __USE_GNU
-
- extern char *strchrnul (__const char *__s, int __c)
- __THROW __attribute_pure__ __nonnull ((1));
- #endif
- __BEGIN_NAMESPACE_STD
-
- extern size_t strcspn (__const char *__s, __const char *__reject)
- __THROW __attribute_pure__ __nonnull ((1, 2));
-
- extern size_t strspn (__const char *__s, __const char *__accept)
- __THROW __attribute_pure__ __nonnull ((1, 2));
-
- extern char *strpbrk (__const char *__s, __const char *__accept)
- __THROW __attribute_pure__ __nonnull ((1, 2));
-
- extern char *strstr (__const char *__haystack, __const char *__needle)
- __THROW __attribute_pure__ __nonnull ((1, 2));
-
- extern char *strtok (char *__restrict __s, __const char *__restrict __delim)
- __THROW __nonnull ((2));
- __END_NAMESPACE_STD
-
- extern char *__strtok_r (char *__restrict __s,
- __const char *__restrict __delim,
- char **__restrict __save_ptr)
- __THROW __nonnull ((2, 3));
- #if defined __USE_POSIX || defined __USE_MISC
- extern char *strtok_r (char *__restrict __s, __const char *__restrict __delim,
- char **__restrict __save_ptr)
- __THROW __nonnull ((2, 3));
- #endif
- #ifdef __USE_GNU
-
- extern char *strcasestr (__const char *__haystack, __const char *__needle)
- __THROW __attribute_pure__ __nonnull ((1, 2));
- #endif
- #ifdef __USE_GNU
-
-
- extern void *memmem (__const void *__haystack, size_t __haystacklen,
- __const void *__needle, size_t __needlelen)
- __THROW __attribute_pure__ __nonnull ((1, 3));
-
- extern void *__mempcpy (void *__restrict __dest,
- __const void *__restrict __src, size_t __n)
- __THROW __nonnull ((1, 2));
- extern void *mempcpy (void *__restrict __dest,
- __const void *__restrict __src, size_t __n)
- __THROW __nonnull ((1, 2));
- #endif
- __BEGIN_NAMESPACE_STD
-
- extern size_t strlen (__const char *__s)
- __THROW __attribute_pure__ __nonnull ((1));
- __END_NAMESPACE_STD
- #ifdef __USE_GNU
-
- extern size_t strnlen (__const char *__string, size_t __maxlen)
- __THROW __attribute_pure__ __nonnull ((1));
- #endif
- __BEGIN_NAMESPACE_STD
-
- extern char *strerror (int __errnum) __THROW;
- __END_NAMESPACE_STD
-
- __END_DECLS
- #endif /* string.h */
1、字符串連接strcat,strncat,wcscat,wcsncat:將字符串src(或其前n個字符)連接到dest,后面兩個是寬字符版本。
-
- #include <string.h>
- #include <memcopy.h> /* 非標準頭文件,定義了reg_char類型 */
- #undef strcat
-
- char *
- strcat (dest, src)
- char *dest;
- const char *src;
- {
- char *s1 = dest;
- const char *s2 = src;
- reg_char c;
-
- do
- c = *s1++;
- while (c != '/0');
- s1 -= 2;
- do
- {
- c = *s2++;
- *++s1 = c;
- }
- while (c != '/0');
- return dest;
- }
- libc_hidden_builtin_def (strcat)
-
- #include <string.h>
- #ifdef _LIBC
- # include <memcopy.h> /* 非標準頭文件,定義了reg_char類型,就是char類型 */
- #else
- typedef char reg_char;
- #endif
- #undef strncat
-
-
- char *
- strncat (s1, s2, n)
- char *s1;
- const char *s2;
- size_t n;
- {
- reg_char c;
- char *s = s1;
- do
- c = *s1++;
- while (c != '/0');
- s1 -= 2;
- if (n >= 4)
- {
- size_t n4 = n >> 2;
- do
- {
- c = *s2++;
- *++s1 = c;
- if (c == '/0')
- return s;
- c = *s2++;
- *++s1 = c;
- if (c == '/0')
- return s;
- c = *s2++;
- *++s1 = c;
- if (c == '/0')
- return s;
- c = *s2++;
- *++s1 = c;
- if (c == '/0')
- return s;
- } while (--n4 > 0);
- n &= 3;
- }
- while (n > 0)
- {
- c = *s2++;
- *++s1 = c;
- if (c == '/0')
- return s;
- n--;
- }
- if (c != '/0')
- *++s1 = '/0';
- return s;
- }
解釋:
(1)strcat基本思想:把指針移到dest的終止符'/0'的前一個位置,然后掃描src的每個字符并連接到dest的后面。
(2)strncat基本思想:為減少掃描的循環次數以提高效率,對src的每4個字符作為一組來進行連接,讓n除以4,計算出循環次數n4。每次循環都要連接4個字符,總共連接了4*n4個字符,最后對剩下的幾個字符(最多3個)進行連接。若src的第n個字符不是終止符'/0',則連接的末尾還要補上一個終止符。
2、字符串比較strcmp,strncmp,wcscmp,wcsncmp:按照字典順序比較兩個字符串(或其前n個字符)的大小。
-
- #include <string.h>
- #include <memcopy.h> /* 非標準頭文件,定義了reg_char類型 */
- #undef strcmp
-
- int
- strcmp (p1, p2)
- const char *p1;
- const char *p2;
- {
- register const unsigned char *s1 = (const unsigned char *) p1;
- register const unsigned char *s2 = (const unsigned char *) p2;
- unsigned reg_char c1, c2;
- do
- {
- c1 = (unsigned char) *s1++;
- c2 = (unsigned char) *s2++;
- if (c1 == '/0')
- return c1 - c2;
- }
- while (c1 == c2);
- return c1 - c2;
- }
- libc_hidden_builtin_def (strcmp)
-
- #include <string.h>
- #include <memcopy.h>
- #undef strncmp
-
-
- int
- strncmp (s1, s2, n)
- const char *s1;
- const char *s2;
- size_t n;
- {
- unsigned reg_char c1 = '/0';
- unsigned reg_char c2 = '/0';
- if (n >= 4)
- {
- size_t n4 = n >> 2;
- do
- {
- c1 = (unsigned char) *s1++;
- c2 = (unsigned char) *s2++;
- if (c1 == '/0' || c1 != c2)
- return c1 - c2;
- c1 = (unsigned char) *s1++;
- c2 = (unsigned char) *s2++;
- if (c1 == '/0' || c1 != c2)
- return c1 - c2;
- c1 = (unsigned char) *s1++;
- c2 = (unsigned char) *s2++;
- if (c1 == '/0' || c1 != c2)
- return c1 - c2;
- c1 = (unsigned char) *s1++;
- c2 = (unsigned char) *s2++;
- if (c1 == '/0' || c1 != c2)
- return c1 - c2;
- } while (--n4 > 0);
- n &= 3;
- }
- while (n > 0)
- {
- c1 = (unsigned char) *s1++;
- c2 = (unsigned char) *s2++;
- if (c1 == '/0' || c1 != c2)
- return c1 - c2;
- n--;
- }
- return c1 - c2;
- }
- libc_hidden_builtin_def (strncmp)
解釋:
(1)strcmp基本思想:掃描兩個串,并對字符作相等比較,直到不相等時退出循環,返回這兩個字符的差值。
(2)strncmp基本思想:做比較操作,每4個字符作為一組來進行比較,以提高效率。掃描兩個串,每次循環時連續比較4個字符,直到比較完前n個字符。