c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(下))

上篇文章介绍了一些常用的字符串函数,大家可以跳转过去浏览一下:c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(上))_总之就是非常唔姆的博客-CSDN博客

今天接着来介绍一些: 


目录

一.字符串查找

1.strstr()

1.1示例

1.2注意事项:

1.3模拟实现

 2.strtok()

 2.1示例

2.2注意事项

 二.错误信息报告

1.strerror()

 1.1示例

1.2注意事项:

 三.内存操作函数

1.memcpy()

1.1示例

1.2注意事项

2.memmove()

 2.1示例

 2.2注意事项:

3.memset()

 3.1示例

 3.2注意事项:

 4.memcmp()

4.1示例

4.2注意事项:


一.字符串查找

1.strstr()

strstr是一个C标准库函数,用于在一个字符串中查找另一个字符串的第一次出现的位置。它的原型如下:

char *strstr(const char *haystack, const char *needle);

strstr函数接受两个参数,haystack是要搜索的字符串,needle是要查找的子字符串。函数返回一个指向第一次出现的子字符串的指针,如果找不到子字符串,则返回NULL

下面是strstr函数的工作原理:

  1. 首先,strstr函数会在haystack字符串中搜索needle字符串的第一个字符

  2. 一旦找到了与needle的第一个字符匹配的字符,strstr函数会继续比较haystack中的后续字符和needle中的字符,直到找到一个不匹配的字符或者needle中的所有字符都匹配

  3. 如果找到了完全匹配的子字符串,strstr函数会返回指向该子字符串的指针

  4. 如果在haystack中找不到子字符串,或者needle是一个空字符串,则strstr函数会返回NULL

1.1示例

int main()
{char arr1[] = "abcdef";char arr2[] = "cd";printf("%s", strstr(arr1, arr2));return 0;
}

 如果找到了完全匹配的子字符串,strstr函数会返回指向该子字符串的指针,结果如下:

1.2注意事项:

strstr函数是区分大小写的,如果要进行大小写不敏感的字符串比较,可以使用其他函数 

1.3模拟实现

char* my_strstr(const char* a1, const char* a2)
{char* cp = a1;char* str1 = a1;char* str2;while (*cp){str1 = cp;str2 = a2;while (*str1&&*str2&&*str1 == *str2){str1++;str2++;}if (*str2 == '\0'){return cp;}cp++;}return NULL;
}int main()
{char arr1[] = "abcdef";char arr2[] = "cd";printf("%s", my_strstr(arr1, arr2));return 0;
}

 2.strtok()

strtok是一个C标准库函数,用于将一个字符串分割成多个子字符串。它的原型如下:

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

其中,str是要分割的字符串delim是用作分隔符的字符串。函数返回一个指向分割后的第一个子字符串的指针,如果没有更多的子字符串,则返回NULL

strtok函数使用一个静态变量来保存当前的分割位置,因此在多次调用strtok时,需要将原始字符串传递给第一次调用,而后续的调用只需要传递NULL作为第一个参数

  • strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
  • strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记

 2.1示例

int main()
{char arr[] = "123@abc%ABC";char a[] = "@%";printf("%s\n", strtok(arr, a));/*printf("%s\n", strtok(NULL, a));*/return 0;
}

 结果如下:

 

int main()
{char arr[] = "123@abc%ABC";char a[] = "@%";printf("%s\n", strtok(arr, a));printf("%s\n", strtok(NULL, a));printf("%s\n", strtok(NULL, a));return 0;
}

 结果如下:

 充分利用性质可以写出这样的代码:

int main()
{char arr[] = "123@abc%ABC";char a[] = "@%";/*printf("%s\n", strtok(arr, a));printf("%s\n", strtok(NULL, a));printf("%s\n", strtok(NULL, a));*/for (char* ret = strtok(arr, a); ret != NULL;ret= strtok(NULL, a)){printf("%s\n", ret);}return 0;
}

2.2注意事项

需要注意的是,strtok函数会修改原始字符串,将分隔符替换为NULL字符。如果需要保留原始字符串,可以使用副本进行分割操作 


 二.错误信息报告

