字符串函数介绍——C语言

news2024/11/20 9:16:41

文章目录

一、引言 

二、函数的介绍与模拟实现

2、1 求字符串长度strlen()函数

2、1、1 strlen()函数介绍

 2、1、2  strlen()函数的模拟实现

2、2 字符串拷贝strcpy()函数

2、2、1 strcpy()函数的介绍

2、2、2 strcpy()函数的模拟实现

2、3 字符串追加strcat()函数

2、3、1 strcat()函数的介绍

2、3、2 strcat()函数的模拟实现

2、4 字符串比较strcmp()函数

2、4、1 strcmp()函数的介绍

2、4、2 strcmp()函数的模拟实现

2、5 字符串查找strstr()函数

2、5、1 strstr()函数的介绍

2、5、2 strstr()函数的模拟实现

2、6 内存拷贝memcpy()函数

2、6、1 memcpy()函数的介绍

2、6、2 memcpy()函数的模拟实现

2、7 可对覆盖内存拷贝memmove()函数

 三、总结


标题:字符串函数介绍

作者:@Ggggggtm

寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景

 

一、引言 

  C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串中或者字符数组中。字符串常量适用于那些对它不做修改的字符串函数

  那要是我们对字符串想要修改呢?例如复制字符串、字符串比较、字符串拼接等等。这时就用到了C语言的库函数。本篇文章会对高频用到的字符串函数进行详解。

二、函数的介绍与模拟实现

2、1 求字符串长度strlen()函数

2、1、1 strlen()函数介绍

  我们先看一下strlen()函数的返回值和参数,如下:

  size_t strlen ( const char * str );

  由上我们可以看出strlen()函数的参数是const char*,也就是我们要传一个地址。返回值为size_t,是无符号整型。

  在使用strlen()函数时,我们需要注意以下几点:

  • 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
  • 参数指向的字符串必须要以 '\0' 结束。
  • 注意函数的返回值为size_t,是无符号的( 易错 )。

  针对上述的最后一点,我们看如下代码: 

#include <stdio.h>
int main()
{
    const char*str1 = "abcdef";
    const char*str2 = "bbb";
    if(strlen(str2)-strlen(str1)>0)
    {
        printf("str2>str1\n");
    }
    else
    {
        printf("srt1>str2\n");
    }
    return 0;
}

  注意strlen()函数的返回值是无符号整型,所以上述代码中strlen(str2)-strlen(str1)的结果不会出现负值的

  当我们熟悉strlen()函数后,我们还应掌握strlen()函数的模拟实现。

 2、1、2  strlen()函数的模拟实现

  strlen()函数的模拟实现的方式有很多种,我们这里给出较为常见的,也是相对容易理解的三种,代码如下:

//计数器方式
int my_strlen(const char * str)
{
    int count = 0;
    while(*str)
    {
        count++;
        str++;
    }
    return count;
}

//不能创建临时变量计数器
int my_strlen(const char * str)
{
    if(*str == '\0')
        return 0;
    else
        return 1+my_strlen(str+1);
}


//指针-指针的方式
int my_strlen(char *s)
{
    char *p = s;
    while(*p != ‘\0’ )
    p++;
    return p-s;
}

2、2 字符串拷贝strcpy()函数

2、2、1 strcpy()函数的介绍

  我们先看一下strcpy()函数的返回值和参数,如下:

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

   由上我们可以看出strcpy()函数的第一个参数是char* destination,是我们要拷贝到的一个地址。第二个参数是const char * source ,是我们要拷贝的字符串地址。返回值为char * ,返回的地址是destination

  在使用strcpy()函数时,我们需要注意以下几点:

  • 源字符串必须以 '\0' 结束。
  • 会将源字符串中的 '\0' 拷贝到目标空间。
  •  目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变。

  我们看strcpy()函数的模拟实现。

2、2、2 strcpy()函数的模拟实现

//1.参数顺序
//2.函数的功能,停止条件
//3.assert
//4.const修饰指针
//5.函数返回值
//6.题目出自《高质量C/C++编程》书籍最后的试题部分
char *my_strcpy(char *dest, const char*src)
{
    char *ret = dest;
    assert(dest != NULL);
    assert(src != NULL);
    while((*dest++ = *src++))
    {
    ;
    }
    return ret;
}

