C语言处理字符串极为不便,幸好库函数提供了还算丰富的处理字符串的函数。有一些函数我们平时不大用的到,不过了解一下总是好的,知道有这么个东西,下次要用的时候再去查一下手册就好了。
这里介绍的函数主要有:strcat, strcmp, strcasecmp, strcpy, strdup, strlen, strchr, strrchr, strstr, strpbrk, strspn, strcspn, strtok. 在本章的最后还会给出这些库函数的具体实现,以应付一些企业的面试。
文章共分四个部分,第一部分直接列出了常用的字符串处理函数,由于这些都是大家平时接触的比较多的,在此不再多说;第二部分介绍了不太常用的字符串处理函数,并给出了具体示例,很多函数看名字很难猜到它的具体作用,但是一个小小的例子就能解释得很清楚;第三部分给出了这些函数的具体实现,大部分参考网上个人认为已经不错的实现,部分是查看glibc源代码后,简化得来的程序;第四部分作者非常道德的给出了参考资料。
常用的字符串处理函数:
char *strcat(char *s1, const char *s2);
char *strncat(char *s1, const char *s2);size_t strlen(const char *s1);
不太常用的字符串处理函数:
//the strdup() function allocates memory and copies into it the string addressed s1. including the terminating null character.
//It is the use's responsibility to free the allocated storage by calling free()
char *strdup(const char *s1);
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char* argv[]) { char str[] = "this is a example"; char *p = NULL; if ((p = strdup(str)) != NULL) { printf("strlen(p) = %d \t sizeof(p) = %d\n", strlen(p), sizeof(p)); printf("strlen(str) = %d\t sizeof(str) = %d\n", strlen(str), sizeof(str)); if ( p == str ) { puts("p == str"); } else { puts("p != str"); } } free(p); p = NULL; return 0; }output:
lalor@ubuntu:~/temp$ ./a.out
strlen(p) = 17 sizeof(p) = 4
strlen(str) = 17 sizeof(str) = 18
p != str
char *strchr(const char *s1, int c);
#include <stdio.h> #include <string.h> int main(int argc, char* argv[]) { char str[] = "This is a sample string"; char *pch; pch = strchr(str, 's'); while (pch != NULL) { printf("found at %d\n", pch - str + 1); pch = strchr(pch + 1, 's'); } return 0; }output:
char *strrchr(const char *s1, int c);
#include <stdio.h> #include <string.h> int main(int argc, char* argv[]) { char str[] = "This is a sample string"; char *pch; pch = strrchr(str, 's'); printf("found at %d\n", pch - str + 1); return 0; }output:
#include <stdio.h> #include <string.h> int main(int argc, char* argv[]) { char str[] = "This is a simple string. It's really a simple string"; char *pch = NULL; pch = strstr(str, "simple"); while (pch != NULL) { printf("found %d\n", pch - str + 1); pch = strstr(pch+1, "simple"); } return 0; }output:
#include <stdio.h> #include <string.h> int main(int argc, char* argv[]) { char str[] = "This is a simple string."; char key[] = "aeiou"; char *pch = NULL; printf("Vowels in '%s' : ", str); pch = strpbrk(str, key); while (pch != NULL) { printf("%c ", *pch); pch = strpbrk(pch + 1, key); } printf("\n"); return 0; }output:
/*
* scans s1 for the first occurrence of any of the characters that are part ofsize_t strcspn(const char *s1, const char *s2);
#include <stdio.h> #include <string.h> int main () { char str[] = "fcba73"; char keys[] = "1234567890"; int i; i = strcspn (str,keys); printf ("The first number in str is at position %d.\n",i+1); return 0; }output:
// return the length of the initial portion of s1 containing only characters
// that appear in s2
size_t strspn(const char *s1, const char *s2);
#include <stdio.h> #include <string.h> int main () { int i; char strtext[] = "129th"; char cset[] = "1234567890"; i = strspn (strtext,cset); printf ("The length of initial number is %d.\n",i); return 0; }output:
lalor@ubuntu:~/temp$ ./a.out
The length of initial number is 3.
//split string into tokens
char *strtok( char *str, const char *delimiters);
#include <stdio.h> #include <string.h> int main(int argc, char* argv[]) { char str[] = " - this, a sample string."; char *pch = NULL; printf("Splitting string \" %s \" into tokens:\n", str); pch = strtok(str, " ,.-");//first call while (pch != NULL) { printf("%s\n", pch); pch = strtok(NULL, " ,.-");//later call, the second time use strtok, first argument must be NULL } //note: strtok will modify the first string printf("strlen(str) = %d\tsizeof(str)/sizeof(char) = %d\n", strlen(str), sizeof(str)/sizeof(char)); return 0; }output:
lalor@ubuntu:~/temp$ ./a.out
Splitting string " - this, a sample string. " into tokens:
this
a
sample
string
strlen(str) = 7 sizeof(str)/sizeof(char) = 26
函数源码:
char *strcat(char *s1, const char *s2);
char* strcat(char *strDes, const char *strSrc)
{ assert((strDes != NULL) && (strSrc != NULL)); char *address = strDes; while (*strDes != '\0') { ++strDes; } while ((*strDes++ = *strSrc++) != '\0') { NULL; } return address; }
char* strncat(char *dest, const char*str, size_t n) { size_t dest_len = strlen(dest); size_t i; for (i = 0; i < n && src[i] != '\0'; i++) { dest[dest_len + i] = src[i]; } dest[dest_len + i] = '\0'; return dest; }
int strcmp(const char *s, const char *t) { assert((s != NULL) && (t != NULL)) while (*s && *t && *s == *t) { s++; t++; } return (*s - *t); }
int strncmp(const char *s1, const char *s2, size_t length);
int strcmp(const char *s, const char *t, size_t n) { assert((s != NULL) && (t != NULL) && n > 0) while (*s && *t && *s == *t && n--) { s++; t++; } return (*s - *t); }
int strcmp(const char *s, const char *t) { assert((s != NULL) && (t != NULL)) char c1, c2; while (*s && *t ) { c1 = TOLOWER(*s); c2 = TOLOWER(*t); if (c1 != c2) { break; } else { s++; t++; } } return (c1 - c2); }
int strncasecmp(const char *s1, const char *s2, size_t length);
int strcmp(const char *s, const char *t, size_t n) { assert((s != NULL) && (t != NULL) && n > 0) char c1, c2; while (*s && *t && n--) { c1 = TOLOWER(*s); c2 = TOLOWER(*t); if (c1 != c2) { break; } else { s++; t++; } } return (c1 - c2); }
char *strncpy(char *s1, const char *s2, size_t length);
The strncpy() function is similar, except that at most n bytes of src
are copied. Warning: If there is no null byte among the first n bytes
of src, the string placed in dest will not be null-terminated.
If the length of src is less than n, strncpy() pads the remainder of
dest with null bytes.
char * strncpy(char *dest, const char *src, size_t n) { size_t i; for (i = 0; i < n && src[i] != '\0'; i++) dest[i] = src[i]; for ( ; i < n; i++) dest[i] = '\0'; return dest; }
int strlen(const char *str) { assert(str != NULL); int len = 0; while (*str++ != '\0') { len++; } return len; }
/* Duplicate S, returning an identical malloc'd string. */ char * __strdup (const char *s) { size_t len = strlen (s) + 1; void *new = malloc (len); if (new == NULL) return NULL; return (char *) memcpy (new, s, len); }
char * strchr(const char *str, int c) { assert(str != NULL); for ( ; *str != (char)c; ++str) { if (*str == '\0') { return NULL; } } return str; }
/* Find the last occurrence of C in S. */ char * strrchr (const char *s, int c) { register const char *found, *p; c = (unsigned char) c; /* Since strchr is fast, we use it rather than the obvious loop. */ if (c == '\0') return strchr (s, '\0'); found = NULL; while ((p = strchr (s, c)) != NULL) { found = p; s = p + 1; } return (char *) found; }
/* Find the first occurrence in S of any character in ACCEPT. */ char * strpbrk (s, accept) const char *s; const char *accept; { while (*s != '\0') { const char *a = accept; while (*a != '\0') if (*a++ == *s) return (char *) s; ++s; } return NULL; }
/* Return the length of the maximum initial segment of S which contains no characters from REJECT. */ size_t strcspn (s, reject) const char *s; const char *reject; { size_t count = 0; while (*s != '\0') if (strchr (reject, *s++) == NULL) ++count; else return count; return count; }
/* Return the length of the maximum initial segment of S which contains only characters in ACCEPT. */ size_t strspn (s, accept) const char *s; const char *accept; { const char *p; const char *a; size_t count = 0; for (p = s; *p != '\0'; ++p) { for (a = accept; *a != '\0'; ++a) if (*p == *a) break; if (*a == '\0') return count; else ++count; } return count; }
参考资料:
1.c语言手册http://www.cplusplus.com/reference/clibrary/cstring/strcmp/
2. glibc源代码,下载地址:ftp://ftp.gnu.org/gnu/glibc
3. 周磊的整理的面试笔试题目http://www.cnblogs.com/v-July-v/