目录
前言
字符串函数是C语言库中一类重要的函数,本文将重点介绍几类常用的字符串函数以及讲解其模拟实现的方法,同时也会拓展一些函数
一、字符串函数的总体介绍
strlen函数
strlen函数用来计算字符串的长度,遇到‘\0’停止,strlen函数返回的是在字符串中‘\0’前面出现的个数(不含‘\0’)
#include <stdio.h>
#include <string.h>
int main()
{
char c[] = { "hsjodb" };
printf("%d\n", strlen(c));
return 0;
}
注意:
- 参数指向的字符串必须以‘\0’结尾
- 使用时要包含头文件<string.h>(所有字符函数均需要)
strcpy函数
字符串复制函数,将源字符串赋值到目的字符串
注意:
- 源字符串必须以‘\0’结尾
- 会将源字符串中的‘\0’拷贝到目标空间
- 目标空间必须足够大,否则可能会出现溢出
- 目标空间必须可修改
strcmp函数
字符串比较函数:不是比较字符串的长度,而是比较两个字符串中对应位置上字符的ASCII码值
比较规则:
- 第一字符串大于第二个,则返回大于零的数
- 第一字符串等于第二个,则返回0
- 第一字符串小于第二个,则返回小于零的数
strcat函数
字符串连接函数,将源字符串连接到目标字符串后面
#include <stdio.h>
#include <string.h>
int main()
{
char c[] = { "hsjodb" };
char a[20] = { "xxxxxxxxxxxxx" };
strcat(a, c);
printf("%s\n", a);
return 0;
}
注意:
- 源字符串必须以‘\0’结尾
- 目标字符串中也必须有‘\0’,否则没办法知道从哪里开始追加
- 目标空间足够大,能容下源字符串的内容
- 目标空间必须可修改
二、各种字符串函数的模拟实现
1.strlen函数
strlen函数的模拟实现总共有三种方法,分别是:
计数法
计数法顾名思义就是利用计数变量,记录字符串的长度,方法比较简单:
#include <stdio.h>
static size_t my_strlen(const char* s)//注意strlen函数的返回值是无符号整型,所以两个无符号整型做加减法不会出现复制,-不代表符号位
{//当`const`用于修饰函数的参数时,它表示参数在函数内部不会被修改
size_t count = 0;
while (*s != '\0')
{
count++;
s++;
}
return count;
}
int main()
{
char arr[] = { "hello my hreat" };
size_t num = my_strlen(arr);
printf("%zd\n", num);
return 0;
}
有几点需要注意:
- 由于字符串的长度不存在负数故,strlen函数的返回值为无符号整型,而无符号整型相减时虽然带负号,但此时符号并不是符号位,返回的值任然是一个大于零/等于0的数
由下图易知b的字符串长度小于a但仍然会打印出-2
- 为了目标字符串不被改变,故用const修饰函数参数
指针-指针
基本思想:记录下初始指针和最后一个字符的指针,再相减便能得出字符串长度
//strlen函数--指针-指针法
#include <stdio.h>
size_t my_strlen(const char* s)
{
char* a = s;
while ((*s) != '\0')//直接让s指向最后的\0
s++;
return s - a;
}
int main()
{
char arr[] = { "hello my hreat" };
size_t num = my_strlen(arr);
printf("%zd\n", num);
return 0;
}
递归
递归的思想是大事化小,把问题拆解,求字符串长度,我们可以拆解成1+去掉前一个字符后面的字符长度
/strlen函数--递归法-不创建变量法
#include <stdio.h>
size_t my_strlen(const char* s)
{
if (*s == '\0')
return 0;
else
return 1 + my_strlen(s + 1);//将字符数量转换成前一个字符加剩下字符的个数
}
int main()
{
char arr[] = { "hello my hreat" };
size_t num = my_strlen(arr);
printf("%zd\n", num);
return 0;
}
2.strcpy函数
代码如下(示例):
其中用assert判断指针不是空指针,用const修饰使得不能改变指针所指向的字符串,但指针本身是可以进行自增,自减运算的(忘记的小伙伴可以看上一篇文章哟~)
#include <stdio.h>
#include <assert.h>
char* my_strcpy(const char* dest,const char* src)
{
assert(dest);
assert(src);
char* ret = dest;
while (*dest++ = *src++)//将arr1中的字符复制到arr2中
;//注意strcpy函数会将源函数中的\0复制到目标字符
return ret;
}
int main()
{
char arr1[] = { "jinandaxue" };
char arr2[] = "you can do it";
char* ret = my_strcpy(arr2, arr1);
printf("%s\n", ret);
return 0;
}
3.strcmp函数
注意:这里的返回值仅再VS条件下为如此,其他编译器可能会返回其他的负值和正值
//模拟strcmp函数
#include <stdio.h>
int my_strcmp(const char* strl1,const char* strl2)
{
while (*strl1 == *strl2)
{
if (*strl1 == '\0')//说明两个指针已经移动到了最后,如果他们还相等说明两个字符串完全相等
return 0;
strl1++;
strl2++;
}
if (*strl1 > *strl2)
return 1;
else
return -1;//等于零的情况已经考虑过了
}
int main()
{
char arr1[] = { "hahanihao" };
char arr2[] = { "howaboutyou" };
printf("%d\n", my_strcmp(arr1, arr2));
return 0;
}
4.strcat函数
//模拟实现strcat函数
//注意:不能自己和自己追加,会出现死循环和越界
#include <stdio.h>
char* my_strcat(char* dest, const char* src)//关键在于找到两个字符串符号零的位置
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
while ((*dest) != '\0')//此时dest最后指向了\0的位置
{
dest++;//如果是*dest++的话,最后dest会再加一次,已经指向了\0后面一位!如果没有覆盖‘\0’会导致输出时提前结束
}
while ((*dest++) = (*src++))//同样实现函数的复制
;
return ret;
}
int main()
{
char arr1[30] = { "I love myself" };
char arr2[] = { " anywhere" };
char* ret = my_strcat(arr1, arr2);
printf("%s\n", ret);
return 0;
}
总结
以上便是常用字符串函数的介绍和模拟实现,灵活运用这些函数可以给我们带来许多方便