常用字符串函数

目录

长度不受限的字符串

strlen

strcpy

strcpy模拟实现

strcat

strcat模拟实现

strcmp

strcmp模拟实现

长度受限的字符串函数

strncpy

strncat

strncmp

其他类型的字符串函数

strstr

strtok

strerror


长度不受限的字符串函数

strlen

size_t strlen(char *str)

1
2
3
4
5
6
7
8
9
10
11
#include<string.h>
#include<stdio.h>
//strlen,记到\0为止
int main()
{
char arr[] = "abc";
char arr1[] = { 'a','b','c' };
int len = strlen(arr1);
printf("%d", len);//len是一个随机数,因为一直往后不知道什么时候会找到\0
return 0;
}

 strlen 的返回值为size_t无符号数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<stdio.h>
#inlcude<string.h>
int main()
{
if (strlen("abc") - strlen("abcdef") > 0)//3-6=-3,正常情况下是小于0,但无符号数-无符号数=无符号数,因此,-3是一个无符号数,最高位就不认为是符号位了
//是一个非常大的数,1000 0000 0000 0000 0000 0000 0000 0011
// 1111 1111 1111 1111 1111 1111 1111 1101
{
printf(">");
}
else
{
printf("<");
}
printf("%u", strlen("abc") - strlen("abcdef"));//无符号数把补码最高位1不认为是符号位,打印了出来
return 0;
}

strcpy

strcpy
注意事项
1.源字符串必须以\0结束,
2.同时会将字符串拷贝到目标空间里面去
3.目标空间必须足够大,来存放源字符串,否者程序就会崩溃
4.目标空间必须可变,源字符串必须不可变
4.arr1的字符大于arr2,arr1后面的也会消失

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
#inlcude<string.h>
int main()
{
char arr[20] = "#########";
char *p = "abcde";//这是一个常量字符串,不可被改变,p指向的是字符串首元素地址,h的地址
//arr="hello"这是错误的
strcpy(arr, p);//把p里面的内容拷贝到arr里面,同时arr后面内容也会消失,等同于一个p
char arr1[20];
char arr2[20]={'a','b','c'};//没有遇到\0,会一直找,就是一个随机值
strcpy(arr1, arr2);
printf("%s\n", arr);
printf("%s", arr1);
return 0;
}

strcpy的模拟实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
#inlcude<string.h>
char * mystrcpy(char *dest, const char *src)
//const修饰*src的内容就不能改变了,这里可以用char*来接收返回值,也可以用void
{
while (*dest++ = *src++)//*dest++到\0的时候就不会继续循环了
{
;
}
return *dest;
}
int main()
{
char arr[20] = { 0 };
char* p = "hello world";
mystrcpy(arr, p);
printf("%s", arr);
return 0;
}

strcat

strcat
把源字符串接到目标字符串的后面
源字符串必须以\0结尾
\0会被覆盖
会将源字符串的\0拷贝到目标空间里面去
目标空间必须足够大
目标空间必须可变

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
#inlcude<string.h>
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
strcat(arr1, arr2);//把world追加到arr1的后面
printf("%s", arr1);

return 0;
}
1
2
3
4
5
6
7
8
9
#include<stdio.h>
#inlcude<string.h>
int main()
{
char arr[20] = "abcd";
strcat(arr, arr);
printf("%s", arr);//无法在自己的后面追加自己,\0被覆盖了,不断重复的追加,找不到结束的\0了
return 0;
}

模拟实现strcat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<stdio.h>
#inlcude<string.h>
char * mystrcat(char *dest, char *src)
{
while (*dest)
{
dest++ ;
}//首先要先让dest指向\0处,指向\0为0就是假就不会继续循环了
//arr1拷贝到arr里面去
while (*dest++ = *src++)
{
;
}
return *dest;
}

int main()
{
char arr[20] = " hacb ";
char arr1[] = "world";
mystrcat(arr, arr1);
printf("%s", arr);
return 0;
}

strcmp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h>
#inlcude<string.h>
int main()
{
char* p = "abcd";
char *q = "abcdef";
if (p > q)//p和q比的地址
{
printf(">");
}
else
{
printf("<");
}

if("anc">"cbcd")//表达式分别是a和c的地址
int ret = strcmp("abbb", "abf");//b<c,返回<0
printf("%d", ret);//

return 0;
}

模拟实现strcmp

strcmp字符串比较函数
比较的是字符串的大小,(ascll)
int strcmp(const char *p1,const char *p2)
如果p1的那个字符大于p2的那个字符,就会返回>0,从左到右比较 

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
#include<stdio.h>
#inlcude<string.h>
#include<assert.h>
int mystrcmp(const char*s1, const char *s2)
{
assert(s1&&s2);//断言s1,s2不是空指针
while (*s1 == *s2)
{
if (*s1 == '\0'||*s2=='\0')//当发现其中有一个等于\0就返回0
{
return 0;
}
s1++;
s2++;
}
if (*s1 > *s2)
{
return 1;
}
else
{
return -1;
}
return *s1 - *s2;
}
int main()
{
char *p = "abcdef";
char *q = "abbb";
int ret = mystrcmp(p, q);
printf("%d", ret);
return 0;
}

