【C语言】字符串函数和内存函数及其模拟实现

文章目录

    • 前言
  • 一、常见字符串库函数
    • 1.strlen函数
    • 2.长度不受限制的字符串函数
      • 2.1 strcpy
      • 2.2 strcat
      • 2.3 strcmp
    • 3.长度受限制的字符串函数
      • 3.1 strncpy
      • 3.2 strncat
      • 3.3 strncmp
  • 二、字符串查找函数
      • strstr
      • strtok
  • 三、strerror函数
  • 四、内存操作函数
    • 1.memcpy
    • 2.memmove
    • 3.memcmp
  • 五、字符函数
    • 字符分类函数
    • 字符转换

前言

C语言中的字符串与C++不同,是没有类型的。C语言本身提供了一些对字符串进行处理的库函数,本篇整理了C语言中针对字符串或者字符数组的各种操作的库函数以及内存操作函数,包括其用法和模拟实现的过程。用到的头文件有#include<string.h>

关于库函数的使用,这里分享一个查阅工具 cplusplus,通过这个手册我们可以了解库函数的信息:头文件、函数名、函数参数、返回值类型等。

一、常见字符串库函数

1.strlen函数

size_t strlen (const char* str);

功能:求字符串长度

cplusplus的使用介绍,后面就不再展示了

在这里插入图片描述

可以看到,strlen所在头文件是string.h,返回值类型是size_t,函数参数类型是const char*,返回值表示的是字符串的长度。

1.字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
2.size_t 是一些C/C++标准在stddef.h中定义的,size_t 类型表示C中任何对象所能达到的最大长度,它是无符号整数,32位平台上,size_t 就是unsigned int,所以一般情况下我们可以用int接收返回值。

strlen的用法:

在这里插入图片描述

strlen的模拟实现:
这里简单说一下关键字assert(断言)的用法:如果assert()括号中的表达式是假,则会中止程序执行,并且会显示错误原因和位置。
在写函数的时候,先采用断言处理,防止字符串为空从而导致后续操作非法,同时方便找错误。

方法一:常规写法

size_t my_strlen(const char* str)//与库函数保持一致
{assert(str);size_t count = 0;while (*str++)//*str不等于'\0',就继续往后走直到遇到'\0'{count++;}return count;
}

方法二:指针减指针

size_t my_strlen(const char* str)
{assert(str);const char* start = str;//保存字符串起始地址//while (*str++);//如果这样写,str会走到'\0'后一个位置,最终需要返回str - start - 1while (*str){str++;}return str - start;
}

方法三:递归

size_t my_strlen(const char* str)
{assert(str);if (*str != '\0')return 1 + my_strlen1(str + 1);elsereturn 0;
}

在这里插入图片描述

2.长度不受限制的字符串函数

下面三种字符串函数都是直接对整个字符串进行操作,不能对部分内容单独操作。

2.1 strcpy

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

功能:将源字符串拷贝给目标字符串

1.源字符串必须以 ‘\0’ 结束
2.该函数会将源字符串中的“ \0 ”一同拷贝到目标空间,如果目标字符串原先就有内容,就会被拷贝的内容覆盖掉,包括“ \0 ”也是。
3.目标空间必须足够大,以确保能存放源字符串,如果放不下就会造成数组越界访问,为非法访问空间。
4.目标空间必须可变,不能是常量字符串。

2.1 strcpy用法:

在这里插入图片描述

注: 返回值是目标空间的起始地址,使用的时候可以接收也可以选择不接收返回值。

strcpy模拟实现:

char* my_strcpy(char* dest, const char* src)
{assert(dest && src);char* ret = dest;while (*dest++ = *src++);	//注意分号/*while (*dest++ = *src++){;		//或者这样写}*/ return ret;
}

2.2 strcat

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

功能:在目标字符串的末尾追加上源字符串

1.源字符串必须以 ‘\0’ 结束。
2.目标空间必须有足够的大,能容纳下源字符串的内容;
3.目标空间必须可修改。

strcat用法:

在这里插入图片描述

strcat模拟实现:

char* my_strcat(char* dest, const char* src)
{assert(dest && src);char* ret = dest;while (*dest){dest++;   //先找到目标字符串的末尾位置'\0'}while (*dest++ = *src++); //从'\0'位置开始追加return ret;
}

2.3 strcmp

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

功能:比较两个字符串的大小(字典序)

1.第一个字符串大于第二个字符串,则返回大于0的数字;
2.第一个字符串等于第二个字符串,则返回0;
3.第一个字符串小于第二个字符串,则返回小于0的数字。

比如:abdef 就比 ace 小,acd 比 acde 小。
比较两个字符串中对应位置上的字符大小,如果相同,就比较下一对,直到不同或都遇到'\0'

strcmp用法:

在这里插入图片描述

strcmp模拟实现:

int my_strcmp(const char* s1, const char* s2)
{assert(s1 && s2);while (*s1 == *s2){if (*s1 == '\0') //s1和s2都走到'\0',且前面字符都相等return 0;s1++;s2++;}return *s1 - *s2;
}

3.长度受限制的字符串函数

下面三个字符串函数是前面三个的衍生版本,既可以操作整个字符串,也可以单独对字符串的部分内容进行操作。

3.1 strncpy

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

功能:拷贝num个字符从源字符串到目标空间。

1.目标空间一定要足够大!
2.如果num大于源字符串的长度,则拷贝完源字符串之后,在目标的后边追加’\0’,直到num个。
3.拷贝num个字符就只会拷贝num个字符,不会再往后补一个’\0’。
4.与strcpy不同的是,strcpy会把目标字符串原本的内容销毁掉,而strncpy不会,多出来的部分仍然保留,见下图。

strncpy的使用:

在这里插入图片描述

3.2 strncat

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

功能:目标空间后面追加num个源字符串的字符

1.确保目标空间足够大;
2.会在追加完num个字符之后再追加一个’\0’

strncat的使用:

在这里插入图片描述

3.3 strncmp

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

功能:比较两个字符串前num个字符的大小

二、字符串查找函数

strstr

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

功能:判断str2是否是str1的子串,并返回str2在str1中首次出现位置的地址。

strstr的使用:

在这里插入图片描述

strstr模拟实现:

char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* s1 = str1;const char* s2 = str2;const char* p = str1;//p用来标记起始判断位置while (*p){s1 = p;	  //s1重新回到起始判断位置并开始判断s2 = str2;//只要遇到不一样的,s2就回到str2起始位置重新开始判断,直到走到str2的'\0'位置while (*s1 && *s2 && *s1 == *s2){s1++;s2++;}if (*s2 == '\0') //走到'\0'说明在str1中找到了str2return p;  	//返回判断成功的起始位置p++;	//否则str1中的起始判断位置往后+1}return NULL;
}

strtok

char* strtok (char* str, const char* sep);

功能:将字符串str按照sep中的分隔符进行分割

1.第一次使用将字符串传过去,在str中找到分隔符并用’\0’代替,返回并保存当前位置;
2.之后每次传参则传空指针NULL,该函数会从上次保存的位置开始向后继续分割;
3.字符串结束后会返回一个空指针;
4.strtok会修改原函数。

strtok的使用:

在这里插入图片描述

三、strerror函数

char* strerror (int errnum);

功能:返回指向错误信息字符串的指针
头文件:#include<errno.h>

这里也简单说一下perror的使用:

void perror(const char *str);

功能: 在输出错误消息时,这个字符串将作为错误消息的前缀,并在这个字符串后面自动打印错误信息。不需要处理消息的格式化和输出。
头文件#include<stdio.h>

strerror的使用:

在这里插入图片描述

四、内存操作函数

内存函数可以直接在内存中修改

1.memcpy

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

功能:从source位置拷贝num个字节的数据到目标空间的内存位置

1.单位是字节,不再局限于拷贝字符串;
2.遇到 ‘\0’ 的时候并不会停下来;

memcpy的使用:
在这里插入图片描述

memcpy模拟实现:

void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;while (num--){*(char*)dest = *(char*)src;//dest = (char*)dest + 1;//src = (char*)src + 1; ++(char*)dest;++(char*)src;}return ret;
}

注: 这里模拟实现的功能是和以前的memcpy的功能一样,如果dest和src的内存块发生位置重叠,例如上图中代码修改为:my_memcpy(arr2 + 3, arr2, 5 * sizeof(int));则会出现问题,导致原本想要拷贝的内容被覆盖。

而如今C语言中的memcpy库函数已经与下面即将登场的memmove函数功能一样了,可以处理源空间和目标空间出现重叠的问题。

2.memmove

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

功能:与memcpy功能一样,但是可以处理源空间和目标空间出现重叠的问题。

memmove的使用:

在这里插入图片描述

memmove模拟实现:

void* my_memmove(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;if (dest < src){while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else{while (num--){*((char*)dest + num) = *((char*)src + num);//从后往前拷贝,避免内容被覆盖}}return ret;
}

3.memcmp

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

功能:比较从ptr1和ptr2指针开始的num个字节

1.第一个内存块中的数据大于第二个内存块中的数据,则返回大于0的数字;
2.第一个内存块中的数据等于第二个内存块中的数据,则返回0;
3.第一个内存块中的数据小于第二个内存块中的数据,则返回小于0的数字。

在这里插入图片描述memvmp模拟实现:

int my_memcmp(const void* s1, const void* s2, size_t num)
{assert(s1 && s2);while (num--){if (*(char*)s1 > *(char*)s2)return 1;else if (*(char*)s1 < *(char*)s2)return -1;else{s1 = (char*)s1 + 1;s2 = (char*)s2 + 1;}}return 0;
}

五、字符函数

字符分类函数

char c = 'a';
int ret = 0;
ret = isdigit(c);//检查是否是十进制数字(0~9)
ret = isxdigit(c);//检查是否是十六进制数字(0~9, a~f, A~F)
ret = isalpha(c);//检查是否是字母(a~z, A~Z)
ret = isalnum(c);//检查是否是字母或者数字(a~z, A~Z, 0~9)
ret = islower(c);//检查是否是小写字母(a~z)
ret = isupper(c);//检查是否是大写字母(A~Z)
ret = isspace(c);//检查是否是空白字符(空格、TAB、换行、垂直TAB、换页、回车)
ret = iscntrl(c);//检查是否是控制字符
ret = isgraph(c);//检查是否是图形字符
ret = ispunct(c);//检查是否是标点符号(任何不属于数字或者字母的图形字符)
ret = isprint(c);//检查是否是可打印的

字符转换

char ch = 'a';
ch = tolower(ch);//ch转换为小写字母
ch = toupper(ch);//ch转换为大写写字母

字符和字符串函数终于整理完啦,感谢您的观看与支持!

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

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

相关文章

水经微图IOS版5.2.0发布

随时随地&#xff0c;微图一下&#xff01; 水经微图&#xff08;简称“微图”&#xff09;IOS新版已上线。 在该版本中主要新增图层树节点排序功能、常规&#xff08;矩形、圆、椭圆、扇形&#xff09;绘制功能、地形夸张等主要功能。 当前版本 当前版本号为&#xff1a;5…

蓝桥杯第2152题——红绿灯

问题描述 爱丽丝要开车去上班, 上班的路上有许多红绿灯, 这让爱丽丝很难过。为 了上班不迟到, 她给自己的车安装了氮气喷射装置。现在她想知道自己上班最 短需要多少时间。 爱丽丝的车最高速度是 米每秒, 并且经过改装后, 可以瞬间加速到小于 等于最高速的任意速度, 也可以瞵…

js可视化爬取数据生成当前热点词汇图

功能 可以爬取到很多数据&#xff0c;并且生成当前的热点词汇图&#xff0c;词越大越热门&#xff08;词云图&#xff09; 这里以b站某个评论区的数据为例&#xff0c;爬取63448条数据生成这样的图片 让我们能够更加直观的看到当前的热点 git地址 可以直接使用&#xff0c;中文…

【C++】类和对象②(类的默认成员函数:构造函数 | 析构函数)

&#x1f525;个人主页&#xff1a;Forcible Bug Maker &#x1f525;专栏&#xff1a;C 目录 前言 类的6个默认成员函数 构造函数 概念 构造函数的特性及用法 析构函数 概念 析构函数的特性及用法 结语 前言 本篇主要内容&#xff1a;类的6个默认成员函数中的构造函…

mysql四种引擎区别

MySQL 提供了多种不同的数据库引擎&#xff0c;其中最常见的有 MyISAM、InnoDB、MEMORY 和 BLACKHOLE。这四个引擎分别有以下特点&#xff1a; 1. MyISAM MyISAM 是 MySQL 的默认引擎。它对于只有较少的修改、大量读取的应用场景具有良好的性能。它不支持事务处理&#xff0c;也…

算法第四十一天-排除排序链表中的重复元素Ⅱ

排除排序链表中的重复元素Ⅱ 题目要求 解题思路 题意&#xff1a;在一个有序链表中&#xff0c;如果一个节点的值出现不止一次&#xff0c;那么把这个节点删除掉 重点&#xff1a;有序链表&#xff0c;所以&#xff0c;一个节点的值出现不止一次&#xff0c;那么他们必相邻。…

LeetCode-416. 分割等和子集【数组 动态规划】

LeetCode-416. 分割等和子集【数组 动态规划】 题目描述&#xff1a;解题思路一&#xff1a;01背包问题&#xff0c;动规五部曲解题思路二&#xff1a;0解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分…

【UE 委托】如何利用函数指针理解委托的基本原理

目录 0 引言1 函数指针模拟多播委托 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;UE虚幻引擎专栏&#x1f4a5; 标题&#xff1a;【UE 委托】如何利用函数指针理解委托的基本原理❣️ 寄语&#xff1a;书到用时方恨少&#xff0c;事非经过不知难…

OpenCV C++学习笔记

1.图像的读取与显示 1.1 加载并显示一张图片 #include<opencv2/opencv.hpp> #include<iostream>using namespace cv; using namespace std; int main(int argc,char** argv){Mat srcimread("sonar.jpg");//读取图像if(src.empty()){printf("Could…

ORA-00600: internal error code, arguments: [krbcbp_9]

解决方案 1、清理过期 2、control_file_record_keep_time 修改 恢复时间窗口 RMAN (Recovery Manager) 是 Oracle 数据库的备份和恢复工具。在 RMAN 中&#xff0c;可以使用“恢复窗口”的概念来指定数据库可以恢复到的时间点。这个时间点是基于最近的完整备份或增量备份。 …

创建一个qt登录界面,密码账号正确转到窗口2,否则弹出对话框提示账号密码错误,窗口2有四个按键,三个按键可以朗读按键文本,第四个退出。

作业要求&#xff1a; 主函数&#xff1a; int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();Form1 f;//连接窗口1的信号函数和窗口2打开的lambda函数Widget::connect(&w,&Widget::login,[&](){f.show();});return a.exec(); }窗…

leetcode73 矩阵置零

题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用原地算法。 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 输入&#xff1a;matrix [[0,1,2,0],[3,4…

力扣 |142. 环形链表 II

用快慢指针的方法 根据推出的表达式&#xff1a;slow和fast相遇的时候&#xff0c;让slow和位于头节点的p同时 向前走&#xff0c;刚好在入环的节点处相遇&#xff01;注意&#xff1a;b和c交界的点不一定是从例如-4这个节点处&#xff0c; 可能是0节点处。因为相遇的点只能是…

pycharm2024关闭项目后一直显示正在关闭项目

网上的很多教程都试了不行&#xff0c;直接用下面的方法有效解决。 点击 帮助--查找操作--输入Registry--点注册表&#xff0c;取消ide.await.scope.completion后的勾选即可。

(Oracle)SQL优化案例:隐式转换优化

项目场景 项目现场的某个kettle模型执行非常缓慢&#xff0c;原因在于某个SQL执行效率非常的低。甲方得知此事要求公司赶紧优化&#xff0c;负责该模块的同事对SQL优化并不熟悉。所以作为一个立志成为优秀DBA的ETL工程师&#xff0c;我自告奋勇&#xff1a;不是DBA&#xff0c;…

最新ChatGPT4.0工具使用教程:GPTs使用,Midjourney绘画,AI换脸,Suno-AI音乐生成大模型一站式系统使用教程

一、前言 ChatGPT3.5、GPT4.0、相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容甚至也可以和用户进行创作交流。 然而&#xff0c;GPT-4对普通用户来说都是需要额外付费才可以…

Docker+Uwsgi+Nginx部署Django项目保姆式教程

之前&#xff0c;我和大家分享了在docker中使用uwsgi部署django项目的教程。这次&#xff0c;为大家带来的是使用DockerUwsgiNginx部署Django项目。废话不多说&#xff0c;我们开干。 步骤1&#xff1a;使用命令创建一个django项目 我这里python版本使用的是3.9.x 首先&#…

千视电子携NDI 6前沿技术,亮相北京CCBN展呈现轻量化媒体解决方案

千视携NDI 6技术闪耀2024 CCBN展会&#xff0c;呈现轻量化媒体解决方案 2024年4月24日至26日&#xff0c;北京首钢会展中心将举办第三十届中国国际广播电视网络技术展览会&#xff08;CCBN2024&#xff09;。这是中国广播电视行业的一项重要盛会&#xff0c;将有国内外超600家…

AI预测体彩排3第2弹【2024年4月13日预测--第1套算法开始计算第2次测试】

各位小伙伴&#xff0c;今天实在抱歉&#xff0c;周末回了趟老家&#xff0c;回来比较晚了&#xff0c;数据今天上午跑完后就回老家了&#xff0c;晚上8点多才回来&#xff0c;赶紧把预测结果发出来吧&#xff0c;虽然有点晚了&#xff0c;但是咱们前面说过了&#xff0c;目前的…

微服务篇面试题

1、SpringCloud的组件有哪些&#xff1f; 2、负载均衡如何实现&#xff1f; 3、什么是服务雪崩&#xff1f;怎么解决&#xff1f; 4、项目中有没有做过限流&#xff1f; Tomcat单体可以&#xff0c;分布式不适合 5、解释一下CAP和BASE P&#xff1a;加入node03这边的网络断了&a…