C语言——字符函数和内存函数
目录
前言
字符函数
1strlen
模拟实现
2strcpy
模拟实现
3strcat
模拟实现
4strcmp
模拟实现
5strncpy
模拟实现
6strncat
模拟实现
7strncmp
模拟实现
8strstr
模拟实现
9strtok
10strerror
11大小写字符转换函数
内存函数
1memcpy
模拟实现
2memmove
模拟实现
3memset
4memcpy
前言
C语言对应字符串的处理很繁琐(比如经常要知道它们的长度啦,拷贝啦,移动啦): 所以专门提供了一些列字符(串)函数来方便使用者处理使用~
而我们在学习各种函数时,推荐cplusplus.com来进行学习使用~
字符函数
1strlen

a计算的是字符串总长度(不包含\0)
b参数传的是字符串首元素地址,返回类型是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(str2) - strlen(str1) = 3 - 6 <0 所以返回的是 str>2str1
但实际上是两个无符号整数相减,结果还是正整数!
模拟实现
//计数器
int Strlen1(char* s)
{int cnt = 0;while (*s != '\0'){cnt++;s++;}return cnt;
}//递归
int Strlen2(char* s)
{if (*s == '\0') return 0;return 1 + Strlen2(++s);//先s移动再递归!
}//指针-指针
int Strlen3(char* s)
{char* begin = s, * end = s;while (*end != '\0') end++;return end - begin;
}
2strcpy

a 源字符串(第二个参数)必须以 '\0' 结束;
否则会不断给目的字符串复制,des字符串复制超过最大空间后,就会越界访问(程序崩溃)
b复制会将源字符串中的 '\0' 拷贝到目标空间。
c目标空间必须足够大,以确保能存放源字符串;小于(源字符串的长度+1)同样崩
所以目标空间必须可变,如char*类型
模拟实现
char* Strcpy(char* desnation, const char* source)
{char* ret = desnation;while (*desnation++ = *source++)//拷贝了source的'\0'后循环停止{}return ret;
}
3strcat

a源字符串必须以 '\0' 结束。
b目标空间必须有足够的大,能容纳下源字符串的内容。
c目标空间必须可修改。
自己给自己追加,如何?
理论上会一直遇不到‘\0’,直到越界访问程序崩溃! 但实际上库函数是可以实现自己给自己追加,但还是不推荐这样做~
模拟实现
char* Strcat(char* desnation, const char* source)
{char* ret = desnation;while (*desnation != '\0'){desnation++;}//des指向'\0'while (*desnation++ = *source++){}return ret;
}
4strcmp

该函数用来进行两个字符串的比较大小:从第一个字符开始比,如果相同就往下一个比...
返回值:
>0 说明str1比str2大
=0 说明str1与str2一样大
<0 说明str1比str2小
模拟实现
int Strcmp(const char* str1, const char* str2)
{while (*str1 == *str2){if (*str1 == '\0') return 0;str1++;str2++;}//if (*str1 > *str2) return 1;//else return -1;return *str1 - *str2 >0 ? 1 : -1;
}
以上的strcpy,strcat和strcmp都是不受长度限制的函数,同时使用时必须先考虑字符串长度大小, 而接下来的函数则是受长度限制的函数,相对安全些~
5strncpy

与strcpy功能类似,但加了一个num参数,表示你当前要拷贝多少个字符(‘\0’算在内)
模拟实现
char* Strncpy(char* desnation, const char* source,int num)
{char* ret = desnation;while ((num--)&&(*desnation++ = *source++))//拷贝了source的'\0'后循环停止{}return ret;
}
6strncat

与strcat是类似的:但你可以选择追加num个字符(‘\0’不算在内),追加完后自动加'\0'!
模拟实现
char* Strncat(char* desnation, const char* source,int num)
{char* ret = desnation;while (*desnation != '\0'){desnation++;}while ((num--)&&(*desnation++ = *source++)){}*desnation = '\0';//不管source指没指向'\0'都要添加return ret;
}
7strncmp

与strcmp是类似的:但你可以自己选择num个字符进行比较
模拟实现
int Strncmp(const char* str1, const char* str2,int num)
{while ((--num)&&(*str1 == *str2)){if (*str1 == '\0') return 0;str1++;str2++;}if (*str1 == *str2) return 0;else return *str1 - *str2 > 0 ? 1 : -1;
}
8strstr

从str1中找包含str2的子串,找到了就返回str1出现子串的第一个位置的地址~