2、3 字符串追加strcat()函数

2、3、1 strcat()函数的介绍

  我们先看一下strcat()函数的返回值和参数,如下:

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

  由上我们可以看出strcat()函数的第一个参数是char* destination,是我们要追加到的一个地址。第二个参数是const char * source ,是我们要追加的字符串地址。返回值为char * ,返回的地址是destination

  在使用strcat()函数时,我们需要注意以下几点:

  • 源字符串必须以 '\0' 结束。
  •  目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变。

  我们看strcat()函数的模拟实现。

2、3、2 strcat()函数的模拟实现

char *my_strcat(char *dest, const char*src)
{
    char *ret = dest;
    assert(dest != NULL);
    assert(src != NULL);
    while(*dest)
    {
        dest++;
    }
    while((*dest++ = *src++))
    {
        ;
    }
    return ret;
}

2、4 字符串比较strcmp()函数

2、4、1 strcmp()函数的介绍

  我们先看一下strcmp()函数的返回值和参数,如下:

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

   由上我们可以看出strcmp()函数的两个参数就是我们要比较的两个字符串的地址。返回值为int

  在使用strcmp()函数时,我们需要注意以下几点:

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

  我们看strcmp()函数的模拟实现。

2、4、2 strcmp()函数的模拟实现

int my_strcmp (const char * src, const char * dst)
{
    int ret = 0 ;
    assert(src != NULL);
    assert(dest != NULL);
    while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
        ++src, ++dst;
    if ( ret < 0 )
        ret = -1 ;
    else if ( ret > 0 )
        ret = 1 ;
    return ret;
}

2、5 字符串查找strstr()函数

2、5、1 strstr()函数的介绍

我们先看一下strstr()函数的返回值和参数,如下:

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

   由上我们可以看出strstr()函数的第一个参数是我们要在字符串中查找的地址。第二个参数是要查找的字符串的地址。返回值为char * ,返回的地址是要在字符串中查找到的地址。

  我们看strstr()函数的模拟实现。

2、5、2 strstr()函数的模拟实现

char * strstr (const char * str1, const char * str2)
{
    char *cp = (char *) str1;
    char *s1, *s2;
    if ( !*str2 )
        return((char *)str1);
    while (*cp)
    {
        s1 = cp;
        s2 = (char *) str2;
        while ( *s1 && *s2 && !(*s1-*s2) )
            s1++, s2++;
        if (!*s2)
            return(cp);
        cp++;
    }
    return(NULL);
}

2、6 内存拷贝memcpy()函数

2、6、1 memcpy()函数的介绍

  我们先看一下memcpy()函数的返回值和参数,如下: 

void * memcpy ( void * destination, const void * source, size_t num );

  由上我们可以看出memcpy()函数第一个参数是void* destination,是我们要拷贝到的一个地址。第二个参数是const void* source ,是我们要拷贝的字符串地址。返回值为void*,返回的地址是destination

  在使用memcpy()函数时,我们需要注意以下几点:

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 '\0' 的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的。

  我们看memcpy()函数的模拟实现。

2、6、2 memcpy()函数的模拟实现

void * memcpy ( void * dst, const void * src, size_t count)
{
    void * ret = dst;
    assert(dst);
    assert(src);
    /*
    * copy from lower addresses to higher addresses
    */
    while (count--) 
    {
        *(char *)dst = *(char *)src;
        dst = (char *)dst + 1;
        src = (char *)src + 1;
    }
    return(ret);
}

2、7 可对覆盖内存拷贝memmove()函数

  memmove()函数与memcpy()函数大同小异。只不过memcpy()函数的是实现并不能对覆盖内存拷贝,但是memmove()函数是可以的,我们直接看memmove()函数的模拟实现,代码如下:

void * memmove ( void * dst, const void * src, size_t count)
{
    void * ret = dst;
    if (dst <= src || (char *)dst >= ((char *)src + count)) 
    {
        /*
        * Non-Overlapping Buffers
        * copy from lower addresses to higher addresses
        */
        while (count--) 
        {
            *(char *)dst = *(char *)src;
            dst = (char *)dst + 1;
            src = (char *)src + 1;
        }
    }    
    else 
    {
        /*
        * Overlapping Buffers
        * copy from higher addresses to lower addresses
        */
        dst = (char *)dst + count - 1;
        src = (char *)src + count - 1;
        while (count--)
        {
            *(char *)dst = *(char *)src;
            dst = (char *)dst - 1;
            src = (char *)src - 1;
        }
    }
    return(ret);
}

 三、总结

  我们上述对多个函数进行了介绍和模拟实现,都是需要我们重点掌握的,再平常用到的频次也较高。

  希望以上内容对你有所帮助,感谢阅读ovo~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/156823.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「旷野俱乐部」在 The Sandbox 开业,SMCU 宫殿等你来体验!

简要概括 KWANGYAThe Sandbox 是「旷野俱乐部」在 The Sandbox 元宇宙中的虚拟空间&#xff1b; SMCU 宫殿体验呈现了 2022 年冬季 SM 小镇的视觉效果&#xff0c;SMCU 宫殿专辑封面将于 1 月 10 日發佈&#xff1b; 将向全球粉丝展示更多基于韩国文化内容的元宇宙体验。 The…

Appium+Pytest+pytest-testreport框架轻松实现app自动化

有任何环境问题&#xff0c;可以参考我的文章 Appium自动化测试&#xff1c;一&#xff1e;&#xff0c; Appium自动化测试&#xff1c;二&#xff1e;有任何定位问题、触屏操作、等待问题、Toast 信息操作问题、手机操作问题及H5页面的操作请参考我的文章&#xff1a;Appium自…

【论文速递】TNNLS2022 - 一种用于小样本分割的互监督图注意网络_充分利用有限样本的视角

【论文速递】TNNLS2022 - 一种用于小样本分割的互监督图注意网络_充分利用有限样本的视角 【论文原文】&#xff1a;A Mutually Supervised Graph Attention Network for Few-Shot Segmentation: The Perspective of Fully Utilizing Limited Samples 获取地址&#xff1a;ht…

Java设计模式-组合模式Composite

介绍 组合模式&#xff08;Composite Pattern&#xff09;&#xff0c;又叫部分整体模式&#xff0c;它创建了对象组的树形结构&#xff0c;将对象组合成树状结构以表示“整体-部分”的层次关系。组合模式依据树形结构来组合对象&#xff0c;用来表示部分以及整体层次。这种类…

【Nginx】Nginx的常用命令和配置文件

1. 常用命令 1. 查看版本2. 查看 Nginx 配置语法的正确性3. 为Nginx指定一个配置文件4. 启动 Nginx 服务5. 开机自启动6. 重启 Nginx 服务7. 查看 Nginx 服务状态8. 重载 Nginx 服务9. 停止 Nginx 服务10. 查看命令帮助 2. 配置文件 第一部分&#xff1a;全局块第二部分&#x…

RT-Thread系列--内存池MEMPOOL源码分析

一、目的嵌入式RTOS中最重要也是最容易被忽略的一个组件就是内存管理&#xff0c;像FreeRTOS单单内存管理组件就提供了heap_1/2/3/4/5这五种方案&#xff0c;每种方案都有其特点和应用场景。一般情况下小系统所运行的芯片平台本身内存就很少&#xff0c;有些时候内存空间还不连…

libdrm-2.4.112

编译 这个版本使用了meson进行构建、ninja进行编译 &#xff1b; 安装meson 编译 报错如上&#xff0c;查看meson.build文件&#xff0c; 我们的meson版本不正确&#xff0c; 查阅发现apt安装的版本过低&#xff1b; 安装meson sudo apt-get install python3 python3-pip …

LeetCode 111. 二叉树的最小深度

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 111. 二叉树的最小深度&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 一、题目名称 二、…

程序的编译与链接——ARM可执行文件ELF

读书《嵌入式C语言自我修养》笔记 目录 读书《嵌入式C语言自我修养》笔记 ARM编译工具 使用readelf命令查看ELF Header 使用readelf命令查看ELF section header 程序编译 预处理器 编译器 &#xff08;1&#xff09;词法分析。 &#xff08;2&#xff09;语法分析。 …

