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个字符。