模拟实现
const char* Strstr(const char* str1, const char* str2)
{if (*str2 == '\0') return str1;//边界情况//匹配过程每次比较时的开始位置const char* p1 = str1;//进行移动判断字符是否相等const char* m1;const char* m2;while (*p1 != '\0'){m1 = p1, m2 = str2;while (*m2 != '\0' && *m1 == *m2){m1++;m2++;}if (*m2 == '\0') return p1;p1++;}return NULL;
}
9strtok

a delimiters是一个标记符集合;
b 将str中出现的标记符进行替换成“\0”(调用一次只会替换一个);
c 如果替换操作完成,返回替换开始前的地址;替换失败(找不到标记符),返回NULL;
d 也就是说:str传进来的参数是要被进行修改的,所以使用前要先将内容进行拷贝一份;
e 调了一次后,接下来要把str置NULL(因为strtok已经记住了下次从什么位置开始替换)
int main()
{char str[] = "zzj@qq.com";char arr[20];strcpy(arr, str);/*char* pch;pch = strtok(arr, ".@");while (pch != NULL){printf("%s\n", pch);pch = strtok(NULL, ".@");}*/for (char* pch = strtok(arr, ".@"); pch != NULL; pch = strtok(NULL, ".@")){printf("%s\n", pch);}return 0;
}

10strerror

返回错误码所对应的信息字符串,我们需要再用printf进行打印出来

相对类似的还有 perror 它不用printf打印方便些:

11大小写字符转换函数
小转大:toupper 大转小:tolower
内存函数
为了防止拷贝内容不只有字符串(可以用strncpy),所以需要内存函数来实现
1memcpy

从source中复制num个字节到destination中;

