C语言字符函数,字符串函数以及内存函数

那么博主写这一片博客的目的就是为下一篇c++的string类做铺垫,那么下面就请期待博主的下一篇文章吧。 

目录

1.字符函数

2.字符串函数(均在string.h头文件中)

strlen的使用和模拟实现

strcpy 的使用和模拟实现 

 strcat 的使用和模拟实现

 strcmp的使用和模拟实现

 strncpy 函数的使用

strncat 函数的使用

strncmp函数的使用

 strstr 的使用和模拟实现

strtok函数的使用

 strerror 函数的使用

3.C语言内存函数

memcpy使用和模拟实现

 memmove使用和模拟实现(可以实现自己给自己追加)

 memset函数的使用

 memcmp函数的使用


1.字符函数

        C语言标准库中的字符处理函数主要是在ctype.h头文件中定义的。先来看字符函数的速查表。

感觉很生涩?没关系,咱们来看几个例子:

写 ⼀个代码,将字符串中的⼩写字⺟转⼤写,其他字符不变。

int main ()

{

int i = 0;

char str[] = "Test String.\n";

char c;

while (str[i])

{

        c = str[i];

        if (islower(c))

        c -= 32;//小写字母与大写字母之间的ASCII值相差32。

        putchar(c);

         i++;

}

        return 0;

}

那么字符函数咱们就不过多的阐述了。下面看字符串函数。

2.字符串函数(均在string.h头文件中)

strlen的使用和模拟实现

size_t  strlen (const char*str) 

       1.  字符串以  '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含'\0')

       2. 参数指向的字符串必须要以 '\0' 结束。

       3. 注意函数的返回值为size_t,是无符号的

         4.strlen的使用需要包含头文件

那么下面咱们来看strlen的模拟实现,下面我提供了三种实现方式:

int my_strlen(const char * str)

{

        int count = 0;

        assert(str);

        while(*str)

{

        count++;

        str++;

}

        return count;

}//这个得引入一个新变量

int my_strlen(const char * str)

{

        assert(str);

        if(*str == '\0')

        return 0;

        else

        return 1+my_strlen(str+1); 

}//采用递归的方式

int my_strlen(char *s)

{

        assert(str);

        char *p = s;

        while(*p != '\0' )

{

        p++;

}

        return p-s; 

}//采用指针减指针的方式,这个方法在C语言指针这一篇博客有讲解

OK,下面进入六个函数的讲解

strcpy 的使用和模拟实现 

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

1.源字符串必须以 '\0' 结束。

2.会将源字符串中的 '\0' 拷贝到目标空间。

 3.目标空间必须足够大,以确保能存放源字符串。

4. 目标空间必须可修改 

5.从源头开始拷贝。

但是这样你打印的话,只能打印出来“xxx”,因为,打印自动到'\0'停止,所以你打印不出完整的拷贝后的字符串,不过可以通过调试观察。

以上也是strcpy函数的模拟实现。

思路:

1.由于返回起始空间的地址,所以要先保存起始空间的地址,防止后面++后,找不到起始空间的地址了。

2.接着断言,防止p与p1指针传的是无效地址。

3.然后把p1指向的字符串中的字符挨个拷贝到p指向的字符串中,之后p1指向的字符串中的字符位置与p指向的字符串中的位置都往后挪动一位。依次重复。

 strcat 的使用和模拟实现

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

1.源字符串必须以 '\0' 结束。

 2.目标字符串中也得有 \0 ,否则没办法知道追加从哪里开始。

3. 目标空间必须有足够的大,能容纳下源字符串的内容。

4. 目标空间必须可修改。 

5.destination中的'\0'也会被覆盖

以上是strcat的模拟实现,需要注意的是这里不可以自己给自己追加,否则会导致未定义。

思路:

1.首先先断言一下,由于这里传的是起始空间的地址,所以还要创建一个变量,用来存储起始地址。

2.之后先去找destination中的'\0',找到之后,就从这开始拷贝即可,需要注意的是,source中的'\0'也会别拷贝到目标字符串中。

 strcmp的使用和模拟实现

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

