字符函数和字符串函数

简介: 今天我为大家分享的是字符函数和字符串函数,那么字符函数和字符串函数有哪些呢?我们来看看。求字符串长度:strlen长度不受限制的字符串函数:strcmp,strcpy,strcat长度受限制的字符串函数:strncmp,strncpy,strncat字符串查找:strstr,strtok

那么接下来我来为大家一一介绍这些库函数是如何使用以及自己如何来模拟实现。


strlen

size_t strlen ( const char * str );

strlen是用来计算字符串中'\0'之前字符的个数的,所以strlen的参数必须以'\0'结束,否则就会出现错误。并且strlen函数的返回值是size_t,说明返回的类型是无符号类型,跟sizeof是一样的,这里我们需要额外注意。知道了strlen的原理之后我们来看看如何自己来模拟实现strlen函数


模拟实现strlen

#include<stdio.h>
#include<assert.h>
//因为我们这里只是计算字符的个数,不改变字符串里的内容,所以我们用const修饰来增加安全性
int my_strlen(const char* str)   
{
  assert(str);    //这里同样是增加安全性
  char* tmp = (char*)str;
  int count = 0;
  while (*tmp != '\0')
  {
    count++;
    tmp++;
  }
  return count;
}
int main()
{
  char str[] = "abcdef";
  int ret = my_strlen(str);
  printf("%d", ret);
  return 0;
}

strcmp

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

strcmp是根据比较每个字符的ASCII大小来实现的,如果str1的ASCII值大于str2的ASCII值就返回大于0的值,小于就返回小于0的值,相等返回0。看看我们是怎样模拟实现的吧。


模拟实现strcmp

#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* arr1, const char* arr2)
{
  assert(arr1 && arr2);
  char* str1 = (char*)arr1;
  char* str2 = (char*)arr2;
 //如果*str1==*str2,str1和str2就++,看后面的是否相同
  while (*str1 == *str2)  
  {
    str1++;
    str2++;
  }
//跳出循环的情况有两种:第一种是字符串都走到'\0'的位置了,这就说明两个字符串相等
//                      第二种就是两个字符串中对应的两个字符不相等,
//所以这里我们就需要做出判断
  if (*str1 == '\0')
    return 0;
  else
    return *str1 - *str2;
}
int main()
{
  char arr1[] = "abcd";
  char arr2[] = "abed";
  int ret = my_strcmp(arr1, arr2);
  printf("%d", ret);
  return 0;
}

strcpy

char* strcpy(char * destination, const char * source );

这个函数的意思是将source中的函数拷贝到destination中,这里我们需要注意的是,拷贝的时候是从destination的'\0'开始的,将destination的'\0'给覆盖了,所以source中必须得有'\0',不仅如此,source中的内容也需要'\0'结束,并且destination的空间必须足够大,不然会出现错误,更重要的是destination空间必须是可变的。


模拟实现strcpy

#include<stdio.h>
#include<assert.h>
void my_strcpy(char* arr1, const char* arr2)
{
  assert(arr1 && arr2);
  char* str1 = arr1;
  char* str2 = (char*)arr2;
  while (*str1++ = *str2++)
  {
    ;
  }
}
int main()
{
  char arr1[] = "abcd";
  char arr2[] = "bcde";
  my_strcpy(arr1, arr2);
  printf("%s", arr1);
  return 0;
}

strcat

char * strcat ( char * destination, const char * source );

这个函数的作用是将source中的内容追加到destination的后面,这也是从destination的'\0'开始的。


模拟实现strcat

#include<stdio.h>
#include<assert.h>
void my_strcat(char* arr1, const char* arr2)
{
  assert(arr1 && arr2);
  char* str1 = arr1;
  char* str2 = (char*)arr2;
  while (*str1 != '\0')  /找到destination的'\0'位置
  {
    str1++;
  }
  while (*str1++ = *str2++)
  {
    ;
  }
}
int main()
{
  char arr1[12] = "hello ";
  char arr2[] = "world";
  my_strcat(arr1, arr2);
  printf("%s", arr1);
  return 0;
}

strncmp

int strncmp ( const char * str1, const char * str2, size_t num );

这个函数可以指定比较的字符个数,相对于strcmp来说就安全一点。我们来看看这个函数是如何实现的吧/


模拟实现strncmp

#include<stdio.h>
#include<assert.h>
int my_strncmp(const char* arr1, const char* arr2,int n)
{
  assert(arr1 && arr2);
  char* str1 = (char*)arr1;
  char* str2 = (char*)arr2;
    for(int i = 0; i<n; i++)
    {
        if(*str1 != *str2)
            return *str1-*str2;
    }
    return 0;
}
int main()
{
  char arr1[] = "abcd";
  char arr2[] = "abed";
  int ret = my_strncmp(arr1, arr2,2);
  printf("%d", ret);
  return 0;
}

strncpy

char * strncpy ( char * destination, const char * source, size_t num );

指定将source中的几个字符拷贝到destination中。结果返回destination的首地址。


模拟实现strncpy

#include<stdio.h>
#include<assert.h>
char* my_strncpy(char* arr1, const char* arr2,int n)
{
  assert(arr1 && arr2);
  char* str1 = arr1;
  char* str2 = (char*)arr2;
    for(int i = 0; i<n; i++)
    {
        *str1++ = *str2++;
    }
    return arr1;
}
int main()
{
  char arr1[] = "abcd";
  char arr2[] = "bcde";
  printf("%s", my_strncpy(arr1, arr2,3));
  return 0;
}


这里再拷贝了之后会不会在destination后面自动填写一个'\0'呢?我们通过一个代码来看看。


39.png40.png


这里我们可以看到,strncpy是不会自动补'\0'的。如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到n个。


strncat

