手把手教你玩转常用字符串函数(包含模拟实现)

简介: 手把手教你玩转常用字符串函数(包含模拟实现)

一、strlen

1.认识strlen

关于函数定义的图片,本文均取自cplusplus.com - The C++ Resources Network

从函数的返回类型可以看出strlen返回的值是一个无符号整型,再从参数观察,使用的是字符指针变量,并用const(常量)使其所指向地址的值不可被修改。

strlen的用途也很简单,就是用来计算字符串长度

2.使用strlen

#include<stdio.h>
#include<string.h>//声明函数,strlen被包含在这个头文件中
int main()
{
  char arr1[] = "abc def";//定义一个字符串
    int a=strlen(arr1);//返回的值是无符号整型,可以使用整型进行接收
  printf("%d\n",a);//将字符串长度打印出来验证
}

3.拓展:模拟实现strlen

首先,我们得明确strlen的目标,它的目标是要计算字符串的长度,那么我们传递过去的值显然就应该是这个字符串的首字符的地址,这样我们才能通过字符串的特性(字符串末尾有\0)来计算出字符串的长度,传递过去的指针变量所指向的内容是不需要修改的,我们只计算长度。因此,我们传递过去的值的类型应是const char*。接着我们判断函数返回的类型,字符串的长度,显而易见应该是整数(没谁见过0.1个字符吧),因此我们函数返回的类型应是int


这些问题都想明白了,那么我们接下来就来说一下实现思路


思路很简单,我们知道字符串的末尾是\0,那么我们就可以通过遍历字符串上每一个字符,再根据/0来判断中止条件,一旦遇到/0立刻就中止程序。


上代码

#include<stdio.h>
#include<string.h>
int my_strlen(const char* a1)
{
  int count = 0;//计数器                     (\0的ASCII码值为0)
  while (*a1++)//当*a1,也就是此时a1对应的字符为'\0'时中止循环,遍历结束
  {
    count++;//每遍历一次就加1
  }
  return count;
}
int main()
{
  char arr1[] = "abc def";
  printf("%d\n",strlen(arr1));
  printf("%d\n", my_strlen(arr1));
}

二、strcpy

1.认识strcpy

strcpy函数的返回类型是char*也就是字符指针,是个地址,参数类型是两个字符指针,其中source这个字符所指向的内容不能被修改。

strcpy的用途是将一个字符串的内容覆盖掉另一个字符串的内容,注意,是覆盖

2.使用strcpy

#include<stdio.h>
#include<string.h>//strcpy位于此头文件中
int main()
{
  char arr1[] = "acdefg";
  char arr2[]= "abcd";
  printf("%s\n", arr1);//打印被覆盖前的字符串
    strcpy(arr1, arr2);//arr1字符串被arr2字符串覆盖
  printf("%s\n", arr1);//打印被覆盖后的字符串
}

为什么之前说覆盖呢,这里笔者通过vs编译器给大家展现一下

在走到strcpy之前arr1和arr2的内容就,接着我们走下strcpy这个函数

不难看出,strcpy只是实现了覆盖,并没有将arr1彻底变成arr2。

3.拓展:模拟实现strcpy

首先,明确strcpy的目标,将一个字符串覆盖上另一个字符串   不难看出,这个函数的值应该要传递两个字符地址,但是要注意的细节是,用来覆盖一个字符串的另一个字符串上的字符只是使用,但不修改,但被覆盖的字符串显然就要被修改,因此,被覆盖字符串的类型应是char*型的,进行覆盖的字符串类型应是const char*型的  那么返回类型我们应该用什么呢?其实用void(空类型)也行,因为我们的目标只是将一个字符串覆盖上另一个字符串   但是我们最好还是用char*型的传递回去给主函数一个地址,因为这样才可以使用链式法则。


这些问题都想明白了,那么我们接下来就来说一下实现思路


我们已知两个字符串的首地址,那么我们就可以通过'\0'将两个字符串都遍历,我们这里只需要遍历完一个字符串就行,那就是实施覆盖的字符串即可,我们只需要将这个字符串全部覆盖在另一个字符串上,我们的任务就完成了。说到这有聪明的小伙伴就触类旁通了,当用来覆盖字符串的那个字符串长度超出被覆盖字符串时不就越界了吗?是的,越界了,比如这串代码


#include<stdio.h>
#include<string.h>
int main()
{
  char arr1[5] = "acde";
  char arr2[20]= "abcdeffff";
  printf("%s\n", strcpy(arr1, arr2));
}