其实这个函数就是一个用于比较字符串大小的工具。 

1.第⼀个字符串大于第二个字符串,则返回大于0的数字 ◦

2.第⼀个字符串等于第二个字符串,则返回0 ◦

3.第⼀个字符串小于第二个字符串,则返回小于0的数字 ◦

4.那么如何判断两个字符串?比较两个字符串中对应位置上字符ASCII码值的大小。

下面看strcmp函数的模拟实现:

不过要注意的是这里博主用的编译器是vs,并且返不返回1,-1,0,纯看编译器,有的编译器就是不返回这几个数字。

模拟实现代码思路:

1.还是老样子先断言,之后从第一个字符的ASCII值开始比较。

2.如果第一个字符相等,那么++,继续往后比较,如果比较完了,直到最后一个标识字符'\0'都相等,那么就返回0.

3.如果第一个字符串的第一个字符比第二个字符串的第一个字符大,那么就返回1(vs下),否则返回-1.

以上三个函数都是长度不受限制的,那么下面看3个长度受限制的。

 strncpy 函数的使用

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

1.拷贝num个字符(不是字节)从源字符串到目标空间。

2.如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加'\0'(可通过调试观察),直到num个 。

该函数就是strcpy函数的减缩版,模拟实现方式差不多,这里就不做演示了。

strncat 函数的使用

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

1.将source指向字符串的num个字符追加到destination指向的字符串末尾,再追加⼀个'\0'字符。

很细节,方便打印 

2.如果source 指向的字符串的长度小于num的时候,它不会像strncpy一样,在后面追加'\0',而是直接不管,直接在destination的字符串末尾加一个'\0'即可。

strncmp函数的使用

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

比较str1和str2的前num个字符,如果相等就继续往后比较,最多比较num个字母,如果提前发现不⼀ 样,就提前结束,大的字符所在的字符串大于另外⼀个。如果num个字符都相等,就是相等返回0。 (就是比strcmp函数多了个限制条件)

 strstr 的使用和模拟实现

strstr的作用是用来查找子串的。

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

1.函数返回字符串str2在字符串str1中第一次出现的位置。

2.字符串的比较匹配不包含 '\0' 字符,以 '\0 '作为结束标志。

来看它的模拟实现吧。

思路:

1.首先先断言一下,因为要返回起始空间的地址,所以说要创建一个变量存放起始地址。

2.先来一个循环,条件是找的时候第一个字符串!='\0',之后,将指向第一个字符串的指针再赋值给s1,指向第二个字符串的指针再赋值给s2,之后便可以开始比较了。

3.如果说找到了s1跟s2相等的字符,那么各自++,继续往后比较,但凡有一个字符不相等了,直接退出循环,cur++,(即返回第一个字符串的起始地址,并且加一,让它从第一个字符串的第二个字符开始比较)。

4.如果说,比较完了,而且正好发现了第一个字符串中藏了第二个字符串,就是到了if阶段,那么这时候,s2就到了'\0'的位置,这时候直接返回当时找的第一个字符串的起始地址即可。

5.不过这里需要注意的是,你打印的时候,是会遇到'\0'才会停止的,所以说,比如,第一个字符串“abcdef”,第二个字符串“cde”,那么可以打印出cdef。

strtok函数的使用

1.sep参数指向⼀个字符串,定义了用作分隔符的字符集合 

2.第⼀个参数指定⼀个字符串,它包含了0个或者多个由sep字符串中⼀个或者多个分隔符分割的标 记。

 3.strtok函数找到str中的下⼀个标记,并将其用 \0 结尾,返回⼀个指向这个标记的指针。

(注: strtok函数会改变被操作的字符串,所以被strtok函数切分的字符串⼀般都是临时拷贝的内容并且可修改。)

 4.strtok函数的第⼀个参数不为 中的位置。 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串

 5.strtok函数的第⼀个参数为 NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标 记。

 6.如果字符串中不存在更多的标记,则返回 NULL 指针

 strerror 函数的使用

char* strerror ( int errnum );

strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来。 在不同的系统和C语言标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头文件中说明 的,C语言程序启动的时候就会使用⼀个全局的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发⽣了某种错误,就会将对应 的错误码,存放在errno中,而⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都 是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回 。

3.C语言内存函数(也在string.h头文件中)

memcpy使用和模拟实现(覆盖原理)

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

1.函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。

2. 这个函数在遇到 '\0' 的时候并不会停下来

3.如果source和destination有任何的重叠,复制的结果都是未定义的 。

4.对于重叠的内存,交给memmove来处理。

来看它的模拟实现

思路:

1.由于也是返回起始空间的地址,所以说先定义一个临时变量,用来存储起始空间的地址,之后再断言。

2.以count--为循环条件,决定了要拷贝的次数,并且让source中的字符拷贝到destination中,一个字符拷贝完之后,++,直到count被减完,才停止赋值。

 memmove使用和模拟实现(可以实现自己给自己追加)

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

其实memmove的用法与memcpy基本一样,就以下不同点:

1.和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

 2.如果源空间和目标空间出现重叠,就得使用memmove函数处理。 

来看它的模拟实现:

 memset函数的使用

void * memset ( void * ptr, int value, size_t num );

memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。 

 memcmp函数的使用

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

比较从ptr1和ptr2指针指向的位置开始,向后的num个字节 ,这个其实也是比较类的函数,与strcmp,strncmp差不多。

下面来看它的返回值:

再来看一个例子:

相信大家对这个函数也已经理解了吧。

以上内容是我个人理解,若有不对,还请指出!谢谢!

本篇完...............

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

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

相关文章

_DISPATCHER_HEADER结构中的WaitListHead和_KWAIT_BLOCK的关系

第一部分: // // Wait block // // begin_ntddk begin_wdm begin_nthal begin_ntifs begin_ntosp typedef struct _KWAIT_BLOCK { LIST_ENTRY WaitListEntry; struct _KTHREAD *RESTRICTED_POINTER Thread; PVOID Object; struct _KWAIT_BLOCK *R…

flutter 自定义控件RenderObjectWidget使用