1.strerror()

strerror是一个C标准库函数,用于将错误码转换为对应的错误信息字符串。它的原型如下:

char * strerror( int errnum );

其中,errnum是错误码。函数返回一个指向错误信息字符串的指针

  • errnum是一个整数类型的错误码,通常用于表示函数调用或操作的结果状态
  • errno是一个全局变量,用于存储最近一次发生的错误码。当函数调用或操作失败时,它们通常会设置errno为一个非零的错误码,以指示错误的类型

 1.1示例

输出1~10分别代表的错误信息:

int main()
{for (int i = 1; i <= 10; i++){printf("%s\n", strerror(i));}return 0;
}

结果如下:
 

1.2注意事项:

strerror函数返回的指针指向的是一个静态分配的字符串,因此在多线程环境下不是线程安全的


 三.内存操作函数

1.memcpy()

memcpy是一个标准C库函数,用于将一段内存区域的数据复制到另一段内存区域。它的函数原型如下:

void *memcpy(void *dest, const void *src, size_t n);

其中,dest是目标内存区域的指针,src是源内存区域的指针,n是要复制的字节数。

memcpy函数将源内存区域的n个字节复制到目标内存区域中。如果源和目标区域重叠,memcpy函数的行为是未定义的。如果需要处理重叠区域的复制,可以使用memmove函数(下面介绍)

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

1.1示例

int main() 
{char src[] = "Hello, world!";char dest[20];memcpy(dest, src, strlen(src) + 1);printf("source string: %s\n", src);printf("copied string: %s\n", dest);return 0;
}

结果如下:

 

1.2注意事项

需要注意的是,memcpy函数不会自动添加字符串结束符\0,因此在复制字符串时需要将\0一起复制。在上面的示例中,strlen(src) + 1计算了源字符串的长度,并将其加1,以便复制\0 

2.memmove()

memmove是一个标准C库函数,用于将一段内存区域的数据复制到另一段内存区域,与memcpy函数类似。但是,memmove函数可以处理源和目标区域重叠的情况,而memcpy函数则不能

memmove函数的函数原型如下:

void *memmove(void *dest, const void *src, size_t n);

其中,dest是目标内存区域的指针,src是源内存区域的指针,n是要复制的字节数。

memmove函数将源内存区域的前n个字节复制到目标内存区域中。如果源和目标区域重叠,memmove函数会确保复制的结果是正确的,即使源和目标区域重叠。因此,memmove函数比memcpy函数更安全,但通常也更慢

 2.1示例

int main() 
{char str[] = "123456";memmove(str,str+3,3);printf("%s\n", str);return 0;
}

 结果如下:

 2.2注意事项:

需要注意的是,memmove函数和memcpy函数一样,不会自动添加字符串结束符\0,因此在复制字符串时需要将\0一起复制

3.memset()

memset是一个用于设置内存块内容的函数。它可以将指定的内存块中的每个字节都设置为特定的值。

memset函数的原型如下:

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

参数说明:

  • ptr:指向要设置的内存块的指针。
  • value:要设置的值,以整数形式提供。
  • num:要设置的字节数。

memset函数将ptr指向的内存块的num个字节设置为value指定的值

 3.1示例

int main() 
{char str[20] = { 0 };memset(str, 'A', 10);printf("%s\n", str);return 0;
}

 结果如下:

 3.2注意事项:

需要注意的是,memset函数是按字节进行设置的,因此对于非字符类型的数组,需要将value参数转换为相应的字节表示

 4.memcmp()

memcmp函数用于比较两个内存区域的内容是否相同,其原型如下:

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

参数说明:

  • ptr1:指向第一个内存区域的指针。
  • ptr2:指向第二个内存区域的指针。
  • num:要比较的字节数。

memcmp函数将ptr1指向的内存区域和ptr2指向的内存区域的前num个字节进行比较,返回值如下:

  • 如果两个内存区域相同,返回0。
  • 如果第一个内存区域小于第二个内存区域,返回负整数。
  • 如果第一个内存区域大于第二个内存区域,返回正整数

4.1示例

