C语言标准库函数学习(二)一一字符串操作函数

String Manipulation 字符串操作函数

strcat()

连接两个字符串

1
2
3
4
5
6
7
8
9
10
//1.strcat()
char *strcat(char *dest, const char *src) {
char *addr = dest;
//find '\0'
while (*dest) {
dest++;
}
while (*dest++ = *src++) {};
return addr;
}

相关:strncat:连接前n个字符串

strcmp()

比较两个字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//2.strcmp()
// > p
// = 0
// < n
int strcmp(const char *str1, const char *str2) {
while (*str1 == *str2) {
if (*str1 == '\0') {
return 0;
}
str1++;
str2++;
}
return *str1 - *str2;
}

相关:strncmp:比较前n个字符串

strcpy()

拷贝字符串内容到目的串

1
2
3
4
5
6
//3.strcpy()
char *strcpy(const char *dest, const char *src) {
char *addr = dest;
while (*dest++ = *src++) {};
return addr;
}

相关:strncpy:拷贝前n个字符串

strlen()

返回字符串str的长度(不包括’\0’)

1
2
3
4
5
6
7
8
9
//4.strlen()
unsigned int strlen(const char *str) {
unsigned len = 0;
while (*str != '\0') {
len++;
str++;
}
return len;
}

strchr()

>

1
2
3
4
5
6
7
//5.strchr()
char *strchr(const char *str, const char c) {
while (*str != '\0' && *str != c) {
str++;
}
return (*src == c ? str : NULL);
}

strrchr()

>

1
2
3
4
5
6
7
8
9
10
11
12
//6.strrchr() last find c
char *strrchr(const char *str, const char c) {
char *p = str + strlen(str);
while (p != str && *p != c) {
p--;
}
if (p == str && *p != c) {
return NULL;
} else {
return p;
}
}

strcspn()

在字符串pstr中搜寻strCharsret中所出现的字符,返回strCharset中出现的第一个字符在pstr中的出现位置。简单的说,若strcspn返回的数值为n,则代表字符串strCharsrt开头连续有n个字符不包含在pstr内的字符。

其实就是计算字符串str中连续有几个字符都不属于字符串accept

这个函数实现的非常巧妙,所以我们重点介绍一下

例如:对于字符’1’,其ASCII码味0x31,右移3位得到6,和7与运算得到1,也就是在map[6]中的第一位.

具体思想:
一个unsigend char有8位,拆为高5位与低3位。前5位的范围有0~32,所以申请32大小的数组map。直接将前5位映射成成数组下标,后3位范围0~7,正好是每一项char(8bit)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//7. tstrCSpn
//sublime
inline int tstrCSpn(const tChar *pStr, const tChar *pStrSet) {
// map有32个字节的大小,也就是256个bit,可把map堪称一个2维数组[32][8]
unsigned char map[32] = {0};
// 每个ASCII码(设为c)有8bit,把它分成2部分,低3位构成下标j(通过c&7(2进制为111)),
// 高5位构成下标i(通过c>>3得到)。这样在map[i][j]中置1表示字符存在
while (*pStrSet) {
map[*pStrSet >> 3] = map[*pStrSet >> 3] | (1 << (*pStrSet & 7));
pStrSet++;
}
map[0] = map[0] | 1;
int count;
while (!(map[*pStrSet >> 3] & (1 << (*pStrSet & 7)))) {
count++;
pStr++;
}
return count;
}

相关:strspn:返回后面字符串中第一个不在前者出现的下标

其实就是计算字符串str中连续有几个字符都属于字符串accept

strdup()

拷贝字符串到新建的内存

1
2
3
4
5
6
7
8
//8. strdup()
char *strdup(const char *str) {
char *p = NULL;
if (str && (p = (char *)malloc(strlen(str) + 1))) {
strcpy(p, str);
}
return p;
}

strrev()

反转字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//9. strrev()
char *strrev(const char *str) {
if (str == NULL) {
return NULL;
}
char *start = str;
char *end = str + strlen(str) - 1;
char temp;
while (start < end) {
temp = *start;
*start = *end;
*end = temp;
start++;
end--;
}
return str;
}

strstr()

查找字符串str2在str1中出现的位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//10. strstr()
char *strstr(const char str1, const char str2) {
int length1 = strlen(st1);
int length2 = strlen(st2);
while (length1 > length2) {
length1--;
if (!strncmp(str1, str2, length2)) {
return str1;
}
str1++;
}
return NULL;
}
inline tChar *tStrStr(tChar *pStr, tChar *pSubStr) {
tChar *b = pSubStr;
if (*b == NULL) {
return pStr;
}
tChar *a = NULL;
for ( ; *pStr != NULL; pStr++) {
if (*pStr != *b) {
continue;
}
a = pStr;
while (1) {
if (*b == NULL) {
return pStr;
}
if (*a++ != *b++) {
break;
}
}
b = pSubStr;
}
return NULL;
}