11-25碎片小知识

一.strlen补充

strlen函数返回值是size_t,即无符号整型,

size_t有头文件,是stdio.h

由于strlen函数返回值是无符号整型,所以下面代码要注意

-3会被转换成无符号的

实现my_strlen

法一:指针减指针

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_strlen(const char* str)
{assert(str!=NULL);char* start = str;while (*str != '\0'){str++;}return str - start;
}
int main()
{char arr[] = "abcdef";int len = my_strlen(arr);printf("%d", len);return 0;
}

指向字符串结尾的指针减去指向字符串开头的指针。

别忘了assert

法二:递归

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_strlen(const char* str)
{assert(str!=NULL);if (*str == '\0')return 0;elsereturn 1 + my_strlen(str + 1);
}
int main()
{char arr[] = "abcdef";int len = my_strlen(arr);printf("%d", len);return 0;
}

二.strncpy

当拷贝的个数小于arr2的长度时,该拷贝几个就拷贝几个,不会在结尾加上\0;

当拷贝的个数大于arr2的长度时,不够的就会补充\0.

三.strncat

当要追加的个数小于arr2的个数时,在结尾还要追加上\0

当要追加的个数大于arr2的个数时,把arr2的内容全部拷过去之后,再加一个\0,而不是把剩余的都追加成\0。

四.strstr补充

实现my_strstr

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);char* cur = str1;char* s1 = NULL;char* s2 = NULL;if (*str2 == '\0')return str1;while (*cur){s1 = cur;s2 = str2;while (*s1 == *s2){s1++;s2++;}if (*s2 == '\0')return cur;elsecur++;}return NULL;
}
int main()
{char arr1[20] = "abbbcdef";char arr2[]="bbcd";char* ret=my_strstr(arr1, arr2, 5);if(ret!=NULL){printf("%s", ret);}else{printf("找不到");}return 0;
}

这段代码有问题

对于arr1=“abcdef”  arr2=“def”  

s1和s2一起开始往后移动后,会出现*s1==*s2=='\0',然后s1 s2会继续++,导致越界访问,所以要修改为

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);char* cur = str1;char* s1 = NULL;char* s2 = NULL;if (*str2 == '\0')return str1;while (*cur){s1 = cur;s2 = str2;while (*s1 && *s2 && *s1 == *s2)//防止出现越界访问的情况{s1++;s2++;}if (*s2 == '\0')return cur;elsecur++;}return NULL;
}
int main()
{char arr1[20] = "abbbcdef";char arr2[]="bbcd";char* ret=my_strstr(arr1, arr2, 5);if(ret!=NULL){printf("%s", ret);}else{printf("找不到");}return 0;
}

这样修改之后,内岑循环终止的可能性就有三个,s1指向\0或s2指向\0或*s1!=*s2,然后,对于s2指向\0的情况,就可以返回指针了

五.memcpy补充

实现my_memcpy

比如将int arr2[]={1,2,3,4,5,6,7,8,9,0}中的4567拷贝到arr1中,如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>void* my_memcpy(void* dest, const void* src, size_t num)
{int i;void* ret = dest;for (i = 0; i < num; i++){*(char*)dest = *(char*)src;((char*)dest)++;((char*)src)++;}return ret;
}
int main()
{int arr1[10] = { 0 };int arr2[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};my_memcpy(arr1, arr2+3, 16);printf("%s", arr1);return 0;
}

注意

1.4567是16个字节,所以传参时传4

2.void*指针无法进行加1操作,所以转换成char*指针,一个字节一个字节地拷贝

3.((char*)dest)++;
        ((char*)src)++;

这俩句代码在某些编译器下会报错,最好改为:

dest=(char*)dest+1;src=(char*)src+1;

4.这个模拟实现函数有缺陷,它在拷贝重叠内容时会出错,如下

当想把arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }中的12345拷贝到45678的位置时,就会出错,这是因为在拷贝4,5之前,45已经被修改为12。

对于这种的,倒着拷贝就可以

