目录
前言
C语言中有着许多字符串函数,使用这些函数可以对字符串进行各种各样的操作,本篇小鸥将从函数原型讲起,依次介绍字符串函数的返回值、参数、作用、使用方法、注意事项和模拟实现。
注:字符串函数的使用需要包含头文件。
#include <string.h>
字符串函数
strlen函数介绍及模拟实现
strlen函数介绍:
函数原型:
返回值:size_t(一种无符号整型,对应占位符为%zd)类型,返回的是计算的字符个数;
参数:const修饰的char* 类型的字符指针;
作用:计算字符串长度;
使用:附代码:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "abc";
char* pc1 = "strlen";
size_t len = strlen(arr1);//arr1是数组名,指向首元素地址
printf("%zd\n", len);
printf("%zd\n", strlen(pc1));//指针的讲解中我们知道:pc1指向的就是"strlen"中字符s的地址
char* pc2 = "str\0len";
printf("%zd\n", strlen(pc2));
return 0;
}
从上文的三个结果对比可以看出:strlen函数计算的是其参数指向的地址位置,到遇到第一个\0之前的所有字符的个数。当strlen函数遇到\0时就会停下来,并返回计算的字符总个数。
strlen模拟实现:
//1.计数器的方式
#include <stdio.h>
size_t my_strlen(const char* p)
{
int count = 0;
while (*p != '\0')
{
count++;
p++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
size_t ret = my_strlen(arr);
printf("%zd", ret);
return 0;
}
//2.指针-指针的方式
#include <stdio.h>
size_t my_strlen(const char* p)
{
char* pstrat = p;
while (*p != '\0')
{
p++;
}
return (p - pstrat);
}
int main()
{
char arr[] = "abcdef";
size_t ret = my_strlen(arr);
printf("%zd", ret);
return 0;
}
//3.递归方法
#include <stdio.h>
size_t my_strlen(const char* p)
{
if (*p != '\0')
{
return (1 + my_strlen(p + 1));
}
else
return 0;
}
int main()
{
char arr[] = "abcdef";
size_t ret = my_strlen(arr);
printf("%zd", ret);
return 0;
}
strcpy与strncpy函数介绍及模拟实现
strcpy与strncpy函数介绍:
函数原型:
返回值:char*类型,返回的是目标空间的起始地址;
参数:strcpy:目标空间起始地址,源空间起始地址;
strncpy:目标空间起始地址,源空间起始地址,限制长度;
作用:将源空间中的字符拷贝到目标空间中(strncpy可以自定义拷贝长度),并返回目标空间的起始地址;
使用及注意事项:
strcpy:
附代码:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = { 0 };
char arr2[] = "hello word!";
char* ret = strcpy(arr1, arr2);
//目标空间在前,源空间在后
printf("%s\n", ret);
printf("%s\n", arr1);
return 0;
}
strncpy:
注意:
1.strcpy和strncpy的结束标志也都是\0,遇到第一个\0之后就结束拷贝,返回目标空间的起始地址;
2.目标空间的大小应该足够大;
3.strncpy函数在第三个参数num大于源空间字符串长度时,不够的会在用\0补齐,直到num个时停止;而num小于源空间函数时,只会拷贝相应个数的字符个数,且不会在拷贝的末尾加\0。
strcpy与strncpy模拟实现:
strcpy
#include <stdio.h>
#include <assert.h>
//模拟实现strcpy
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src);//断言是否为空指针
char* ret = dest;
while (*dest++ = *src++)
;
return ret;
}
int main()
{
char arr1[] = "Hello world";
char arr2[20] = "xxxxxxxxxxxxxxxx";
char* ret = my_strcpy(arr2, arr1);
printf("%s", ret);
return 0;
}
strncpy
#include <stdio.h>
#include <assert.h>
char* my_strncpy(char* dest, const char* src, size_t num)
{
char* ret = dest;
assert(dest && src);
while (num--)
{
if (*src != '\0')//当num还没到0,源字符串也没到\0时,就给目标空间拷贝*src
{
*dest++ = *src++;
}
else if(*src == '\0')//若源空间先到\0,则在目标空间中补\0,直到num为0
*dest++ = '\0';
}
return ret;
}
int main()
{
char arr1[20];
char arr2[] = "aafdsdsa";
char* ret = my_strncpy(arr1,arr2,10);//当num小于源字符串时,不会在目标空间后补\0
printf("%s", ret);
return 0;
}
strcat与strncat函数介绍及模拟实现
strcat与strncat函数介绍:
函数原型:
返回值:char*类型,返回的是目标空间的起始地址;
参数:strcat:目标空间起始地址,源空间起始地址;
strncat:目标空间起始地址,源空间起始地址,限制长度;
作用:在目标空间中追加源空间中的字符串(strncat可自定义追加长度),并返回目标空间的起始地址;
使用及注意事项:
strcat:
附代码:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "hello_";
char arr2[] = "word!";
char* ret = strcat(arr1, arr2);
printf("%s\n", ret);
printf("%s\n", arr1);
return 0;
}
strncat:
注意:
1.由上文对比图可知,函数结束标志为\0,先找到目标空间中的第一个\0,然后再将源空间中的字符串追加到目标空间中,直到找到第一个\0为止结束;
2.目标空间的大小应该足够大;
3.strncat函数,当num大于源空间中字符串长度时,只会追加源空间字符串相应的长度,不会补\0以满足参数num的大小(和strncpy区别),而num小于源空间字符串长度时,只追加num相应长度的字符个数,然后自动在追加末尾加上\0。
strcat与strncat模拟实现:
strcat
#include <stdio.h>
#include <assert.h>
//模拟实现strcat
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*dest != '\0')//先找到需要进行追加字符串的目标地址中的\0,用于判断追加字符串的起始位置
dest++;
while (*dest++ = *src++)//和模拟strcpy时相同的方法将需要追加的内容追加到目标字符串的后面
;
return ret;
}
int main()
{
char arr1[20] = "Hello ";
char arr2[] = "wrold!";
char* ret = my_strcat(arr1, arr2);
printf("%s", ret);
return 0;
}
strncat
#include <stdio.h>
#include <assert.h>
char* my_strncat(char* dest, const char* src, size_t num)
{
assert(dest && src);
char* ret = dest;
while (*dest++)//dest指向\0后还会往后++一次
;
dest -= 1;//让dest回到\0的位置
while (num--)
{
*dest++ = *src++;
if (!(*(src-1)))//当src指向的字符串小于num时,*src追加给目标空间\0之前的最后一个数后,由于后置++
return ret;//如果直接判断*src会导致\0没有追加到目标空间中,所以判断*src-1
}
*(dest + 1) = 0;//当num小于src指向的字符串时,追加结束在目标字符串后加上\0
return ret;
}
int main()
{
char arr1[20] = "Holle_";
char arr2[] = "World!";
char* ret = my_strncat(arr1, arr2, 8);
printf("%s", ret);
return 0;
}
strcmp与strncmp函数介绍及模拟实现
strcmp与strncmp函数介绍:
函数原型:
返回值:int类型,返回的值有三类 :1.字符串1大于字符串2时,返回大于零的数;2.字符串1=字符串2时,返回0;3.字符串1<字符串2时, 返回小于零的数;
参数:strcmp:字符串1的起始地址,字符串2的起始地址;
strncmp:字符串1的起始地址,字符串2的起始地址,限制长度;
作用:比较两个字符串的大小 。
使用:
附代码:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "hello_";
char arr2[] = "word!";
char* ret = strcat(arr1, arr2);
printf("%s\n", ret);
printf("%s\n", arr1);
return 0;
}
strncmp:
注意:
1.strcmp与strncmp两个函数在比较字符串大小时,是从参数传入的地址位置开始,一个字符一个字符的比较大小,本质是比较两个字符ASCII码的大小( \0的ASCII码值为0);
2.strncmp函数比较的长度就是由参数num决定的。
strcmp与strncmp模拟实现:
strcmp
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);//断言是否为NULL
while (*str1 == *str2)//相等就继续比较下一个字符
{
if (*str1 == '\0')//相等且等于\0 则说明两个字符串相同
return 0;//直接返回0
str1++;
str2++;
}
return *str1 - *str2;//不相等时返回差值
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcdef";
int ret = my_strcmp(arr1, arr2);
if (ret > 0)
printf("arr1>arr2");
else if (ret == 0)
printf("arr1=arr2");
else
printf("arr1<arr2");
return 0;
}
strncmp
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2,size_t num)
{
assert(str1 && str2);//断言是否为NULL
while (*str1 == *str2 && num)//相等就继续比较下一个字符
{
if (*str1 == '\0')//相等且等于\0 则说明两个字符串相同
return 0;//直接返回0
str1++;
str2++;
num--;
}
//当num为0时,str1和str2已经跳过了num个字符指向了第num + 1个字符
//此时直接返回差值,返回的将是第num + 1个字符的差值,所以需要调整指针向前退一位
return *(str1 - 1) - *(str2 - 1);//不相等时返回差值
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcf";
int ret = my_strcmp(arr1, arr2, 3);
if (ret > 0)
printf("arr1>arr2");
else if (ret == 0)
printf("arr1=arr2");
else
printf("arr1<arr2");
return 0;
}
strstr函数介绍及模拟实现
strstr函数介绍:
函数原型:
返回值:返回值是找到的第一个目标字符串(被查找字符串中可能不止包含一个待查找字符串)的起始地址,若没有查找到字符串则返回NULL;
参数:被查找字符串,待查找字符串;
作用:在被查找字符串中查找待查找字符串;
使用:
注意:
1.返回的是被查找字符串中找到的第一个待查找字符串的起始地址;
strstr模拟实现:
#include <stdio.h>
#include <assert.h>
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);//断言防止空指针
const char* s1 = str1;
const char* s2 = str2;
const char* flag = str1;
while (*flag)//当*flag为0时就表示没有目标字符串
{
s2 = str2;
s1 = flag;
while (*s1 == *s2 && s1 != '\0' && s2 != '\0')//当找到相同字符后,进入循环继续查看后面的字符是否相同
{
s1++;
s2++;
}
if (*s2 == '\0')//上循环结束后,若s2指针指向的是\0则说明已经找到该字符串
return (char*)flag;//返回该字符串的起始位置
flag++;//若没有跳出
}
return NULL;//当s1指向\0时说明没有找到目标字符串,返回空指针
}
int main()
{
char arr1[] = "abdagsadafe";
char arr2[] = "sad";
char* ret = my_strstr(arr1, arr2);//在arr1,中查找是否存在arr2中的字符串
printf("%s", ret);
return 0;
}
strtok函数介绍
函数原型:
返回值:返回的是每一次分割的字符段的首地址;
参数:被分割的字符串的地址,分隔符数组的地址;
作用:将被分割的字符串以分割符为界限分隔开(一次调用只能分割出一个字符段),并返回该次分割得到的字符段的地址;
使用及注意事项:
调用一次:
调用多次:(使用for循环)
附代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "fdhauifdaf@outlook.com";//含有分隔符的字符串
char arr2[] = "@.";//分隔符集合
char* ret = NULL;
for (ret = strtok(arr1, arr2); ret != NULL; ret = strtok(NULL, arr2))
printf("%s\n", ret);
return 0;
}
注意:
1.strtok函数的原理时是:在找到一个分隔符后,将分隔符换为\0,并返回当前被分割字符段的起始地址;
2.strtok函数会记住当前调用时找到的分隔符的地址,因此第二次调用时若第一个参数为NULL时,strtok函数就会从记住的位置开始继续往后查找下一个分隔符,若没有查找到,就返回NULL;
3.在VS环境下要包含#define _CRT_SECURE_NO_WARNINGS;
strerror函数介绍
函数原型:
返回值:返回的是参数部分错误码对应的错误信息的字符串的地址;
(错误码和错误信息):
参数:错误码;
作用:返回错误码对应的错误信息的字符串的地址;
使用:
附代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
for (int i = 0; i <= 10; i++)
{
printf("%d:%s\n", i, strerror(i));
}
return 0;
}
图中就是每个错误码对应的错误信息(不止10个)。
注意:
在VS环境下要包含#define _CRT_SECURE_NO_WARNINGS;
总结
strlen函数:计算字符串长度(单位字节);
strcpr、strncpy函数:拷贝字符串;
strcat、strncat函数:追加字符串;
strcmp、strncmp函数:比较字符串大小;
strstr函数:在一个字符串中查找另一个字符出;
strtok函数:使用分隔符分割字符串;
strerror函数:获取错误码对应错误信息的地址;
后记
感谢各位读者的阅读,今天我们主要总结了各种字符串函数的用途和模拟,不足的地方请大家多多指教,我们下期再见!