C语言字符字符串函数:strcpy、strcat、strcmp介绍和模拟实现以及stnrcpy、strncat、strncmp介绍(近万字详解,建议三连收藏)
函数头文件:string.h函数参数:① char * destination:追加目的空间的地址②const char * source:源字符串的地址返回值类型:char*返回值:返回目的字符串的地址也就是考到到某个地方,这个某个地方的地址。函数功能:将源字符串直到\0以前的所有内容追加到目的空间,包括\0.源字符串必须以 '\0' 结束。会将源字符串中的 '\0' 追加到目标空间。目标空间必
目录
4.strncpy(字符串拷贝函数,可以指定拷贝的字符数目)
1.strcpy(字符串拷贝函数)
1.1函数介绍
函数头文件:string.h
函数参数:① char * destination:拷贝目的空间的地址
②const char * source:源字符串的地址
返回值类型:char*
返回值:返回目的字符串的地址也就是考到到某个地方,这个某个地方的地址。
函数功能:将源字符串直到\0以前的所有内容拷贝到目的空间,包括\0.
源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变
1.2函数使用示范
int main()
{
char arr1[20] = { 0 };
char arr2[] = "hello world";
char arr3[6] = { 'a','b','c','d','e','f' };
strcpy(arr1, arr2);
printf("%s\n", arr1);
strcpy(arr1, arr3);
printf("%s\n", arr1);
char arr4[6] = { 'a','b','c','d','e','\0' };
strcpy(arr1, arr4);
printf("%s\n", arr1);
return 0;
}
1.3函数模拟实现
实现思想:
将目的空间的起始地址保存后,因为后续返回的是目的空间的地址。利用指针遍历将源字符串的内容赋值给目的空间,直到源字符串的指针解引用得到\0.
参数部分:由于传递的是字符串的地址,所以用char* 类型的指针接收,对于源字符串来说,只是遍历但是不用修改其值,可以用const来修饰。接下来我们看实现
char* my_strcpy(char* dest, const char* src)
{
char* ret = dest;
//保存目的空间的地址,后续返回的是目的空间的地址
//对于判断条件来说,要对指针解引用要保证指针的有效性,所以这里我们要断言一下
assert(dest != NULL);
assert(src != NULL);
while (*src != '\0')
{
*dest = *src;
src++;
dest++;
}
*dest = *src;//\0
return ret;
}
int main()
{
char arr1[20] = "hello world";
char arr2[] = "xxxxx";
my_strcpy(arr1, arr2);
printf(“%s\n”,arr1);
return 0;
}
正是因为我们拷贝的时候将\0也拷贝进入了字符串1,所以1打印的时候只打印了前五个元素,但是内存里面是这样的
当然我们的循环遍历部分也可以改造得简单一些:
while (*dest++ = *src++)
{
;
}
补充:
返回值写成char* 是为了实现链式访问 比如:printf("%s\n",my_strcpy(arr1,arr2);
因为返回的是目的空间首元素的地址
2.strcat(字符串追加函数)
2.1函数介绍
函数头文件:string.h
函数参数:① char * destination:追加目的空间的地址
②const char * source:源字符串的地址
返回值类型:char*
返回值:返回目的字符串的地址也就是考到到某个地方,这个某个地方的地址。
函数功能:将源字符串直到\0以前的所有内容追加到目的空间,包括\0.
源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 追加到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变
2.2函数使用示范:
引入例子:现在有目标空间里有hello,但是空间大,希望追加一个world,追加在后面
工作原理:找到目标地址的\0,然后追加
源和目标都有\0,都可修改,然后,目标空间要走足够大
int main()
{
char arr1[20] = "hello";
char arr2[] = "world";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
2.3函数模拟实现 :
实现思想:先利用目标空间首元素这个指针来找到目标空间字符串中的\0,然后从这个地址开始将源字符串通过指针遍历放到目的空间中,直到找到源字符串的\0.
参数部分:由于传递的是字符串的地址,所以用char* 类型的指针接收,对于源字符串来说,只是遍历但是不用修改其值,可以用const来修饰。接下来我们看实现
char * my_strcat(char* dest, const char* src)
{
//断言
assert(dest);
assert(src);//等于空指针就是0,为假就报错了
char* ret = dest;
//1.首先找目标空间中的\0
while (*dest)
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return ret;
}
//
int main()
{
char arr1[20] = "hello";
char arr2[] = "world";
//strcat(arr1, arr2);
my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
实现效果:
2.4思考:字符串可以自己给自己追加吗?
分析:当我们自己给自己追加的时候,字符串首元素的地址即是目的地址也是源地址,等目的地址找到\0, 此时开始追加,第一步就将h赋值给了\0的地址空间,让后des++,src++,依次赋值e,l,l....,最后我们发现\0就消失了,整个程序就陷入了死循环,当指针增加超过了这个数组的空间就越界了。
3.strcmp(字符串比较函数)
3.1函数介绍
函数头文件:string.h
函数参数:①const char * str1:字符串1的地址
②,const char * str2:字符串2的地址
返回值类型:int
返回值:第一个字符串小于第二个字符串就返回一个<0的数
第一个字符串等于第二个字符串就返回0
第一个字符串大于第二个字符串就返回一个>0的数
函数功能:
将 C字符串 str1 与 C字符串 str2 进行比较。从传递的地址处开始比较每个字符串的第一个字符(比较的是字符的ACSII码值)。如果它们彼此相等,则继续以下对,直到字符不同或同时达到\0字符。
3.2函数使用示范
int main()
{
int ret = strcmp("abq", "abq");
printf("%d\n", ret);
return 0;
}
3.3函数模拟实现
思想:通过两个指针循环遍历比较对应字符的acsii码值。
参数部分由于只做比较,不修改值所以可以用const修饰
int my_strcmp(const char* str1, const char* str2)
{
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
if (*str1 > *str2)
{
return 1;
}
else
return -1;
}
int main()
{
int ret = my_strcmp("abq", "abq");
printf("%d\n", ret);
return 0;
}
分割:
前面三个函数都是长度不受限制的字符串函数,只关心\0的位置,就是直接拷贝或者追加默认到结尾。
下面介绍长度受限制的字符串函数,唯一的区别就是可以控制拷贝的字符串长度,可以控制追加和比较的字符串的长度。这里做出介绍,不模拟实现,大家可以根据前三个函数和参数介绍进行使用与练习。
4.strncpy(字符串拷贝函数,可以指定拷贝的字符数目)
4.1函数介绍
函数头文件:string.h
函数参数:① char * destination:拷贝目的空间的地址
②const char * source:源字符串的地址
③num:无符号整型,表示要拷贝num个字符从源字符串到目标空间
返回值类型:char*
返回值:返回目的字符串的地址也就是考到到某个地方,这个某个地方的地址。
函数功能:将源字符串中前num个字符拷贝到目的空间,但是不会在拷贝完后补充\0
目标空间必须足够大,以确保能存放源字符串。目标空间必须可变如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
4.2函数使用示范
int main()
{
char arr1[20] = { 0 };
char arr2[] = "hello world";
strncpy(arr1, arr2,3);
printf("%s\n", arr1);
return 0;
}
看一下拷贝后的内存空间:
5.strncat(字符串追加函数可以指定追加的字符数目)
5.1函数介绍
函数头文件:string.h
函数参数:① char * destination:追加目的空间的地址
②const char * source:源字符串的地址
③要追加的字符个数
返回值类型:char*
返回值:返回目的字符串的地址也就是考到到某个地方,这个某个地方的地址。
函数功能:将源的前 num 个字符附加到目标,以及\0字符。只把要求的串的内容追加完成就行,追加完成会在后面补上\0.
5.2函数使用示范
int main()
{
char str1[20];
char str2[20];
strcpy(str1, "To be ");
strcpy(str2, "orcd");
strncat(str1, str2, 6);
puts(str1);
return 0;
}
6.strncmp(字符串比较函数,可以限定比较的字符数)
6.1函数介绍
函数头文件:string.h
函数参数:①const char * str1:字符串1的地址
②,const char * str2:字符串2的地址
③无符号整型num,表示要比较的前num个字符
返回值类型:int
返回值:第一个字符串小于第二个字符串就返回一个<0的数
第一个字符串等于第二个字符串就返回0
第一个字符串大于第二个字符串就返回一个>0的数
函数功能:
将 C字符串 str1 与 C字符串 str2 进行比较。从传递的地址处开始比较每个字符串的第一个字符(比较的是字符的ACSII码值)。如果它们彼此相等,则继续以下对,直到字符不同或者第num个字符比较完
6.2函数的实现
int main ()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
int n;
puts ("Looking for R2 astromech droids...");
for (n=0 ; n<3 ; n++)
if (strncmp (str[n],"R2xx",2) == 0)
{
printf ("found %s\n",str[n]);
}
return 0;
}
7.strstr(字符串中找子字符串函数:图解实现)
7.1函数介绍
函数头文件:string.h
函数参数:① str1:目标字符串的地址
②str2:被查找的字符串的地址
返回值类型:char*
返回值:返回指向 str1 中 str2 第一次出现的指针
函数功能:
查找子字符串返回指向 str1 中 str2 第一次出现的指针,如果 str2 不是 str1 的一部分,则返回 null 指针。
匹配过程不包括终止 null 字符,但到此为止。
7.2函数演示使用
此示例在 str 中搜索“simple”子字符串,并将该词替换为“sample”。
输出:
This is a sample string
|
int main ()
{
char str[] ="This is a simple string";
char * pch;
pch = strstr (str,"simple");
if (pch != NULL)
strncpy (pch,"sample",6);
puts (str);
return 0;
}
7.3函数模拟实现
函数实现思想:
char* my_strstr(const char* str1, const char* str2)
{
char* cp = (char*)str1;//用来记录从目标字符串开始匹配的位置
char* s1 = cp;//用来在目标字符串中从开始匹配的位置进行匹配
char* s2 = (char*)str2;//用来配合目标字符串之中的查找
if (*str2 =='\0')
{
return (char* )str1;
}
while (*cp)//循环条件为当开始匹配的位置不为空指针,为空说明目标字符串已经遍历到了末尾了
{
//开始进行从匹配起始位置进行一个字一个字符的检查
s1 = cp;//将起始位置赋值给s1,用来进行遍历匹配
s2 = (char* )str2;
while (*(char*)s1 && *(char*)s2 && *(char*)s1 == *(char*)s2)//
{
(char*)s1++;
(char*)s2++;
//当地址加加的时候,有可能目标地址来到末尾或者源字符串来到末尾,二者都应该结束循环,不进入循环
//
}
if (*(char*)s2 == '\0')
{
return cp;//循环结束,只有源字符串遍历到最后一位找到了,返回目标字符串的起始匹配地址
}
cp++;//当循环结束没有找到,那就将起始匹配地址+!
}
return NULL;//当目标字符串遍历完了都没有匹配成功,那就找不到返回空指针
}
int main()
{
char arr1[] = "abbbcdef ";
char arr2[] = "bbc";
char* ret = my_strstr(arr1, arr2);
if (ret != NULL)
{
printf("%s\n", ret);
}
else
{
printf("找不到\n");
}
return 0;
}
8.strtok函数(实现字符分割的函数)
8.1函数介绍
sep参数是个字符串,定义了用作分隔符的字符集合第一个参数指定一个字符串,它包含了0,个或者多个由sep字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用\0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
如果strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针
8.2函数的使用举例
int main()
{
char arr[] = "ouybnji@jdkdm.com";
char copy[20];
strcpy(copy, arr);
char sep[] = { "@." };
char* ret = NULL;
for (ret = strtok(copy, sep); ret != NULL; ret = strtok(NULL, sep))
{
printf("%s\n", ret);
}
return 0;
}
由于strtok函数会改变原字符串的内容,所以将字符串拷贝进copy数组里面,sep作为字符参数传入,把copy中的字符串以这两个字符进行分割,不管分隔符的顺序。第一次传参传入的1是copy数组的地址,函数找到分割符@将@改为\0,返回ouybnji的地址,第二次传参第一个函数即是空指针,函数里面保存的是j的地址,从这个地址去寻找分割符号,找到.,进行分割,返回j的地址,第三次传参传入空指针,函数里面保存了c的地址,找到\0没有找到分割符号返回null.
9.strerror(打印错误信息函数)
9.1函数介绍
库函数执行的时候会发生错误,会将错误码放在errnum这个变量中,errno是C语言提供的全局变量,错误信息表示的错误
函数:返回错误码,所对应的错误信息,返回来错误信息首字符的地址。
9.2函数实现例子
10.字符分类函数
这类函数很简单,控制字符属于什么关系,比如大写字符,小写字符,数字字符,如果判断为真就返回一个非0的值,如果判断为假函数就返回0.
这类函数的头文件包含为:ctype.h
我们来看一个:
函数:
检查字符是否为大写字母检查参数 c 是否为大写字母。
返回值:如果 c 确实是大写的字母,则与零不同的值(即 true)。否则为零(即 false)。
函数有:
函数 如果他的参数符合下列条件就返回真
iscntrl 任何控制字符
isspace 空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v'
isdigit 十进制数字 0~9
isxdigit 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
islower 小写字母a~z
isupper 大写字母A~Z
isalpha 字母a~z或A~Z
isalnum 字母或者数字,a~z,A~Z,0~9
ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph 任何图形字符
isprint 任何可打印字符,包括图形字符和空白字符
11.字符转换函数
int tolower ( int c );
int toupper ( int c )
函数功能:
将大写字母转换为小写字母如果 c 是大写字母并且具有小写等效字母,则将 c 转换为小写等效字母。如果无法进行此类转换,则返回的值为 c 不变。
函数:将小写字母转换为大写字母如果 c 是小写字母并且具有大写等效字母,则将 c 转换为大写等效字母。如果无法进行此类转换,则返回的值为 c 不变。
*10、11两种函数搭配实例
int main()
{
char arr[20] = { 0 };
gets(arr);//这里使用gets函数获取字符串空格也可以直接读
char* p = arr;
while (*p)
{
if (isupper(*p))
{
*p = tolower(*p);
}
p++;
}
printf("%s\n", arr);
return 0;
}
12.结语
以上就是本期的所有内容,知识含量蛮多,大家可以配合解释和原码运行理解。创作不易,大家如果觉得还可以的话,欢迎大家三连,有问题的地方欢迎大家指正,一起交流学习,一起成长,我是nicn,正在c++方向前行的新手,感谢大家的关注与喜欢。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)