编译器会报错 ,因此在使用这个函数时还应该注意的细节就是被覆盖字符串的大小应该足够大。

题外话讲完了,上代码

#include<stdio.h>
#include<string.h>
#include<assert.h>//assert的头文件
char* my_strcpy(char* str1, const char* str2)
{
assert(*str1 && *str2);
//断言一下,含义是当*str1或者*str2其中有一个是空字符串就报错,看不懂没关系,影响不大
char* ret = str1;
//储存被覆盖字符串的首地址,因为随着遍历,str1所指向的不再是之前的首地址
while(*str1++ = *str2++);
//遍历的同时进行覆盖,一旦覆盖到'\0'即为假,中止循环
return ret;
}
int main()
{
  char arr1[5] = "acde";
  char arr2[20]= "abcdeffff";
  printf("%s\n", arr2);
  printf("%s\n", arr1);
  printf("%s\n", my_strcpy(arr1, arr2));
}

三、strcmp

1.认识strcmp

strcmp的用途是来比较两个字符串的大小的  它的返回类型是整型,有两个字符指针参数,这两个地址对应的内容是不可被修改的,参数类型为const char*其中值得一提的是,当str1对应的字符串大于str2时编译器返回大于0的数,等于返回等于0的数,小于返回小于0的数,那么strcmp是通过字符串的哪个特性来比较字符串的大小的呢?strcmp是通过一对一对的比较字符串上的字符,一旦不相等则根据当前比较结果返回值。一直相等则比较到'\0'结束,返回0

2.使用strcmp

#include<stdio.h>
#include<string.h>//strcmp函数位于这个头文件中
int main()
{
  char arr1[] = "eee";
  char arr2[] = "abcdGfg";
    int a=strcmp(arr1, arr2);//将比较的结果储存到a中
  printf("%d\n",a);//将结果打印出来
}

3.拓展:模拟实现strcmp

老样子,先看目标,目标是比较两个字符串的大小,实现方式是将字符串上的字符取出,一对一对的进行比较。函数的返回类型显然为int,两个参数只是比较不参与修改,因此都应是字符指针且对应地址不能被修改,故类型应为const char*,


这些问题都想明白了,那么我们接下来就来说一下实现思路


比较两个字符串的大小,是一对一对字符进行比较然后通过字符的差别返回值,那么我们首先要遍历,通过遍历字符串上的字符内容一直到两个字符不相等则返回对应值,一直相等便一直比较到'\0'则返回0


上代码

#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_strcmp1(const char* str1,const char* str2)
{
  assert(*str1 && *str2);
  while (*str1==*str2)//相等则一直遍历下去
  {
    if (*str1 == '\0')//遍历到'\0'停止
      return 0;
    str1++;
    str2++;
  }
  if (*str1 > *str2)
  {
    return 1;//大于返回大于0的数
  }
  else
    return -1;//小于返回小于0的数
}
int main()
{
  char arr1[] = "abcdefg";
  char arr2[] = "abcdGfg";
  printf("%d\n",strcmp(arr1, arr2));
  printf("%d\n", my_strcmp1(arr1, arr2));
}

精简版本

#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_strcmp2(const char*str1,const char*str2)
{
  assert(*str1 && *str2);
  while (*str1==*str2)
  {
    if (*str1 == '\0')
      return 0;
    str1++;
    str2++;
  }
  return *str1 - *str2;//不相等时才会跳出循环,因此作差得所需值
}
int main()
{
  char arr1[] = "abcdefg";
  char arr2[] = "abcdGfg";
  printf("%d\n",strcmp(arr1, arr2));
  printf("%d\n", my_strcmp2(arr1, arr2));
}

四、strcat

1.认识strcat

strcat是用来拼接字符串的,它会将参数source字符串复制到参数destination所指的字符串尾部,函数返回类型为char*,两个参数一个是char*,一个是const char*

2.使用strcat

#include<stdio.h>
#include<string.h>//strcat被包含在这个头文件中
int main()
{
  char arr1[20] = "acdefgh";
  char arr2[20] = "def";
  printf("%s",strcat(arr1, arr2));//打印拼接完成后的内容
}

3.拓展:模拟实现strcat

为了使用链式法则,我们这里不用void类型作为函数的返回值,虽然我们的工作仅仅只是将两个字符串拼接在一起。参数类型,一个是被拼接的,要能被修改,一个是用来拼接的,不需要修改,故参数类型分别是char*和const char*


这些问题都想明白了,那么我们接下来就来说一下实现思路


