11-25碎片小知识

news2024/11/30 7:49:03

一.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;
	else
		return 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;
		else
			cur++;
	}
	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;
		else
			cur++;
	}
	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.coloradmin.cn/o/1253569.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Cache框架,实现了基于注解的缓存功能。

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ Spring Cache框架 简介Spring Cache 环境准备S…

RedLock底层源码分析

RedLock底层源码分析 一、Redlock红锁算法 https://redis.io/docs/manual/patterns/distributed-locks/官网说明 1、为什么要学习这个&#xff1f;怎么产生的&#xff1f; ​ 一个很直接的问题&#xff0c;当我使用redis锁的那台机器挂了&#xff0c;出现了单点故障了&#…

源 “MySQL 8.0 Community Server“ 的 GPG 密钥已安装,但是不适用于此软件包。请检查源的公钥 URL 是否配置正确。

源 “MySQL 8.0 Community Server“ 的 GPG 密钥已安装&#xff0c;但是不适用于此软件包。请检查源的公钥 URL 是否配置正确。yum install mysql-server --nogpgcheck

【深度学习】因果推断与机器学习的高级实践 | 数学建模

文章目录 因果推断因果推断的前世今生&#xff08;1&#xff09;潜在结果框架&#xff08;Potential Outcome Framework&#xff09;&#xff08;2&#xff09;结构因果模型&#xff08;Structual Causal Model&#xff0c;SCM&#xff09; 身处人工智能爆发式增长时代的机器学…

VCenter6.7 Web访问提示503 Service Unavailable

PS&#xff1a;本文分享VMware Vcenter在web登录的时候报错&#xff1a;503 Service Unavailable&#xff0c;对于6.7.x版本比较适用&#xff0c;其他版本需自行测试。 简单来讲就是需要重启一下vsphre-client服务&#xff0c;如重启该服务仍无法解决&#xff0c;可以尝试重启一…

Windows系统管理之备份与恢复

本章目录&#xff1a; 一. 本章须知&#xff1a; 前置条件 需要创建一个新的磁盘 前置条件2 给新添加的磁盘分盘 二. 了解开启并学会使用Windows sever backup 如何使用备份与恢复“备份计划”“一次性备份”“恢复” 最后是用命令行“一次性备份命令 ”完成一次备份 话不多说 …

MyBatis框架_01

Web后端开发_03 MyBatis框架 什么是MyBatis? MyBatis是一款优秀的持久层框架&#xff0c;用于简化JDBC的开发。MyBatis本是 Apache的一个开源项目iBatis&#xff0c;2010年这个项目由apache迁移到了google code&#xff0c;并且改名为MyBatis 。2013年11月迁移到Github。官网…

MSI Center,XBox从任务栏取消固定

1&#xff0c;设置查看方式中隐藏项目可见 2&#xff0c;进入文件夹&#xff1a;C:\Users\Default\AppData\Local\Microsoft\Windows\Shell 找到下面这两个文件夹&#xff1a; 3&#xff0c;修改文件名或者删除这两个文件即可

从0开始学习JavaScript--JavaScript函数返回值

在JavaScript中&#xff0c;函数是一种强大的工具&#xff0c;不仅能够执行一系列操作&#xff0c;还可以返回值。理解函数返回值的概念对于编写清晰、灵活的代码至关重要。本文将深入探讨JavaScript函数返回值的各种方面&#xff0c;包括基本返回值、多返回值、异步函数的返回…

NoSQL基础知识小结

NoSQL 基础知识 什么是 NoSQL? NoSQL&#xff08;Not Only SQL 的缩写&#xff09;泛指非关系型的数据库&#xff0c;主要针对的是键值、文档以及图形类型数据存储。 NoSQL 数据库天生支持分布式&#xff0c;数据冗余和数据分片等特性&#xff0c;旨在提供可扩展的高可用高…

超越噪音,让音乐重获新生:iZotope RX 10音频降噪修复软件

在音乐制作或者音频处理的过程中&#xff0c;噪音往往是一个让人头痛的问题。无论是环境噪音&#xff0c;还是设备产生的噪音&#xff0c;都会对音频质量产生重大影响。而现在&#xff0c;我们有了iZotope RX 10&#xff0c;这款专业的音频降噪修复软件&#xff0c;可以将你从噪…

HCIA题目解析(1)

1、【多选题】关于动态 MAC 地址表说法正确的是&#xff1f; A、通过报文中的源MAC地址学习获得的动态MAC表项会老化 B、通过查看指定动态MAC地址表项的个数&#xff0c;可以获取接口下通信的用户数 C、在设备重启后&#xff0c;之前的动态表项会丢失 D、在设备重启后&…

leetCode 100. 相同的树 和 leetCode 101. 对称二叉树 和 110. 平衡二叉树 和 199. 二叉树的右视图

1.leetCode 100. 相同的树 C代码&#xff1a; class Solution { public:bool isSameTree(TreeNode* p, TreeNode* q) {if(p nullptr || q nullptr) return pq;return p->val q->val && isSameTree(p->left,q->left) && isSameTree(p->righ…

2 时间序列预测入门:GRU

0 论文地址 GRU 原论文&#xff1a;https://arxiv.org/pdf/1406.1078v3.pdf GRU&#xff08;Gate Recurrent Unit&#xff09;是循环神经网络&#xff08;RNN&#xff09;的一种&#xff0c;可以解决RNN中不能长期记忆和反向传播中的梯度等问题&#xff0c;与LSTM的作用类似&a…

基于卷积优化算法优化概率神经网络PNN的分类预测 - 附代码

基于卷积优化算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于卷积优化算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于卷积优化优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

深度学习之基于YoloV3杂草识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 深度学习在图像识别领域已经取得了显著的成果&#xff0c;其中基于YOLO&#xff08;You Only Look Once&#xff09…

1.1 半加器

输入1输入2结果进位0000101001101101 半加器: 实现1位的加法 根据结果可知输入1与输入2相加结果 -> 符合 异或门进位 -> 符合 与门最终要么有结果要么有进位,不存在即有结果也有进位 异或门的实现也可以由基本的3个 “与或非” 门实现 与:& , 或:| , 非:! 用这3个…

2. 寄存器

锁存器,用于存储1位的电路 只有当 可写位(write enable)开启,才会把输入写到输出,同时保存输出 使用锁存器 带时钟的锁存器 带时钟带可写控制的完整版锁存器 下面的时钟使用按钮来代替, 只有按钮为1时,相连的电路才工作时钟的作用在于协同所有电路共同工作,也是一切电路自动化…

android shape绘制半圆

<?xml version"1.0" encoding"utf-8"?><shape xmlns:android"http://schemas.android.com/apk/res/android"android:shape"rectangle"><sizeandroid:width"20dp"android:height"10dp" /><…

山西电力市场日前价格预测【2023-11-26】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-26&#xff09;山西电力市场全天平均日前电价为144.57元/MWh。其中&#xff0c;最高日前电价为341.24元/MWh&#xff0c;预计出现在08:00。最低日前电价为0.00元/MWh&#xff0c;预计出…