模拟实现
void* Memcpy(void* de, void* so, size_t num)
{while (num--){*((char*)de) = *((char*)so);//前置++在vs或许能过,但在别的平台就不能保证(++优先级高于强转)//++(char*)de;//++(char*)so;de=(char*)de+1;so=(char*)so+1;}
}
能不能实现在同一个数组进行拷贝?

如果用我们模拟实现出来的函数,是不行的:拷贝时会把后面的数给覆盖掉!
标准规定:使用非一块空间复制用memcpy;使用同一块空间复制用memmove
但是如果用memcpy呢?

居然是可以!难道是我们实现出来的代码有问题? 当然不是:我们实现出来的按照标准来说是合格了的;但在VS平台中实现的memcpy不仅是符合标准的,而且还把它给加强了,只能说是满分级别的标准~
2memmove

与memcpy的参数是一样的,通常用来解决同一块空间进行复制
模拟实现
解决上面数据被覆盖的问题,我们可以选择从后先前拷贝,那是不是所有的情况都适合?

如果是上面的情况,从后先前拷贝也出现了数据被覆盖的问题,这时选择从前向后拷贝更合适~
所以要分情况进行讨论:来决定用那种拷贝方式

3memset
以字节为单位:将num个字节设置成value值
应用与字符串时:

能做到,那如果想把int类型的值进行修改呢?

做不到:它是按字节为单位进行修改的;如果是修改成0的话就可以
所以它通常是用来进行将空间全部置为0(清理空间)
4memcpy

以字节为单位比较从desnation和source指针开始的num个字节

使用:

以上便是全部内容,有问题欢迎在评论区指正,感谢观看!
相关文章:
C语言——字符函数和内存函数
目录 前言 字符函数 1strlen 模拟实现 2strcpy 模拟实现 3strcat 模拟实现 4strcmp 模拟实现 5strncpy 模拟实现 6strncat 模拟实现 7strncmp 模拟实现 8strstr 模拟实现 9strtok 10strerror 11大小写字符转换函数 内存函数 1memcpy 模拟实现 2…...
查询docker overlay2文件夹下的 c7ffc13c49xxx是哪一个容器使用的
问题背景 查询docker overlay2文件夹下的 c7ffc13c49xxx是哪一个容器使用的 [root@lnops overlay2]# du -sh * | grep G 1.7G 30046eca3e838e43d16d9febc63cc8f8bb3d327b4c9839ca791b3ddfa845e12e 435G c7ffc13c49a43f08ef9e234c6ef9fc5a3692deda3c5d42149d0070e9d8124f71 1.…...
Golang的容器编排实践
Golang的容器编排实践 一、Golang中的容器编排概述 作为一种高效的编程语言,其在容器编排领域也有着广泛的运用。容器编排是指利用自动化工具对容器化的应用进行部署、管理和扩展的过程,典型的容器编排工具包括Docker Swarm、Kubernetes等。在Golang中&a…...
【51项目】51单片机自制小霸王游戏机
视频演示效果: 纳新作品——小霸王游戏机 目录: 目录 视频演示效果: 目录: 前言:...
ArkTs之NAPI学习
1.Node-api组成架构 为了应对日常开发经的网络通信、串口访问、多媒体解码、传感器数据收集等模块,这些模块大多数是使用c接口实现的,arkts侧如果想使用这些能力,就需要使用node-api这样一套接口去桥接c代码。Node-api整体的架构图如下&…...
【数据库初阶】MySQL中表的约束(上)
🎉博主首页: 有趣的中国人 🎉专栏首页: 数据库初阶 🎉其它专栏: C初阶 | C进阶 | 初阶数据结构 亲爱的小伙伴们,大家好!在这篇文章中,我们将深入浅出地为大家讲解 MySQL…...
173. 矩阵距离 acwing -多路BFS
原题链接:173. 矩阵距离 - AcWing题库 给定一个 N行 M 列的 01矩阵 A,A[i][j] 与 A[k][l]]之间的曼哈顿距离定义为: dist(i,j,k,l)|i−k||j−l|| 输出一个 N 行 M 列的整数矩阵 B,其中: B[i][j]min1≤x≤N,1≤y≤M,A…...
Linux下部署Redis集群 - 一主二从三哨兵模式
三台服务器redis一主二从三哨兵模式搭建 最近使用到了redis集群部署,使用一主二从三哨兵集群部署redis,将自己部署的过程中的使用心得分享给大家,希望大家以后部署的过程减少一些坑。 服务器准备 3台服务器 ,确定主redis和从red…...
实战设计模式之建造者模式
概述 在实际项目中,我们有时会遇到需要创建复杂对象的情况。这些对象可能包含多个组件或属性,而且每个组件都有自己的配置选项。如果直接使用构造函数或前面介绍的工厂方法来创建这样的对象,可能会导致以下两个严重问题。 1、参数过多。当一个…...
活动预告 | Microsoft Azure 在线技术公开课:使用 Azure OpenAI 服务构建生成式应用
课程介绍 通过 Microsoft Learn 免费参加 Microsoft Azure 在线技术公开课,掌握创造新机遇所需的技能,加快对 Microsoft Cloud 技术的了解。参加我们举办的“使用 Azure OpenAI 服务构建生成式应用”活动,了解如何使用包括 GPT 在内的强大的…...
ubuntu安装firefox
firefox下载地址:https://ftp.mozilla.org/pub/firefox/releases/ 卸载 sudo apt-get update dpkg --get-selections |grep firefox apt-get purge firefox 解压 tar -xjf firefox*.tar.bz2复制文件 sudo mv firefox/ /opt/firefox30sudo mv /usr/bin/firefox /…...
计算机网络原理(谢希仁第八版)第4章课后习题答案
第四章 网络层 详细计算机网络(谢希仁-第八版)第四章习题全解_计算机网络第八版谢希仁课后答案-CSDN博客 1.网络层向上提供的服务有哪两种?是比较其优缺点。网络层向运输层提供 “面向连接”虚电路(Virtual Circuit)服…...
RabbitMQ-基本使用
RabbitMQ: One broker to queue them all | RabbitMQ 官方 安装到Docker中 docker run \-e RABBITMQ_DEFAULT_USERrabbit \-e RABBITMQ_DEFAULT_PASSrabbit \-v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \--network mynet\-d \rabbitmq:3…...
从零开始学架构——互联网架构的演进
1 技术演进 1.1 技术演进的动力 对于新技术,我们应该站在行业的角度上思考,哪些技术我们要采取,哪些技术我们不能用,投入成本过大会不会导致满盘皆输?市场、技术、管理三者组成的业务发展铁三角,任何一个…...
python +tkinter绘制彩虹和云朵
python tkinter绘制彩虹和云朵 彩虹,简称虹,是气象中的一种光学现象,当太阳光照射到半空中的水滴,光线被折射及反射,在天空上形成拱形的七彩光谱,由外圈至内圈呈红、橙、黄、绿、蓝、靛、紫七种颜色。事实…...
重新整理机器学习和神经网络框架
本篇重新梳理了人工智能(AI)、机器学习(ML)、神经网络(NN)和深度学习(DL)之间存在一定的包含关系,以下是它们的关系及各自内容,以及人工智能领域中深度学习分支对比整理。…...
TypyScript从入门到精通
TypyScript从入门到精通 TypyScript 是什么?增加了什么环境搭建二、为何需要 TypeScript三、编译 TypeScript四、类型声明五、类型推断基本类型六、类型总览JavaScript 中的数据类型TypeScript 中的数据类型1. 上述所有 JavaScript 类型2. 六个新类型:3.…...
【MATLAB】绘制投资组合的有效前沿
文章目录 一、数据准备二、有效前沿三、代码3.1 数据批量读取、预处理3.2 绘制可行集3.3 绘制有效前沿3.4 其它-最大夏普率 一、数据准备 准备多个股票的的历史数据,目的就是找到最优的投资组合。 下载几个标普500里面的公式的股票数据吧,下载方法也可…...
matlab时频分析库
time frequency gallery...
GBase 8s 数据库备份还原
每一天都是一个新的篇章,等待着你去书写属于自己的故事!!! 一:备份 1.1.下载脚本文件,并上传到数据库服务器上相应目录。 解压后目录为: 说明: dbcomm.sh:导出注释脚本…...
深入解析 vSphere 7 vMotion 迁移实战:从单中心到跨中心的无缝迁移策略
1. vMotion迁移的核心价值与场景定位 当你凌晨三点接到机房断电预警电话时,vMotion可能是你最想拥抱的技术。作为vSphere的"灵魂功能"之一,vMotion允许我们将运行中的虚拟机在不同主机间无缝迁移,就像给飞行中的飞机更换引擎——用…...
Altium Designer 实战指南:高效创建与优化PCB封装库
1. Altium Designer封装库基础入门 刚接触PCB设计时,我最头疼的就是封装库的创建。记得第一次画板子,因为电阻封装画错导致整批板子返工,那种挫败感至今难忘。现在用Altium Designer做封装就像搭积木一样简单,关键是要掌握正确的方…...
LeetCode 300. Longest Increasing Subsequence 题解
LeetCode 300. Longest Increasing Subsequence 题解 题目描述 给你一个整数数组 nums,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,…...
Spring Security实战:Bcrypt加密算法在用户密码存储中的正确使用姿势(附完整代码)
Spring Security实战:Bcrypt加密算法在用户密码存储中的正确使用姿势(附完整代码) 在当今数字化时代,用户密码安全已成为系统开发中最基础也最关键的一环。作为开发者,我们经常面临一个核心问题:如何在数据…...
利润中心(Profit Center)和段(Segment)在 SAP 中关系非常紧密,但它们的设计目的和应用场景有本质区别
利润中心(Profit Center)和段(Segment)在 SAP 中关系非常紧密,但它们的设计目的和应用场景有本质区别。简单来说,段(Segment)是利润中心的一个上级归类。它们之间通常是“一对多”的…...
从原理到实战:位运算巧解最小码距(附完整代码)
1. 什么是码距?从生活场景理解概念 第一次听到"码距"这个词时,我脑海里浮现的是超市货架上相似商品间的距离。后来才发现,在计算机世界里,它描述的是两个编码之间的差异程度。举个生活中的例子:假设我们用5…...
Windows 10/11下用StyleGAN2-ADA-PyTorch训练自己的数据集(避坑Visual Studio编译错误)
Windows平台StyleGAN2-ADA-PyTorch环境配置全指南:从编译错误到自动化训练 在Windows 10/11上配置StyleGAN2-ADA-PyTorch环境时,许多开发者都会遇到Visual Studio编译工具链缺失的经典问题。不同于Linux系统的开箱即用,Windows环境需要额外处…...
Czkawka:智能存储管理的5个核心解决方案
Czkawka:智能存储管理的5个核心解决方案 【免费下载链接】czkawka Multi functional app to find duplicates, empty folders, similar images etc. 项目地址: https://gitcode.com/GitHub_Trending/cz/czkawka 1.0 现象剖析:数字存储管理的现实困…...
Phi-3-mini-4k-instruct-gguf应用落地:教育场景中的作业辅导与知识点提炼
Phi-3-mini-4k-instruct-gguf应用落地:教育场景中的作业辅导与知识点提炼 1. 教育场景中的AI助手需求 想象一下这样的场景:晚上10点,孩子还在为数学作业发愁,家长已经精疲力尽;老师批改着第50份作文,眼睛…...
[Windows 驱动] 深入解析进程名获取的多种内核方法
1. Windows驱动开发中的进程名获取基础 在Windows内核驱动开发中,获取进程名是最基础但至关重要的操作之一。想象一下,你正在开发一个安全监控驱动,需要实时检查哪些进程正在运行;或者你在开发一个性能优化工具,需要针…...
