字符串函数`strlen`、`strcpy`、`strcmp`、`strstr`、`strcat`的使用以及模拟实现

简介: 字符串函数`strlen`、`strcpy`、`strcmp`、`strstr`、`strcat`的使用以及模拟实现

🚀前言

今天阿辉将为大家介绍字符串库函数strlenstrcpystrcmpstrstrstrcat的使用以及模拟实现,关注阿辉不迷路哦 😘 ,内容干货满满😋,接下来就跟着阿辉一起学习吧👊

🚀库函数strlen

库函数strlen是专门求字符串长度的库函数,strlen只能求字符串长度且要求字符串末尾须有\0,返回值长度不包括\0

strlen的函数声明

size_t strlen(const char* src);
返回值为size_t类型
接受一个字符串的首元素地址,即可返回字符串长度

例子:

#include<stdio.h>
#include<string.h>
int main()
{
  char* a = "abcdef";`//末尾有\0
  char c[] = { 'a','b','c','d','e','f' };//末尾无\0
  printf("%zd\n", strlen(a));
  printf("%zd\n", strlen(c));
  return 0;
}

输出:

上图我们可以看到一个输出6而一个却是42,就是因为常量字符串a末尾有\0而字符串数组c末尾无\0,而库函数strlen计算的长度是从字符串首元素到\0之间的元素个数,若字符串末尾无\0strlen则会一直向后找到\0位置然后返回。在C语言中\0堪称字符串的灵魂,后面几个函数会让大家有更深的体会。

✈️strlen的模拟实现

铁子们,咱们直接代码以及详解奉上👇

size_t my_strlen(const char* src)
{
  assert(src != NULL);//断言判断传入指针不为空
  size_t ret = 0;//记录字符串长度,作为返回值
  while (*src++)//这句代码下面单独解释
  {
    ret++;
  }
  return ret;
}

关于while(*src++)这句代码,因为后置++的优先级更高所以src++,但是又因为后置++实现使用后++,所以*src++这个表达式的值是*src然后src再加1,然后当指针src偏移到\0位置时while循环就停止了因为\0的本质就是0

🚀库函数strcpy

库函数strcpy是用来用来拷贝字符串的

strcpy的函数声明:

char* strcpy(char* dest, const char* src);
把从src地址开始到\0的字符串复制到以dest开始的地址空间
返回值为拷贝位置起始地址

注意:

  • 将源指向的 C 字符串复制到目标指向的数组中,包括终止空字符(并在该点停止)
  • 源字符串必须以 ‘\0’ 结束。
  • 会将源字符串中的 ‘\0’ 拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变

例子:

int main()
{
  char a[] = "abcd";
  char b[10] = { 0 };
  strcpy(b, a);
  printf("%s",b);
  return 0;
}

输出:

abcd

✈️strcpy的模拟实现

char* my_strcpy(char* dest, const char* src)
{
  char* ret = dest;//记下目标位置起始地址
  assert(dest && src);//断言判断传入的指针不为空
  while (*dest++ = *src++)
  {
    ;
  }
  return ret;//返回目标位置起始地址
}

*dest++ = *src++这段代码可以理解为先进行*dest = *src,然后dest = dest + 1; src = src + 1,当src指向\0时,\0赋给*dest然后跳出循环

🚀strcmp

库函数strcmp的函数声明:

int strcmp(const char* str1, const char* str2);

strcmp是用来比较字符串大小的函数,但并非是以字符串长度比较的,而是从两个字符串的起始位置开始,一一对应地进行比较,如果它们彼此相等,则继续以下对,直到字符不同或达到\0,字符不同时比较的是ASII值大小

返回值:

  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字

例子:

int main()
{
  char a[] = "adc";
  char b[] = "abcd";
  int ret = strcmp(a, b);
  printf("%d ", ret);
  return 0;
}

输出:

1

✈️strcmp的模拟实现

int my_strcmp(const char* str1, const char* str2)
{
  assert(str1 && str2);
  while (*str1 == *str2)
  {
    if (*str1 == '\0')//两字符串相等,同时指向字符串末尾的\0
      return 0;
    str1++;
    str2++;
  }
  return *str1 - *str2;//不等位置相减
}

🚀strstr

库函数strstr的函数声明:

char* strstr(const char* str1, const char* str2);

strstr函数是用来判断主串str1中是否存在子串str2,如果存在则返回str1中第一次出现子串的起始位置地址,否则返回NULL

阿辉作图给大家展示一下:

int main()
{
  char a[] = "abcdsfejsl";
  char b[] = "dsfe";
  printf("%s", strstr(a, b));
  return 0;
}

输出:

dsfejsl

因为返回的是主串中子串起始位置地址,上述代码中也就是d位置的地址,用%s打印就是dsfejsl这一段

✈️strstr的模拟实现

char* my_strstr(const char* dest, const char* src)
{
  assert(dest && src);//断言判断不为空
  char* ret = dest;//ret作返回值,记录主串下一个起始比对位置
  char* p = src;//记录子串的起始位置
  if (*src == '\0')//子串为空直接返回主串
  {
    return ret;
  }
  while (*dest)//遍历到主串\0位置跳出循环
  {
    //从主串起始比对位置与子串一一比对
    while (*dest++ == *src++)//不相等时跳出循环
    {
      if (*dest == '\0')//当主串遍历到\0位置还进来,说明子串也到末尾\0位置了,直接返回主串起始比对位置
      {
        return ret;
      }
    }
    if (*src == '\0')//跳出循环时,src已到\0位置说明主串中找到子串,返回主串起始比对位置
    {
      return ret;
    }
    dest = ++ret;//上述if都没进去说明该主串起始比对位置找不到子串,++ret记录下一个起始比对位置,并把值赋给dest,从下一个起始比对位置开始遍历
    src = p;//src返回子串起始位置
  }
  return NULL;//上述都为返回说明找不到,返回空
}

铁子们不懂的话,下面这幅图还有解释:

🚀strcat

库函数strcat的函数声明:

char* strcat(char* dest, const char* src);

strcat库函数是用来把src所指向的字符串(包括\0)复制到dest所指向的字符串后面(删除*dest原来末尾的\0)。要保证*dest足够长,以容纳被复制进来的*src*src中原有的字符不变。返回指向dest的指针

例子:

int main()
{
  char a[20] = "abc";
  char b[] = "dsfe";
  printf("%s\n", strcat(a, b));
  return 0;
}

输出:

abcdsfe

✈️strcat的模拟实现

char* my_strcat(char* dest, const char* src)
{
  assert(dest && src);//断言判断不为空
  char* ret = dest;//记录起始地址作为返回值
  while (*dest)//找到目标字符串\0位置
  {
    dest++;
  }
  while (*dest++ = *src++)
  {
    ;
  }
  return ret;
}

while (*dest++ = *src++)这段代码前面大家见得多了,实在不理解可以自己敲出来试试,这里阿辉复制粘贴一下😘

*dest++ = *src++这段代码可以理解为先进行*dest = *src,然后dest = dest + 1; src = src + 1,当src指向\0时,\0赋给*dest然后跳出循环


到这里,阿辉今天对于C语言中部分字符函数的分享就结束了,希望这篇博客能让大家有所收获, 如果觉得阿辉写得不错的话,记得给个赞呗,铁子们的支持是我创作的最大动力🌹

相关文章
解析与模拟常用字符串函数strcpy,strcat,strcmp,strstr(一)
解析与模拟常用字符串函数strcpy,strcat,strcmp,strstr(一)
268 0
|
设计模式 算法 安全
【C/C++ 关键字 函数说明符 】C++ final关键字(修饰成员函数无法被子类重写覆盖)
【C/C++ 关键字 函数说明符 】C++ final关键字(修饰成员函数无法被子类重写覆盖)
550 1
|
10月前
|
应用服务中间件 nginx Docker
配置Containerd运行时镜像加速器
containerd配置国内容器镜像加速器
4052 1
|
11月前
|
传感器 安全 物联网
阿里云先知安全沙龙(北京站) ——车联网安全渗透测试思路分享
本文介绍了智能汽车的整车架构、协议栈结构、攻击点分析、渗透思路及案例分享。整车架构涵盖应用层、协议层和物理层,详细解析各层次功能模块和通信机制。攻击点包括Wi-Fi、USB、NFC等,展示车辆通信接口和系统组件的安全风险。渗透思路从信息收集到系统内部探索,利用固件漏洞控制车辆功能。案例展示了网段隔离不足导致的SSH访问和OTA日志审计漏洞,揭示了潜在的安全威胁。
|
Python
turtle库的几个案例进阶,代码可直接运行(python经典编程案例)
该文章展示了使用Python的turtle库进行绘图的进阶案例,包括绘制彩色圆形和复杂图案的代码示例。
4062 7
turtle库的几个案例进阶,代码可直接运行(python经典编程案例)
|
Docker 容器
docker:记录如何在x86架构上构造和使用arm架构的镜像
为了实现国产化适配,需将原x86平台上的Docker镜像转换为适用于ARM平台的镜像。本文介绍了如何配置Docker buildx环境,包括检查Docker版本、安装buildx插件、启用实验性功能及构建多平台镜像的具体步骤。通过这些操作,可以在x86平台上成功构建并运行ARM64镜像,实现跨平台的应用部署。
8879 2
|
JSON 安全 JavaScript
Web安全-JQuery框架XSS漏洞浅析
Web安全-JQuery框架XSS漏洞浅析
2269 3
|
缓存 负载均衡 应用服务中间件
在Linux中,Squid、Varinsh和Nginx有什么区别,工作中怎么选择?
在Linux中,Squid、Varinsh和Nginx有什么区别,工作中怎么选择?
|
SQL 测试技术 数据库
Flask与SQLAlchemy的神秘力量:如何让你的数据库飞起来?
【8月更文挑战第31天】在现代Web开发中,Flask和SQLAlchemy是热门技术栈,前者是轻量级Web框架,后者为强大的ORM库。本文介绍如何在Flask项目中集成SQLAlchemy,通过示例展示数据库操作方法,并分享最佳实践,如熟悉ORM、编写测试及适度使用SQL语句,以提升开发效率和代码质量。
555 0
|
存储 开发框架 安全
【C++ 线程】深入理解C++线程管理:从对象生命周期到线程安全
【C++ 线程】深入理解C++线程管理:从对象生命周期到线程安全
1041 0