关键在找到被拼接字符串的末尾,这里可以通过'\0'来实现,实现完成后再在末尾的地址上将另一个字符串覆盖上去即可,还是老样子,被拼接字符串要够长,不然会越界。


上代码

#include<stdio.h>
#include<string.h>
char* my_strcat(char* str1, const char* str2)
{
  char* ret = str1;//储存开始时的地址,因为str1会再遍历时被改变
  while (*str1)//当*str1为'\0'时找到关键地址
  {
    str1++;
  }
  while (*str2)
  {
    *str1 = *str2;//开始覆盖
    str1++;
    str2++;
  }
  return ret;
}
int main()
{
  char arr1[20] = "acdefgh";
  char arr2[20] = "def";
  printf("%s",my_strcat(arr1, arr2));
}

五、strstr

1.认识strstr

strstr函数的作用是在一个给定的字符串中查找另一个字符串,如果存在,则返回第一次出现的位置。函数的返回类型为const char*,两个参数均为const char*

2.使用strstr

#include<stdio.h>
#include<string.h>//strstr被包含在这个头文件中
int main()
{
  char arr1[] = "abcdefgbc";
  char arr2[] = "cde";
  printf("%s\n", strstr(arr1, arr2));//将查找到的地址所对应的字符串打印
}

3.拓展:模拟实现strstr

这个的实现思路比较复杂,三言两语解释不清楚,我们直接上代码,通过注释解释

#include<stdio.h>
#include<string.h>
#include<assert.h>
const char* my_strstr(const char*str1,const char*str2)
{
  while (*str1)//查找不到目标时也就是全部都找完了,来到了末尾'\0'中止循环
  {
    char* ch1 = str1;
      //假设现在就已经找到目标(因为每次遍历都可能找到目标),因此储存第一次出现的位置
    char* ch2 = str2;
     //目标字符串首元素的地址在每次查找前应重新取出,这样才能查找到对应字符串
    while (*ch2 == *ch1)//当此时地址对应的字符相等时进入循环
    {
      ch1++;
      ch2++;
      if (*ch2 == '\0')//因为被查找目标已经遍历完,因此中止循环
      {
        return str1;
      }
    }
    str1++;
  }
  return NULL;//找不到返回空指针
}
int main()
{
  char arr1[] = "abcdefgbc";
  char arr2[] = "cde";
  printf("%s\n", my_strstr(arr1, arr2));
}

今天的分享到这里就结束了,感谢各位友友的来访,祝各位友友前程似锦O(∩_∩)O

相关文章
|
7月前
|
存储 安全 C语言
c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(下))
c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(下))
126 0
|
7月前
|
存储 C语言
c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(上))
c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(上))
117 0
|
6月前
|
算法 C语言
【再识C进阶3(上)】详细地认识字符串函数、进行模拟字符串函数以及拓展内容
【再识C进阶3(上)】详细地认识字符串函数、进行模拟字符串函数以及拓展内容
|
7月前
|
C++
C++语言学习数组和字符串应用案例
【4月更文挑战第8天】该文展示了C++中数组和字符串的应用案例。数组示例定义了一个整数数组并访问、修改其元素,计算了元素之和。字符串示例中,定义了一个字符串并遍历、修改字符,进行了字符串拼接、查找子字符串及替换操作。
40 3
|
算法 Linux C语言
【C++技能树】String类解析与模拟实现
终于放假啦,停更了一个月的博客也要重新拾起来了。近一个月都没怎么好好写代码,现在好多都看不懂了。在接下的时间里,会更新:算法题,ROS,C++,Linux相关内容。
64 0
【C++技能树】String类解析与模拟实现
C进阶:字符串相关函数及其模拟实现
C进阶:字符串相关函数及其模拟实现
59 0
C进阶:字符串相关函数及其模拟实现
字符串的进阶练习案例(接上一节)
字符串的进阶练习案例(接上一节)
51 0
|
Python
Python编程 字符串组成方式
Python编程 字符串组成方式
82 0
|
编译器 C++
C++学习笔记(十一)——String类的模拟实现(一)
C++学习笔记(十一)——String类的模拟实现
C++学习笔记(十一)——String类的模拟实现(一)
|
算法
【C字符串函数】字符串函数和内存操作函数模拟实现(进阶版)(二)
【C字符串函数】字符串函数和内存操作函数模拟实现(进阶版)
67 0
【C字符串函数】字符串函数和内存操作函数模拟实现(进阶版)(二)