而当想把arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }中的45678拷贝到12345的位置时,就不能用倒着拷贝了,就得正着拷贝。如下

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest&&src);int i;void* ret = dest;if (((char*)dest - (char*)src) < num){for (i = num - 1; i >= 0; i--){*((char*)dest + i) = *((char*)src + i);//注意,i必须是涉及到0~num-1,就好像用下标访问元素一样,首元素的下标为0,第n个元素的下标为n-1;}}else{for (i = 0; i < num; i++){*((char*)dest + i) = *((char*)src + i);dest = (char*)dest + 1;src = (char*)src + 1;}}return ret;
}
int main()
{int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };my_memcpy(arr+3, arr , 20);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

for (i = num - 1; i >= 0; i--)
        {
            *((char*)dest + i) = *((char*)src + i);
        }

这段代码也可以改为:

while(num--)//先使用,后减一,可以访问到0~num-1。

{

        *((char*)dest + num) = *((char*)src + num);
}

但是,库函数memcpy不会处理这种重叠拷贝的现象,如果有重叠拷贝,就要用memmove库函数

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

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

相关文章

CleanMyMac X好不好用?有哪些优势

CleanMyMac X2024正是这一愿景和使命的体现。 作为一个团队&#xff0c;我们致力于采用令人过目不忘的设计来打造我们引以为豪的产品。 这是 UX/UI 设计已经成为我们核心价值的原因之一。 这也是我们不断完善它&#xff0c;从而为我们的用户创造最神奇体验的动力。 CleanMyMac …

论文导读 | 10月专题内容精选:人的预测

编者按 本次论文导读&#xff0c;编者选择了10月份OR和MS上与"人的预测"有关的三篇文章&#xff0c;分别涉及群体智慧的提取&#xff0c;个体序列预测的评估&#xff0c;以及决策者对风险的扭曲感知在分布式鲁棒优化中的应用。其中&#xff0c;从基于"生成式可能…

Java、PHP、C语言经典项目源码合集推荐(一)

&#xff08;一&#xff09;.Java智慧校园系统源码、 智慧学校源码、 智慧校园平台源码、智慧校园电子班牌系统源码、中小学智慧校园系统源码、 原生微信小程序端源码、电子班牌系统源码 项目技术栈 1、使用springboot框架Javavue2 2、数据库MySQL5.7 3、移动端小程序使用小程…

基于springboot实现智慧党建系统项目【项目源码】

基于springboot实现智慧党建系统演示 Java技术 Java是由Sun公司推出的一门跨平台的面向对象的程序设计语言。因为Java 技术具有卓越的通用性、高效性、健壮的安全性和平台移植性的特点&#xff0c;而且Java是开源的&#xff0c;拥有全世界最大的开发者专业社群&#xff0c;所以…

GIT版本控制和常用命令使用介绍

GIT版本控制和常用命令使用介绍 1. 版本控制1.1 历史背景1.2 什么是版本控制1.3 常见版本控制工具1.4 版本控制的分类 2 Git介绍2.1 Git 工作流程2.2 基本概念2.3 文件的四种状态2.4 忽略文件2.5 Git命令2.5.1 查看本地git配置命令2.5.2 远程库信息查看命令2.5.3 分支交互命令2…

适用于 Mac 和 Windows 的顶级U 盘数据恢复软件

由于意外删除或设备故障而丢失 USB 驱动器中的数据始终是一件令人压力很大的事情&#xff0c;检索该信息的最佳选择是使用优质数据恢复软件。为了让事情变得更容易&#xff0c;我们已经为您完成了所有研究并测试了工具&#xff0c;并且我们列出了最好的 USB 记忆棒恢复软件&…

零基础学Linux内核:1、Linux源码组织架构

文章目录 前言一、Linux内核的特征二、Linux操作系统结构1.Linux在系统中的位置2.Linux内核的主要子系统3、Linux系统主要数据结构 三、linux内核源码组织1、下载Linux源码2、Linux版本号3、linux源码架构目录讲解 前言 这里将是我们从零开始学习Linux的第一节&#xff0c;这节…

大量索引场景下 Easysearch 和 Elasticsearch 的吞吐量差异

最近有客户在使用 Elasticsearch 搜索服务时发现集群有掉节点&#xff0c;并且有 master 收集节点信息超时的日志&#xff0c;节点的负载也很高&#xff0c;不只是 data 节点&#xff0c;master 和协调节点的 cpu 使用率都很高&#xff0c;看现象集群似乎遇到了性能瓶颈。 查看…

3、MSF使用

文章目录 一、利用ms17-010漏洞对靶机执行溢出攻击二、后渗透模块meterpreter的使用 一、利用ms17-010漏洞对靶机执行溢出攻击 分别输入以下命令&#xff0c;使用ms17_010_eternalblue模块对目标机的ms17-010漏洞进行利用&#xff1a; use exploit/windows/smb/ms17_010_eter…

iar如何全擦芯片内存

Project ->Download -> Erase memory

【理解ARM架构】 散列文件 | 重定位

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《理解ARM架构》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f3d3;引出重定位&#x1f3d3;散列文件&#x1f3d3;可读可写数据段重定位&#…

QXDM Filter使用指南

QXDM Filter使用指南 1. QXDM简介2 如何制作和导入Filter2.1 制作Filter2.1.1 制作Windows环境下Filter2.1.2 制作Linux环境下Filter 2.2 Windows环境下导入Filter 3 Filter配置3.1 注册拨号问题3.1.1 LOG Packets(OTA)3.1.2 LOG Packets3.1.3 Event Reports3.1.4 Message Pack…