本文将通过函数原型、用法、模拟实现等多个方面全面讲解字符串的库函数
strlen函数用来计算字符串的长度,它会从接收到字符的地址开始读取直到遇到'\0',每读取一个非'\0'的字符长度+1,最后返回一个size_t(无符号)类型的数
strlen函数原型:
返回类型为size_t,参数是一个字符指针用来接收字符的地址
#include
#include //记得加上头文件
int main()
{
char arr[] = "abcedf";
size_t len = strlen(arr);
printf("%zd", len); //结果为6
return 0;
}
这里总结了三种strlen函数模拟实现的方法,分别为:计数器、指针-指针和递归
计数器:
size_t my_strlen1(const char* arr) //计数器
{
size_t count = 0;
while (*arr++ != '\0')
{
count++;
}
return count;
}
递归:
size_t my_strlen(const char* arr)
{
if (*arr != '\0')
{
return 1 + my_strlen(++arr);
}
else
{
return 0;
}
}
每次递归都判断以下arr指针是否指向'\0',如果是则返回0,不是则指向下一个字符进行判断并且长度+1
指针-指针:
size_t my_strlen2(const char* arr)
{
char* p = arr;
while (*arr != '\0')
{
arr++;
}
return arr - p;
}
指针-指针用来计算两个指针之间元素的个数,先让p指向字符串的首地址,之后通过while循环使arr指向'\0',最后返回arr - p
strcpy函数用来拷贝字符串将源数组中的字符串拷贝到目标数组中,但需要注意以下几点:
- 目标数组可能没有'\0',所以strcpy再拷贝时会将源数组的'\0'也拷贝过去,也就是说源数组中必须有'\0'
- 目标数组的空间必须足够大,确保其在被拷贝后能存放的下字符串
- 目标数组必须可变,不能是常量字符串
strcpy函数原型:
返回类型为char*,destination用来接收目标数组的地址,source用来接收源数组的地址
#include
#include
int main()
{
char arr1[20] = { 0 }; //目标数组空间确保能存放源数组
char arr2[] = "abcdef";
strcpy(arr1, arr2);
printf("%s", arr1); //结果为abcdef
return 0;
}
#include
#include
char* my_strcpy( char* des, const char*src)
{
assert(des && src); //断言判断des和src是否时空指针
char* ret = des; //将des的首地址赋给ret用来最后返回,因为des在++后不再指向首地址
while (*des++ = *src++) //依次将字符赋给des直到'\0'循环终止
{
;
}
return ret;
}
int main()
{
char arr1[] = "abcdef";
char arr2[20] = { 0 };
char* ret = my_strcpy(arr2, arr1);
printf("%s", ret);
return 0;
}
strcat函数用来追加字符串,将源数组加到目标数组的末尾,即从目标数组的'\0'位置处开始追加;和strcpy函数需要注意的点一样:
- 源数组必须有'\0'
- 目标数组的空间必须足够大
- 目标数组必须可变,不能是常量字符串
strcat函数原型:
返回类型为char*,destination用来接收目标数组的地址,source用来接收源数组的地址
#include
#include
int main()
{
char arr1[20] = "abc"; //目标空间必须足够大
char arr2[] = "def";
strcat(arr1, arr2);
printf("%s", arr1); //结果为abcdef
return 0;
}
#include
#include
char* my_strcat(char* des, const char* src)
{
assert(des && src); //断言判断des和src是否为空指针
char* ret = des;
while (*des != '\0') //先找到目标数组'\0'的位置
{
des++;
}
while (*des++ = *src++) //从目标数组的'\0'位置处开始依次将源数组拷贝到目标数组
{
;
}
return ret;
}
int main()
{
char arr1[20] = "abc";
char arr2[] = "def";
char* ret = my_strcat(arr1, arr2);
printf("%s", ret);
return 0;
}
strcmp函数用来比较字符串,从两个字符串的第一个字符开始依次比较它们的ASCII码值,只要出现一个字符大于另一个字符就停止比较,此时较大字符所在的字符串大于另一个字符串
strcmp函数原型:
str1和str2分别接收要比较的两个数组的地址,返回类型为int,str1>str2则返回一个大于0的数,str1
#include
#include
int main()
{
char arr1[] = "abcfff";
char arr2[] = "abczz";
int cmp = my_strcmp(arr1, arr2);
if (cmp > 0)
{
printf(">");
}
else
{
printf("<="); //结果为<=,因为f
#include
#include
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1++ == *str2++) //依次比较两字符串的字符
{
if (*str1 == '\0' && *str2 == '\0')
{
return 0; //若两字符串的字符一直到'\0'都相等,则相等,返回0
}
}
return *str1 - *str2; //*str1大返回大于0的数,否则返回小于0的数
}
int main()
{
char arr1[] = "abcfff";
char arr2[] = "abczz";
int cmp = my_strcmp(arr1, arr2);
if (cmp > 0)
{
printf(">");
}
else
{
printf("<=");
}
return 0;
}
strncpy函数原型:
这里相较于strcpy多了一个参数num
用法:和strcpy用法相同,但它是将源数组的前num个字符拷贝到目标数组中
#include
int main()
{
char arr1[] = "abcdef";
char arr2[20] = { 0 };
size_t num = 3;
strncpy(arr2, arr1, num); //将arr1的前三个字符拷贝到arr2中
printf("%s", arr2); //结果为abc
return 0;
}
和strcpy的模拟实现类似,只不过要加一条对n的判断以确保只拷贝前n个字符
#include
#include
char* my_strncpy(char* des, const char* src, size_t n)
{
assert(des && src);
char* ret = des;
while (*des++ = *src++)
{
n--;
if (n == 0)
{
return ret;
}
}
}
int main()
{
char arr1[] = "abcedf";
char arr2[20] = { 0 };
size_t num = 3;
char* r = my_strncpy(arr2, arr1, num);
printf("%s", r);
return 0;
}
strncat函数原型:
用法:和strncat函数用法相同,但它是将数组的前num个字符追加到目标数组的'\0'处
#include
#include
int main()
{
char arr1[20] = "abc\0xxx";
char arr2[] = "defghi";
size_t num = 3;
strncat(arr1, arr2, num); //加完后会自动将\0加上
printf("%s", arr1);
return 0;
}
在arr1的'\0'处将def加上后会自动加一个'\0'以构成一个完整的字符串
和strcat的模拟实现类似,只不过要加一条对n的判断以确保只追加前n个字符
#include
#include
char* my_strncat(char* des, const char* src, size_t n)
{
char* ret = des;
while (*des != '\0')
{
des++;
}
while (*des++ = *src++)
{
n--;
if (n == 0)
{
*des = '\0';
return ret;
}
}
}
int main()
{
char arr1[20] = "abc";
char arr2[] = "defghi";
size_t num = 3;
char* ret = my_strncat(arr1, arr2, num);
printf("%s", ret);
return 0;
}
strncmp函数原型:
用法:和strcmp用法相同,但它只比较两个字符串前num个字符
#include
#include
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcdzz";
size_t num = 0;
int cmp = strncmp(arr1, arr2, num);
if (cmp > 0)
{
printf(">");
}
else
{
printf("<=");
}
return 0;
}
#include
#include
int my_strncmp(const char* str1, const char* str2, size_t n)
{
assert(str1 && str2);
while (*str1 == *str2)
{
n--;
if (n == 0)
{
return 0; //当前n个字符相同,返回0
}
}
return *str1 - *str2; //出现字符不相同时,跳出上面循环,返回*str1 - *str2
//前者大,返回大于0的值,后者大,返回小于0的值
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcdzz";
size_t num = 3;
int cmp = my_strncmp(arr1, arr2, num);
if (cmp > 0)
{
printf(">");
}
else
{
printf("<=");
}
return 0;
}
以上为7个字符串库函数的讲解,后续会对剩余的字符串库函数和内存函数进行讲解