int main() 
{char str1[20] = "Hello, world!";char str2[20] = "Hello, world!";int result1 = memcmp(str1, str2, strlen(str1));printf("result = %d\n", result1);return 0;
}

结果如下:


 

4.2注意事项:

memcmp函数比较的是字节,因此对于非字符类型的数组,比较的结果可能与预期不同 

 


好了各位,这次的内容就先整理到这里吧!下次按照学习计划就打了结构体的部分知识内容啦! 

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

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

相关文章

扭线机控制

扭线机属于线缆加工设备&#xff0c;线缆加工设备种类非常多。有用于网线绞合的单绞&#xff0c;双绞机等&#xff0c;有关单绞机相关算法介绍&#xff0c;大家可以查看专栏相关文章&#xff0c;有详细介绍&#xff0c;常用链接如下&#xff1a; 线缆行业单绞机控制算法&#…

性能测试笔记

一、性能测试的概念 性能测试的概念 使用自动化工具&#xff0c;模拟不同的场景&#xff0c;对软件各项性能指标进行测试和评估的过程 性能测试的目的 评估当前系统能力&#xff0c;出现性能bug后&#xff0c;优化性能&#xff1a;预测未来的性能需求是否满足 例如&#xf…

【软考】8.2 编译程序基本原理/文法/正规式/有限自动机

《编译程序基本原理》 编译过程 词法分析&#xff1a; 针对单词&#xff1b;输入是字符&#xff1b;读的是字符流&#xff1b;语法分析&#xff1a; 针对语句&#xff1b;读的是记号流&#xff0c;即词法分析产生的一个个单词语义分析&#xff08;针对语句含义&#xff09; a.…

Golang interface 接口的应用场景 使用细节

应用场景介绍 对初学者讲&#xff0c;理解接口的概念不算太难&#xff0c;难的是不知道什么时候使用接口&#xff0c;下面我例举几个应用场景&#xff1a; 1.说现在美国要制造轰炸机&#xff0c;武装直升机&#xff0c;专家只需把飞机需要的功能/规格定下来即可&#xff0c;然…

Sql server 使用DBCC Shrinkfile 收缩日志文件

磁盘空间有限&#xff0c;需要收缩日志文件释放空间。 数据库名称上右击属性->文件,逻辑名称日志文件默认名称为“_log”结尾。 alter database 数据库 set recovery simple dbcc shrinkfile(XXX_log,2,truncateonly) alter database 数据库 set recovery full

【Vue2.0源码学习】生命周期篇-销毁阶段(destroy)

文章目录 1. 前言2. 销毁阶段分析3. 总结 1. 前言 接下来到了生命周期流程的最后一个阶段——销毁阶段。从官方文档给出的生命周期流程图中可以看到&#xff0c;当调用了vm.$destroy方法&#xff0c;Vue实例就进入了销毁阶段&#xff0c;该阶段所做的主要工作是将当前的Vue实例…

Vue 3 学习 源码解读

该文章内容为以下视频的学习笔记&#xff1a; 前言_哔哩哔哩_bilibili前言是秋招解决方案&#xff1a;深入 Vue3 源码&#xff0c;带你彻底打通 Vue3 源码面试的第1集视频&#xff0c;该合集共计13集&#xff0c;视频收藏或关注UP主&#xff0c;及时了解更多相关视频内容。htt…

微信小程序——CSS3渐变

SS3 渐变&#xff08;gradients&#xff09;可以在两个或多个指定的颜色之间显示平稳的过渡。CSS3 定义了两种类型的渐变&#xff08;gradients&#xff09;&#xff1a; 说明 1、线性渐变&#xff08;Linear Gradients&#xff09;- 向下/向上/向左/向右/对角方向&#xff1…

Spring AOP 详解及@Trasactional

Spring AOP 详解 AOP基础 AOP: Aspect Oriented Program, 面向切面编程。解耦&#xff08;组织结构调整&#xff09;、增强&#xff08;扩展&#xff09;。 AOP术语 术语 说明 Aspect&#xff08;切面&#xff09; 横切于系统的连接点实现特定功能的类 JoinPoint&#xf…

