字符串和字符串函数(1)
前言:
字符串在C语言中比较特别,没有单另的字符串类型,想要初始化字符串必须用字符变量的数组初始化,但是在C语言标准库函数中提供了大量能对字符串进行修改的函数,比如说可以实现字符串的的拷贝,字符串的追加,字符串的替换等等。
接下来就一起来学习这些功能,并且能够模拟实现以下这些函数的功能。
strlen函数
介绍并且使用:
简单了来说就是可以得到字符串的长度的函数,注意事项:
1、字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 含 '\0' )。
2、参数指向的字符串必须要以 '\0' 结束。
3、注意函数的返回值为size_t,是无符号的( 易错 )。
#include<stdio.h>
#include<stdlib.h>
int main()
{char arr[] = { "abcdefg" };printf("%u\n", strlen(arr));//因为strlen返回值是一个无符号整型,我们可以用%u打印return 0;
}
很容易计算出结果是7,也就是这个字符串中有7个字符。
模拟实现strlen函数
我们可以自己编写自己的strlen函数,只需要返回一个整型,然后即可,接下来用三种方式模拟实现strlen函数。
方法一:while循环
代码如下:
int my_strlen(char *arr)
{int num = 0;while (1){if (*arr == '\0'){break;}arr++;num++;}return num;
}
int main()
{char arr[] = { "abcdefg" };printf("%d\n",my_strlen(arr));return 0;
}
方法二:递归
int my_strlen(char* arr)
{if (*arr == '\0'){return 0;}else{return 1 + my_strlen(arr + 1);}
}
int main()
{char arr[] = { "abcdefg" };printf("%d\n",my_strlen(arr));return 0;
}
方式三:指针
//指针-指针的方式
int my_strlen(char *s)
{char *p = s;while(*p != ‘\0’ )p++;return p-s;
}
int main()
{char arr[] = { "abcdefg" };printf("%d\n",my_strlen(arr));return 0;
}
strcpy函数
介绍并使用:
可以进行字符串的拷贝。从源头拷贝到目的地。
注意事项:
1、源字符串必须以 '\0' 结束。
2、会将源字符串中的 '\0' 拷贝到目标空间。
3、目标空间必须足够大,以确保能存放源字符串。
4、目标空间必须可变。
int main()
{char arr1[] = {"abcde"};char arr2[20] = {0};strcpy(arr2,arr1);printf("%s\n", arr2);return 0;
}
模拟实现strcpy函数
这里需要强调几点:
1、由于是将一个数组的字符串传到另一个字符串中,所以这两个字符串里面应该都有位置,也就是传过去的地址不能是空值(NULL)
所以用assret断言一下,如果是空值,电脑会进行报错。
2、因为传进去的时候,也要将'\0'传进去所以当判断是'\0'的时候应该要跳出循环,在跳出之前最后将'\0'传进去。
根据注意事项,即可对strcpy函数进行模拟,返回类型为char*。代码如下:
#include<assert.h>
char* my_strcpy(char* arr2, const char* arr1)
{assert(arr1 !=NULL);assert(arr2 != NULL);char* arr = arr2;while (1){if (*arr1 == '\0'){*arr2 = *arr1;break;}*arr2 = *arr1;arr1++;arr2++;}return arr;
}
int main()
{char arr1[] = {"abcde"};char arr2[20] = {0};my_strcpy(arr2, arr1);printf("%s\n",arr2 );return 0;
}
当然这里可以对代码进行升级,升级如下:
#include<assert.h>
char* my_strcpy(char* arr2, const char* arr1)
{assert(arr1 !=NULL);assert(arr2 != NULL);char* arr = arr2;while (*arr2++ = *arr1++){;}*arr2 = *arr1;return arr;
}
int main()
{char arr1[] = {"abcde"};char arr2[20] = {0};my_strcpy(arr2, arr1);printf("%s\n",arr2 );return 0;
}
strcat函数
介绍并使用:
该函数可以对字符串进行追加(连接)
例如:
int main()
{char arr1[20] = {"abcd"};char arr2[] = {"efgh"};strcat(arr1, arr2);printf("%s\n", arr1);return 0;
}
效果如下:
注意事项:
1、源字符串必须以 '\0' 结束。
2、目标空间必须有足够的大,能容纳下源字符串的内容。
3、目标空间必须可修改。
模拟实现strcat函数
这里首先根据正常逻辑分析并my_strcat
char* my_strcat(char*arr1,const char* arr2)
{assert(arr1 != NULL);assert(arr2 != NULL);char* arr = arr1;while (1){if (*arr1 == '\0'){while (1){*arr1 = *arr2;arr1++;arr2++;if (*arr2 == 0){*arr1 = *arr2;break;}}break;}arr1++;}return arr;
}
int main()
{char arr1[20] = { "abcd" };char arr2[] = {"efgh"};//my_strcat(arr1, arr2);printf("%s\n", my_strcat(arr1, arr2));return 0;
}
可以进行一次改进:(减少if语句)
char* my_strcat(char*arr1,const char* arr2)
{assert(arr1 != NULL);assert(arr2 != NULL);char* arr = arr1;while (*arr1){arr1++;}while (1){*arr1 = *arr2;if (*arr2 == 0){*arr1 = *arr2;break;}arr1++;arr2++;}return arr;
}
int main()
{char arr1[20] = { "abcd" };char arr2[] = {"efgh"};//my_strcat(arr1, arr2);printf("%s\n", my_strcat(arr1, arr2));return 0;
}
可以进行第三次改进:
char* my_strcat(char* arr1, const char* arr2)
{assert(arr1 != NULL);assert(arr2 != NULL);char* arr = arr1;while (*arr1){arr1++;}while (*arr1++ = *arr2++)//先赋值后++{;}return arr;
}
int main()
{char arr1[20] = { "abcd" };char arr2[] = { "efgh" };//my_strcat(arr1, arr2);printf("%s\n", my_strcat(arr1, arr2));return 0;
}
strcmp函数
介绍并使用:
这个函数可以实现比较两个字符串:
比较的是两个字符串的ASCALL码值,从第一个字符开始比较,返回值是这样的:
当 str1大于str2的时候,返回>0的数
当str1小于str2的时候,返回<0的数
当str1等于str2的时候,返回 = 0的数
使用代码如下:
int main()
{char arr1[] = {"abcdf"};char arr2[] = {"abct"};if (strcmp(arr1, arr2) == 0){printf("=");}else if(strcmp(arr1, arr2)>0){printf(">");}else{printf("<");}return 0;
}
模拟实现strcmp函数
初步模拟:
int my_strcmp(const char* arr1, const char* arr2)
{assert(arr1 != NULL);assert(arr2 != NULL);while (1){if (*arr1 > *arr2){return 1;}else if(*arr2 > *arr1){return -1;}else if (*arr2 == '\0' && *arr1 == '\0'){return 0;}arr1++;arr2++;}}
int main()
{char arr1[] = {"abcdef"};char arr2[] = {"abcdfk"};int c = 0;c = my_strcmp(arr1,arr2);if (c > 0){printf(">");}else if (c < 0){printf("<");}elseprintf("=");return 0;
}
二次修改:
可以自己分析一下,while函数。
int my_strcmp(const char* src, const char* dst)
{int ret = 0;assert(src != NULL);assert(dst != 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;
}
int main()
{char arr1[] = {"abcdef"};char arr2[] = {"abcdefo"};int c = 0;c = my_strcmp(arr1,arr2);if (c > 0){printf(">");}else if (c < 0){printf("<");}elseprintf("=");return 0;
}
相关文章:

字符串和字符串函数(1)
前言: 字符串在C语言中比较特别,没有单另的字符串类型,想要初始化字符串必须用字符变量的数组初始化,但是在C语言标准库函数中提供了大量能对字符串进行修改的函数,比如说可以实现字符串的的拷贝,字符串的追…...

基于springboot+vue的班级综合测评管理系统
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...

蓝海项目揭秘:跨境选品师的崛起与挑战
随着全球化贸易的日益深入和电子商务的蓬勃发展,跨境选品师这一新兴职业逐渐走进人们的视野。跨境选品师,顾名思义,就是专门负责为跨境电商平台挑选和推荐适合海外市场的商品的专业人士。那么,跨境选品师这一职业能否被视为一个蓝…...

酷黑简洁大气体育直播自适应模板赛事直播门户网站源码
源码名称:酷黑简洁大气体育直播自适应模板赛事直播门户网站源码 开发环境:帝国cms 7.5 安装环境:phpmysql 支持PC与手机端同步生成html(多端同步生成插件) 带软件采集,可以挂着自动采集发布,无…...

2024年电工杯高校数学建模竞赛(B题) 建模解析| 大学生平衡膳食食谱的优化设计
问题重述及方法概述 问题1:膳食食谱的营养分析评价及调整 数学方法:线性规划模型、营养素评价模型、比较分析 可视化数据图:营养素含量表、营养素摄入量对比图、营养素缺乏情况图 问题2:基于附件3的日平衡膳食食谱的优化设计 数…...

学习编程对英语要求高吗?
学习编程并不一定需要高深的英语水平。我这里有一套编程入门教程,不仅包含了详细的视频讲解,项目实战。如果你渴望学习编程,不妨点个关注,给个评论222,私信22,我在后台发给你。 虽然一些编程资源和文档可能…...

使用 Django 和 RabbitMQ 构建高效的消息队列系统
文章目录 RabbitMQ 简介Django 中使用 RabbitMQ总结与拓展 在现代的 Web 应用程序开发中,构建一个高效的消息队列系统变得越来越重要。使用消息队列可以帮助我们解耦系统中不同模块的任务,并提高系统的性能和可扩展性。本文将介绍如何结合 Django 和 Rab…...

Pycharm常见问题1
问题: ValueError at /user/users/ The view user.views.get_users didnt return an HttpResponse object. It returned None instead. 问题分析: 视图user.views.get_users未返回HttpResponse对象,它返回值为None。也就是说在视图文件没有…...

开发一个comfyui的自定义节点
文章目录 目标功能开发环境comfyui自定义节点的实现原理仓库地址完整代码目标功能 开发一个comfyui的自定义节点,该节点的功能是:可以对comfyui工作流中最终输出的图像添加一些自定义文案,且可以指定文案在图像上的位置、文案的字体样式、字体大小、字体颜色等。最终效果如…...
Prime算法构造最小生成树(加点法)
一、算法逻辑 想要轻松形象理解Prime的算法逻辑,视频肯定比图文好。 小编看过很多求相关的教学视频,这里选出一个我认为最好理解的这一款安利给大家。 因为他不仅讲解细致,而且还配合了动画演示,可以说把一个抽象的东西讲的非常…...

【VTKExamples::Utilities】第五期 CommandSubclass
很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例CommandSubclass,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. CommandSubclass …...

重生之 SpringBoot3 入门保姆级学习(04、 包扫描)
重生之 SpringBoot3 入门保姆级学习(04、 包扫描) 2.1 包扫描 2.1 包扫描 默认包扫描规则: SpringBootApplication 标注的就是主程序 SpringBoot 只会扫描主程序下面的包 自动的 component-scan 功能 在 SpringBootApplication 添加参数可以…...

VectorDBBench在windows的调试
VectorDBBench在windows的调试 VectorDBBench是一款向量数据库基准测试工具,支持milvus、Zilliz Cloud、Elastic Search、Qdrant Cloud、Weaviate Cloud 、 PgVector、PgVectorRS等,可以测试其QPS、时延、recall。 VectorDBBench是一款使用python编写的…...

KAN(Kolmogorov-Arnold Network)的理解 1
系列文章目录 第一部分 KAN的理解——数学背景 文章目录 系列文章目录前言KAN背后的数学原理:Kolmogorov-Arnold representation theorem 前言 这里记录我对于KAN的探索过程,每次会尝试理解解释一部分问题。欢迎大家和我一起讨论。 KAN tutorial KAN背…...
Vue 项目中使用 Element UI库(Element UI 是一套基于 Vue.js 的桌面端组件库)
1. 安装 Element UI npm install element-plusnext 2.引入 Element UI(在main.js中引入组件,注意要引入.css文件,图标也要单独引用) import { createApp } from vueimport ElementPlus from element-plusimport element-plus/dist/index.css…...

C++240527
定义自己的命名空间 my_sapce,在 my_sapce 中定义 string 类型的变量 s1,再 定义一个函数 完成 对字符串的逆置 。 #include <iostream>//导入 标准命名空间,cout 和 endl 标识符 存在于标准命名空间中 using namespace std;//定义了自…...

揭秘动态网页爬取:步骤与实战技巧
新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、引言 二、动态网页爬取步骤 三、实战技巧分享 四、总结 一、引言 在大数据时代&#…...

Lvm逻辑卷调整容量
1、拉伸逻辑卷调整容量 [rootdesktop ~]# df ‐hT Filesystem Type Size Used Avail Use% Mounted on /dev/sda1 xfs 9.8G 3.3G 6.5G 34% / devtmpfs devtmpfs 660M 0 660M 0% /dev tmpfs tmpfs 674M 0 674M 0% /dev/shm tmpfs tmpfs 674M 8.9M 666M 2% /run tmpfs tmpfs 674M …...

CLIP源码详解:clip.py 文件
前言 这是关于 CLIP 源码中的 clip.py 文件中的代码带注释版本。 clip.py 文件的作用:封装了 clip 项目的相关 API,通过这些 API ,我们可以轻松使用 CLIP 项目预训练好的模型进行自己项目的应用。 另外不太容易懂的地方都使用了二级标题强…...
linux下重启oracle数据库步骤
Linux下重启oracle数据库步骤: 1.使用oracle用户登录数据库服务器(root登录的话进入数据库时会找不到sqlplus命令) su – oracle 2.通过数据库管理员sysdba进入oracle数据库 sqlplus / as sysdba 3.关闭数据库 shutdown immediate ࿰…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...