CustomWidget的自定义组件的注释还是比较清晰的 参考文档Flutter实战 import package:flutter/cupertino.dart; import package:flutter/gestures.dart; import package:flutter/material.dart; /* * 如果组件不会包含子组件,则我们可以直接继承自 LeafRenderObject…

机器视觉场景应用中,有没有超景深的工业镜头

在机器视觉领域,确实存在具有超景深特性的工业镜头,这类镜头通过特殊的光学设计或技术手段,能够显著扩大清晰成像的纵向范围,从而满足复杂检测场景中对多平面物体清晰成像的需求。以下是相关技术要点及典型镜头类型: 1. 远心镜头 远心镜头是超景深镜头的典型代表,其特点包…

【Linux】同步原理剖析及模拟BlockQueue生产消费模型

📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…

光流 | 基于KLT算法的人脸检测与跟踪原理及公式,算法改进,matlab代码

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 人脸检测与跟踪 一、KLT算法原理与分析1. 核心思想2. 数学模型二、人脸…

<数据集>轨道异物识别数据集<目标检测>

数据集下载链接:https://download.csdn.net/download/qq_53332949/90527370 数据集格式:VOCYOLO格式 图片数量:1659张 标注数量(xml文件个数):1659 标注数量(txt文件个数):1659 标注类别数:6 标注类别…

LabVIEW液压振动锤控制系统

在现代工程机械领域,液压振动锤的高效与精准控制日益显得重要。本文通过LabVIEW软件,展开液压振动锤启停共振控制技术的研究与应用,探讨如何通过改进控制系统来优化液压振动锤的工作性能,确保其在复杂工况下的稳定性与效率。 ​ …

【开源宝藏】30天学会CSS - DAY7 第七课 CSS 关键帧打造Preloader 追逐动画

你的代码实现了一个 方形轨迹预加载动画(Preloader Animation),其中三个 span 元素沿着一个 22 网格 轨迹循环移动。现在,我们将 拆解核心实现步骤,让你能一步步理解并调整动画效果。 第 0 步:项目概览 你…

在shell脚本内部获取该脚本所在目录的绝对路径

目录 需求描述 方法一:使用 dirname 和 readlink 命令 方法二:使用 BASH_SOURCE 变量 方法三:仅使用纯 Bash 实现 需求描述 工作中经常有这样情况,需要在脚本内部获取该脚本自己所在目录的绝对路径。 假如有一个脚本/a/b/c/…

常考计算机操作系统面试习题(一下)

目录 操作系统基本类型 操作系统的功能 操作系统的主要任务 进程与线程 进程状态转变 内存管理 文件系统与文件管理 虚拟存储器 设备管理 磁盘调度 死锁 信号量机制 文件打开与管理 进程与线程的互斥与同步 进程同步 进程调度 文件分配磁盘块的方法 程序执行…

GPT-SoVITS本地部署:低成本实现语音克隆远程生成音频全流程实战

文章目录 前言1.GPT-SoVITS V2下载2.本地运行GPT-SoVITS V23.简单使用演示4.安装内网穿透工具4.1 创建远程连接公网地址 5. 固定远程访问公网地址 前言 今天要给大家安利一个绝对能让你大呼过瘾的声音黑科技——GPT-SoVITS!这款由花儿不哭大佬精心打造的语音克隆神…

JVM(基础篇)

一.初识JVM 1.什么是JVM JVM全称Java Virtyal Machine,中文译名 Java虚拟机 。JVM本质上是一个运行在计算机上的程序,他的职责是运行Java字节码文件(将字节码解释成机器码)。 2.JVM的功能 解释和运行:对字节码文件中的指令号,实时…

【高并发内存池】第四弹---深入理解PageCache:整体设计、核心实现及Span获取策略详解

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【Linux网络编程】【项目详解】 目录 1、pagecache 1.1、整体设计 1.2、核心实现 1.3、获取Span 1.3.1、获取一个非空的Span 1.3…

深入理解C语言数据结构之快速排序三路划分

在数据结构和算法的世界里,排序算法是基石一般的存在。快速排序作为一种高效的排序算法,以其平均情况下的优秀时间复杂度而被广泛应用。今天,让我们深入探讨快速排序的一种变体——三路划分的快速排序,看看它是如何在C语言中施展魔…

Java实现后量子密码(PQC)与国密算法(SM4)混合加密

以下是使用Java实现一种后量子密码(PQC)与国密算法(SM4)混合加密的示例方案。该方案结合了后量子密码的抗量子特性与国密算法的国产化合规要求,适合需要双重安全保障的场景。 一 . 方案验证 1.代码截图 2.运行测试 二 . 方案设计 密钥交换:使用后量子密码(如Kyber)生…

【SQL Server数据库备份详细教程】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

SpringBoot古典舞在线交流平台设计与实现

随着古典舞文化的普及,越来越多的人希望通过线上平台交流学习。幽络源作为一站式综合平台,致力于为用户提供免费源码、技术教程及网络兼职资源。本文将详细介绍基于SpringBoot的古典舞在线交流平台的设计与实现,帮助开发者快速搭建一个功能完…

关于绝对时间、人类时间、本地时间、时区时间的对比分析,结合编程场景(如Java)进行说明

以下是关于绝对时间、人类时间、本地时间、时区时间的对比分析,结合编程场景(如Java)进行说明: 1. 定义与核心区别 (1) 绝对时间(Absolute Time) 定义:不受时区影响,以固定时间起点…

go语言中的strings库

strings库 func EqualFold func EqualFold(s, t string) bool判断两个utf-8编码字符串(将unicode大写、小写、标题三种格式字符视为相同)是否相同。 func main() {fmt.Println(strings.EqualFold("hello", "hello")) //truefmt.…

Git冲突解决

目录 一、Git冲突产生的原因二、解决Git冲突的步骤1. 发现冲突2. 查看冲突文件3. 手动解决冲突4. 提交解决后的代码5. 完成合并 三、预防Git冲突的小技巧四、总结 在团队协作开发中,Git冲突是常见的问题。当多个开发者同时修改了同一个文件的不同部分,然…