班级人员可视化项目

页面分布文件分布index.html(搭建页面)index.css (修饰页面)fonts (放图标)images &#xff08;放图片&#xff09;jsjquery.js &#xff08;调整页面的js&#xff09;flexible.js (尺寸大小的js)echarts.min.js (charts图表的js)chinaMap…

论文投稿指南——中文核心期刊推荐(中国医学 2)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

普元PAS部署springboot项目访问500

背景 项目需要从东方通部署迁移到普元PAS部署。记录一下遇到的问题 问题一 WebSocket启动异常: Error creating bean with name ‘serverEndpoint’ defined in class path resource 因为SpringBoot默认使用的容器是tomcat 对应的Websocket实现 PAS中直接使用ServerEndpoin…

虹科新品丨什么是光纤微动开关?(下)

HK-Micronor光纤微动开关 HK-MR386光纤微动开关和HK-MR380系列控制器搭配使用&#xff0c;提供了一种全新的创新型信号解决方案&#xff0c;可以长距离部署在困难和危险环境中。该开关传感器采用光中断的方法&#xff0c;通过双工62.5/125μm光纤链路&#xff0c;进行可靠的信号…

虹科方案|使用直接连接的阵列创建 SAN

一、引言通过将直连环境转换为共享存储&#xff0c;用户可以体验到物理主机之间或主机与存储之间更快的数据传输&#xff0c;从而使vMotion 实时迁移等 VMware 功能能 够在更短的时间内完成。二、关于VMWARE VSPHEREvSphere 平台是您的应用程序、云和业务 的最佳基础。 vSphere…

C语言_字符串旋转结果_C语言字符串旋转结果

上一篇博文讲了字符串左旋http://t.csdn.cn/8zbRf 这篇文章将讲解判断一个字符串是不是逆序过。 目录 一、问题描述 二、设计与分析 三、代码实现 一、问题描述 写一个函数&#xff0c;判断一个字符串是否为另外一个字符串旋转之后的字符串。 例如&#xff1a;给定s1 AAB…

【零基础】学python数据结构与算法笔记9

文章目录前言53.栈和队列的应用&#xff1a;迷宫问题54.使用栈解决迷宫问题55.使用队列进行迷宫问题&#xff1a;介绍56.使用队列进行迷宫问题&#xff1a;实现&#xff1a;总结前言 学习python数据结构与算法&#xff0c;学习常用的算法&#xff0c; b站学习链接 53.栈和队列…

【学习笔记之Linux】工具之vim配置

配置文件的位置&#xff1a; 在目录/etc/下面有一个名为vimrc的文件&#xff0c;这是系统中公共的vim配置文件&#xff0c;对所有用户都有效&#xff1b;   每个用户可以在自己的主目录下创建一个私有的配置文件&#xff0c;命名为“.vimrc”&#xff0c;这个配置只对自己有效…

如何利用MOS管实现双向电平转换

前面讲过的三极管和MOS管电平转换电路都是单向的&#xff0c;就是信号只能是从A输出到B输入。其实单个MOS管也能实现双向电平转换&#xff0c;即信号即能从A输出到B输入&#xff0c;也能从B输出到A输入。实际电路就是这个&#xff0c;包含一个MOS管和两个电阻&#xff0c;芯片1…

自定义启动器

&#x1f341;博客主页&#xff1a;&#x1f449;不会压弯的小飞侠 ✨欢迎关注&#xff1a;&#x1f449;点赞&#x1f44d;收藏⭐留言✒ ✨系列专栏&#xff1a;&#x1f449;SpringBoot专栏 &#x1f525;欢迎大佬指正&#xff0c;一起学习&#xff01;一起加油&#xff01; …

D. Meta-set(组合数学)

Problem - D - Codeforces 你喜欢纸牌棋盘游戏“集合”。每张牌包含k个特征&#xff0c;每个特征都等于集合{0,1,2}中的一个值。这副牌包含所有可能的纸牌变体&#xff0c;也就是说&#xff0c;总共有3k张不同的纸牌。 如果三张牌的某个特征与这三张牌相同或两两不同&#xff0…