长度受限的字符串函数

strncpy

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
#inlcude<string.h>
int main()
{
char arr1[20] = "abcdef";
char arr2[] = "qwer";
//strncpy(arr1, arr2, 2);//把arr2的前两个拷贝到arr1里面//qwcdef
//strcpy(arr1, arr2);
strncpy(arr1, arr2, 6);//arr2拷贝过去\0也会被拷贝过去,arr2的字符小于6,但也只会拷贝arr2所有元素加\0
printf("%s", arr1);
return 0;
}

strncat

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
#inlcude<string.h>
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
//strncat(arr1, arr2, 2);//在arr后面2个元素
strncat(arr1, arr2, 10);//hello world\0,即使数多余arr2,也只会追加一个

printf("%s", arr1);
return 0;
}

strncmp

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
#inlcude<string.h>
int main()
{
char *p = "abcdef";
char *q = "abcqwert";
int ret = strncmp(p, q, 4);//选前四个进行一一比较
printf("%d", ret);
return 0;
}

其他的一些字符串函数

strstr

char *strstr(const char *str1,const char* str2)
如果找到了就会返回str2在str1中首地址,否则返回空指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
#inlcude<string.h>
int main()
{
char arr1[] = "abcdefabcdef";
char arr2[] = "bcd";
char *ret = strstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到");

}
else
{
printf("找到了");
}
return 0;
}

模拟实现strstr

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
41
42
43
44
45
#include<assert.h>
#include<stdio.h>
#inlcude<string.h>
char *mystrstr(const char *str1, const char *str2)
{
assert(str1&&str2);
const char *s1 = NULL;//s1来移动判断是否有和str2有相同元素
const char *s2 = NULL;//s2如果能走到\0就找到了
char *cp = str1;//cp来记录如果s1走下去没有,cp就往下走一位
while (*cp)
{
s1 = cp;//s1从cp的位置的位置开始走
s2 = str2;//s2从str2的首元素位置开始走
while (*s1&&*s2 && (*s1 == *s2))//*s1走到\0或者*s2走到\0就不继续循环了,
{
//*s1和*s2相等的话,就开始循环,循环到*s1或者*s其中一方到\0就跳出循环
s1++;
s2++;
}
if (*s2 == '\0')//如果*s到达\0,就代表找到了,
{
return cp;
}
cp++;

}
return NULL;

}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "cde";
char *ret = mystrstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到");

}
else
{
printf("找到");
}
return 0;
}

strtok

strtok(char *str,const char*sep)
1990.02.19//..就是分隔符号的集合
sep参数是一个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,他包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针首元素地址,
strtok函数的第一个参数部位NULL,函数找到str中第一个标记,strtok函数保存他在字符串中的位置
strtok函数第一个参数为NULL,函数将同一个字符串被保存的位置开始,查找下一个标记,
如果不存在更多的标记,则返回NULL指针 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "1990.02.20";
char *p = "..";
char tmp[20] = { 0 };
strcpy(tmp, arr);//tmp中拷贝了arr的元素
char* ret = NULL;//在没有考虑好要赋什么值的时候将其置为空指针
ret=strtok(tmp, p);//tmp到第一个分隔符停止补上\0
printf("%s\n", ret);
ret = strtok(NULL, p);//此后每次使用第一个位置都是NULL
printf("%s\n", ret);
ret = strtok(NULL, p);
printf("%s", ret);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "1990.02.20";
char *p = "..";
char tmp[20] = { 0 };
strcpy(tmp, arr);
char *ret = NULL;
for (ret = strtok(tmp, p); ret != NULL; ret = strtok(NULL, p))//ret比到最后就变成空指针,不是空指针就不会继续循环
{
printf("%s\n",ret);
}
return 0;
}

strerror

strerror//把错误码翻译成对应的错误信息
char *strerror(int errnum)
errno是一个全局的错误码
要包含头文件
#include<>
使用库函数的时候,有可能会调用库函数失败的时候,都会设置一个错误码, int errno 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
int main()
{
printf("%s\n", strerror(0));
printf("%s\n", strerror(1));
printf("%s\n", strerror(2));
printf("%s\n", strerror(3));
printf("%s\n", strerror(4));
printf("%s\n", strerror(5));
FILE * pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("%s",strerror(errno));
return 1;
}
fclose(pf);
pf = NULL;
return 0;
}

只会我会将代码上传到我的gitee仓库上


常用字符串函数
http://example.com/2021/10/30/常用字符串函数/
作者
Zevin
发布于
2021年10月30日
许可协议