编译工具链 之二 详解 ELF 格式及标准、UNIX 发展、ABI

在计算机及嵌入式系统中&#xff0c;二进制文件也有一定的标准格式&#xff0c;通常会包含在各平台的应用程序二进制接口 &#xff08;Application Binary Interface&#xff0c;ABI&#xff09;规范中。它是编译工具链必须要遵守的规范&#xff08;编译工具链产生符合 ABI 的二…

Qt单一应用实例判断

原本项目中使用QSharedMemory的方法来判断当前是否已存在运行的实例&#xff0c;但在MacOS上&#xff0c;当程序异常崩溃后&#xff0c;QSharedMemory没有被正常销毁&#xff0c;导致应用程序无法再次被打开。 对此&#xff0c;Qt assistant中有相关说明&#xff1a; 摘抄 qt-s…

tailscale自建headscale和derp中继

tailscale自建headscale和derp中继 Tailscale 官方的 DERP 中继服务器全部在境外&#xff0c;在国内的网络环境中不一定能稳定连接&#xff0c;所以有必要建立自己的 DERP 服务器的。 准备工作&#xff1a; 需要有自己的云服务器&#xff0c;本示例为阿里云轻量服务器需要有…

Spring的beanName生成器AnnotationBeanNameGenerator

博主介绍&#xff1a;✌全网粉丝4W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

11.3 读图举例

一、低频功率放大电路 图11.3.1所示为实用低频功率放大电路&#xff0c;最大输出功率为 7 W 7\,\textrm W 7W。其中 A \textrm A A 的型号为 LF356N&#xff0c; T 1 T_1 T1​ 和 T 3 T_3 T3​ 的型号为 2SC1815&#xff0c; T 4 T_4 T4​ 的型号为 2SD525&#xff0c; T 2…

(高阶) Redis 7 第21讲 IO多路复用模型 完结篇

🌹 以下分享 Redis IO多路复用模型,如有问题请指教。🌹🌹 如你对技术也感兴趣,欢迎交流。🌹🌹🌹 如有对阁下帮助,请👍点赞💖收藏🐱‍🏍分享😀 IO多路复用模型是什么 I/O:网络IO 多路:多个客户端连接(连接即套接字描述符,即socket或channel),指…

leetcode 49. 字母异位词分组

2023.10.7 根据字母异位词的定义&#xff0c;可知&#xff1a;所有字母异位词经过排序之后得到的字符串相同&#xff0c;所以可以定义一个哈希表&#xff0c;将排序后的字符串当作哈希表的键&#xff0c;哈希表的值则用来存储该字母异位词对应的所有字符串&#xff0c;最后将哈…

HDLbits: Shift18

先补充一下算术移位寄存器和按位移位寄存器&#xff1a; SystemVerilog具有按位和算术移位运算符。 按位移位只是将向量的位向右或向左移动指定的次数&#xff0c;移出向量的位丢失。移入的新位是零填充的。例如&#xff0c;操作8’b11000101 << 2将产生值8’b00010100…

【数据结构-二叉树 八】【遍历求和】:求根到叶子节点数字之和

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【遍历求和】&#xff0c;使用【二叉树】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&am…

练[SUCTF 2019]CheckIn

[SUCTF 2019]CheckIn 文章目录 [SUCTF 2019]CheckIn掌握知识解题思路关键paylaod 掌握知识 ​ .user.ini文件上传利用–需要上传目录有一个php文件(index.php)&#xff0c;文件头绕过&#xff0c;文件内容<&#xff1f;检测 解题思路 打开题目链接&#xff0c;发现又是一…

[SWPUCTF 2021 新生赛]easy_sql - 联合注入||报错注入||sqlmap

[SWPUCTF 2021 新生赛]easy_sql 一、思路分析二、解题方法解法一&#xff1a;手注解法二&#xff1a;报错注入解法三&#xff1a;sqlmap 一、思路分析 这题可以直接参考&#xff1a;[NISACTF 2022]join-us - 报错注入&无列名注入 网站标题提示&#xff0c;参数是wllm ?…