char * strncat ( char * destination, const char * source, size_t num );

指定source中的n个字符追加到destination中。


模拟实现strncat

#include<stdio.h>
#include<assert.h>
char* my_strncat(char* arr1, const char* arr2,int n)
{
  assert(arr1 && arr2);
  char* str1 = arr1;
  char* str2 = (char*)arr2;
  while (*str1 != '\0')
  {
    str1++;
  }
    for(int i = 0; i<n; i++)
    {
        *str1++ = *str2++;
    }
    return arr1;
}
int main()
{
  char arr1[12] = "hello ";
  char arr2[] = "world";
  printf("%s", my_strncat(arr1, arr2,3));
  return 0;
}

那么这里会不会自动补'\0'呢?我们来看看。


41.png

42.png


答案是会的,再拷贝完你指定的字符个数后,会在后面自动补上一个'\0'。  


strstr

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

在字符串str1中查找是否有str2字符串。如果有就返回str1中第一个str2字符串的地址。


模拟实现strstr

#include<stdio.h>
#include<assert.h>
char* findStr(const char* arr1,const char* arr2)
{
  assert(arr1 && arr2);
//用s1来记录跟str2首字符相等的位置,以便cur1在找到首字符相等时,继续找后面字符是否相等,但不
//相等的时候,将cur1返回到第一个字符相等的位置,在进行后面的查找。
  char* s1 = NULL;  
//s2跟s1的作用是类似的
  char* s2 = (char*)arr2;
  char* cur1 = (char*)arr1;
  while (*cur1 != '\0')
  {
    char* cur2 = s2;
    while (*cur1 != *cur2)
    {
      cur1++;
    }
    s1 = cur1;
    while (*cur2 != '\0')
    {
      if (*cur1 != *cur2)
        break;
      cur1++;
      cur2++;
    }
    if (*cur2 == '\0')
      return s1;
    cur1 = s1;
    cur1++;
  }
  return NULL;
}
int main()
{
  char arr1[] = "abcdef";
  char arr2[] = "bcd";
  printf("%s", findStr(arr1,arr2));
  return 0;
}

如何在arr1中找到arr2最后出现的地址

#include<stdio.h>
#include<assert.h>
char* findStr(const char* arr1,const char* arr2)
{
  assert(arr1 && arr2);
  char* s1 = NULL;
  char* s2 = (char*)arr2;
  char* cur1 = (char*)arr1;
    //ret来记录每个出现arr2完整字符串的首元素地址
    char* ret = NULL;
  while (*cur1 != '\0')
  {
    char* cur2 = s2;
    while (*cur1 != *cur2)
    {
      cur1++;
    }
    s1 = cur1;
    while (*cur2 != '\0')
    {
      if (*cur1 != *cur2)
        break;
      cur1++;
      cur2++;
    }
    if (*cur2 == '\0')
      {
                ret = s1;
            }
    cur1 = s1;
    cur1++;
  }
    return ret;
}

那么这些就是我所要分享的我学到的所有关于字符串函数的内容了,谢谢大家的观看,希望对大家能有帮助。

相关文章
|
安全 关系型数据库 MySQL
MySQL数据库高效秘籍:10个小技巧,让你轻松应对各种场景!
【8月更文挑战第25天】本文介绍了十个提升MySQL数据库效率与安全性的实用技巧。涵盖查询性能分析、索引优化、慢查询日志利用、图形化工具如MySQL Workbench的应用、性能分析工具、主从复制实现、备份与恢复策略、数据库迁移方法及安全性保障等多个方面。通过具体的示例代码展示每个技巧的实际操作方式,帮助读者深入理解并有效运用MySQL数据库。
616 0
|
安全 数据安全/隐私保护
31、CSRF漏洞介绍
31、CSRF漏洞介绍
100 0
|
关系型数据库 MySQL 数据安全/隐私保护
docker应用部署---MySQL的部署配置
这篇文章介绍了如何使用Docker部署MySQL数据库,包括搜索和拉取MySQL镜像、创建容器并设置端口映射和目录映射、进入容器操作MySQL,以及如何使用外部机器连接容器中的MySQL。
docker应用部署---MySQL的部署配置
|
Nacos
nacos 配置页面的模糊查询
nacos 配置页面的模糊查询
365 0
|
存储 安全 NoSQL
后端技术在现代软件开发中的重要性
在当今数字化时代,软件开发已经成为推动各行各业发展的核心动力。无论是互联网企业还是传统行业,软件系统的稳定性、性能和安全性都至关重要。作为软件系统的重要组成部分,后端技术在现代软件开发中扮演着不可或缺的角色。本文将探讨后端技术的重要性,并通过具体实例展示其在实际应用中的关键作用。通过对后端技术的深入理解和应用,我们可以更好地构建高效、可靠和安全的软件系统,满足不断变化的市场需求和用户期望。
|
运维 安全 Java
Log4j2 远程代码执行漏洞——总结
前两天网络有爆料log4j安全漏洞,安全大于天,于是也加入到这个和时间赛跑的临时事件中。对于安全漏洞网上有很多文章,内容都大同小异,不过针对于这件事小编下面的故事一定能让读者有"意外"收获。
|
敏捷开发 测试技术 API
阿里云云效产品使用问题之API中包含有获取测试计划的接口吗
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
机器学习/深度学习 算法 数据可视化
上海交大团队使用联合深度学习优化代谢组学研究
上海交大团队使用联合深度学习优化代谢组学研究
354 0
|
网络协议 网络安全
TCP故障排除
查看防火墙状态,查看socket监听,端口链路测试 systemctl status firewalld #查看防火墙状态 netstat -nltp #查看socket监听 端口链路测试 #能 ping 通但端口不通时端口可用性探测说明 https://help.
1011 0