C语言——二周目——字符串与内存库函数总结

news2024/11/15 10:26:33

目录

一、字符串函数

1.求字符串长度——strlen

模拟实现

2.字符串拷贝函数——strcpy/strncpy

3.字符串追加函数——strcat/strncat

4.字符串比较函数——strcmp/strncmp

5.字符串查找函数——strstr

6.字符串分割函数——strtok

二、内存操作函数

1.内存拷贝函数——memcpy

2.内存移动函数——memmove

3.内存比较函数——memcmp

4.内存设置函数——memset

 ​编辑



一、字符串函数

1.求字符串长度——strlen

1)字符串'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前出现的字符个数(不包含'\0')。

2)当字符串不以'\0'结尾时,将输出一个随机值(系统越界访问直到找到'\0'字符为止)。

3)size_of 是无符号整型。所以两个strlen的结果直接相减得到的也是无符号整型,所以即使是负数也被认为是正数。

模拟实现

size_t my_strlen(char* s)
{
	size_t ret = 0;
	while (s[ret++] != '\0');
	return ret - 1;
}				   
				   
int main()	   
{				   
	char s[] = "hello world!";
	printf("库函数:%zd\n", strlen(s));
	printf("模拟实现:%zd\n",my_strlen(s));
	return 0;
}

2.字符串拷贝函数——strcpy/strncpy

对于strcpy:

1)源字符串必须以'\0'结束,strcpy执行到'\0'字符停止。

2)源字符串中的'\0'也会被拷贝到目标空间。

3)目标空间应该足够大以存放源字符串。

4)目标空间必须可变。(避免向dest传字符串常量参数)

char* my_strcpy(char* dest, char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*(dest++) = *(src++));
	return ret;
}

int main()
{
	char arr1[] = "Hello world!";
	char arr2[20] = "";
	printf("arr1:%s\narr2:%s\n",arr1,my_strcpy(arr2,arr1));
	return 0;
}

对于strncpy:

1)多了一个num参数,表示要拷贝的字节个数。

2)如果源字符串的长度小于num,则拷贝完源字符串后,在后面追加'\0'直到num个。

3)需要注意strncpy在拷贝结束时不会自动补‘\0’。

char* my_strncpy(char* dest, const char* src, size_t num)
{
	assert(dest && src);

	char* ret = dest;
	while (num--)
	{
		if (*src == '\0')
		{
			*(dest++) = '\0';
		}
		else
		{
			*(dest++) = *(src++);
		}
	}
	
	return ret;
}

3.字符串追加函数——strcat/strncat

对于strcat:

1)源字符串必须以'\0'结束,strcat从目标字符串的'\0'开始,执行到源字符串的'\0'字符停止。

2)源字符串中的'\0'也会被追加到目标空间。

3)目标空间应该足够大以容纳追加的源字符串。

4)目标空间必须可变。

5)不可以给自己追加。给自己追加会使得src和dest两个字符串同时改变,找不到'\0'而死循环。
 

char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);

	char* ret = dest;
	while (*dest != '\0')
		dest++;
	while (*dest++ = *src++);
	return ret;
}

对于strncat:

1)追加结束后会自动补一个'\0'。

2)当指定追加字节大于源字符串总长度时,追加到末尾‘\0’处结束。

char* my_strncat(char* dest, char* src, size_t num)
{
	assert(dest && src);
	
	char* ret = dest;
	while (*dest != '\0')
	{
		dest++;
	}
	while (num--)
	{
		if (!(*dest++ = *src++))
			return ret;
	}
	if (num == 0);
	{
		*dest = '\0';
	}
	return ret;
}

4.字符串比较函数——strcmp/strncmp

对于strcmp:

比较两个字符串是否相等(首字母)。

若str1>str2,返回大于0的数;若str1<str2,返回小于0的数;若str1=str2,返回0 。

int my_strcmp(const char* e1, const char* e2)
{
	assert(e1 && e2);

	while (*e1 == *e2)
	{
		if (*e1 == '\0')
			return 0;
		else
		{
			e1++;
			e2++;
		}
	}
	return *e1 - *e2;
}

对于strncmp:

比较两个字符串是否相等(首字母),比较num个字符。

若str1>str2,返回大于0的数;若str1<str2,返回小于0的数;若str1=str2,返回0 。

5.字符串查找函数——strstr

        查找一个字符串中是否存在指定的子字符串。若存在,返回第一个找到的子字符串在原字符串中的首字符位置;若不存在,则返回一个空指针。

char* my_strstr(const char* s1, const char* s2)
{
	assert(s1 && s2);

	char* ret = s1;
	while (*s1 != '\0')
	{
		int cur = 0;
		while (*s1 != *s2)
		{
			s1++;
		}
		while (s1[cur] == s2[cur])
		{
			cur++;
			if (s2[cur] == '\0')
				return s1;	
		}
		s1++;
	}
	return NULL;
}

6.字符串分割函数——strtok

1)后一个参数是个字符串,内容为将要用作分隔符的字符的集合。

2)第一个参数为指定的字符串(可包含0个或多个分隔符)。

3)strtok函数找到str的下一个分隔符后,将其用'\0'结尾,返回一个指向这个'\0'前字符串首字符的指针。(strtok函数会改变被操作的字符串)

4)对于一个字符串第一次调用strtok函数,第一个参数不为NULL,函数找到字符串中第一个标记,并保存。

5)对同一个字符串再次调用strtok函数,第一个参数为NULL,函数将从保存的上次标记处开始,查找下一个标记。

6)如果字符串中不存在更多的标记,则返回NULL指针。

int main()
{
    char arr[] = "lang1940629384@mail.nwpu.edu.cn";
    char* p = "@.";
 
    char buf[1024] = {0};
    strcpy(buf,arr);
    
    char* ret = NULL;
    
    for(ret = strtok(arr,p);ret != NULL;ret = strtok(NULL,p))
    {
        printf("%s\n",ret);
    }
    return 0;
}
 
//output:
//    lang1940629384
//    mail
//    nwpu
//    edu
//    cn

二、内存操作函数

1.内存拷贝函数——memcpy

1)函数从source的位置开始向后复制num个字节的数据到destination指向的内存位置。

2)函数不会因为遇到'\0'而停止,而是一直执行直到操作过num个字节的数据为止。

3)如果source与destination有拷贝过程中不应该有重叠。

void* my_memcpy(void* dest, const void* src, size_t size)
{
	assert(dest && src);

	while (size--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
}

2.内存移动函数——memmove

拷贝内存中储存的数据,功能与memcpy相同。二者区别在于memmove考虑重叠对象的问题,而memcpy不考虑该情况。

void* my_memmove(void* dest, const char* src, size_t size)
{
	assert(dest && src);
	
	if (dest > src)
	{
		dest = (char*)dest + size - 1;
		src = (char*)src + size - 1;
		while (size--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest - 1;
			src = (char*)src - 1;
		}
	}
	else
	{
		while (size--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
}

3.内存比较函数——memcmp

用于比较从ptr1和ptr2指针开始的num个字节。若小于返回负数,大于返回正数,相等返回0 。

4.内存设置函数——memset

 

设置指定内存空间内为指定字符。即将ptr指针指向的位置开始num个字节内容变为指定值value。 

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

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

相关文章

每日leetcode_2441

Leetcode每日一题_2441 记录自己的成长&#xff0c;加油。 题目 解题 class Solution {public int findMaxK(int[] nums) {int k -1;Set<Integer> set new HashSet<Integer>();for (int x : nums) {set.add(x);}for (int x : nums) {if (set.contains(-x)) {k …

linux 分区 添加 挂载centos挂载 Microsoft basic

​ 一 背景 es 忽然写不进去了 报错 TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark查看发现 磁盘已经满了 2T 的磁盘已经使用完了 ​ fdisk -l 查看原来磁盘有64000G 有64T 装机的人只分区了2T,白白浪费58T. 二 添加分区 利用剩余的空间 1添加分区 添…

光伏发电站并网新能源消纳数据采集监控监测方案

全市分布式光伏大数据平台&#xff0c;上报省级能源大数据中心。光伏电站实时运行数据&#xff1a;包括逆变器运行数据和状态、样板逆变器实时出力曲线&#xff0c;光伏电站并网点实际功率&#xff0c;气象监测数据&#xff0c;数据实时采集&#xff0c;采集频率根据光伏电站实…

Pytorch之EfficientNetV2图像分类

文章目录 前言一、EfficientNet V21. 网络简介2. EfficientNetV1弊端&#x1f947;训练图像的尺寸很大时&#xff0c;训练速度非常慢&#x1f948;在网络浅层中使用Depthwise convolutions速度会很慢&#x1f949;同等的放大每个stage是次优的 3.NAS Search4. Progressive Lear…

【C++】Vector -- 详解

一、vector的介绍及使用 1、vector的介绍 https://cplusplus.com/reference/vector/vector/ vector 是表示可变大小数组的序列容器。 就像数组一样&#xff0c;vector 也采用的连续存储空间来存储元素。也就是意味着可以采用下标对 vector 的元素进行访问&#xff0c;和数组一…

华天OA任意文件上传漏洞 复现

文章目录 华天OA任意文件上传漏洞 复现0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 华天OA任意文件上传漏洞 复现 0x01 前言 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播…

整理笔记——推挽输出、开漏输出

在使用MCU时&#xff0c;常看到配置IO口为推挽输出、开漏输出&#xff0c;以STM32为例&#xff0c;IO口有一下集中模式&#xff0c;单片机的内部电路简化图如下&#xff1a; 1.推挽输出 2.开漏输出 3.复用推挽输出 4.复用开漏输出 一、推挽输出 推挽电路的示意图&#xff1a; …

Linux系统常用指令篇---(完)

Linux系统常用指令篇—(完) 1.时间相关的指令 date显示 date 指定格式显示时间&#xff1a; date %Y:%m:%d date 用法&#xff1a; date [OPTION]… [FORMAT] 1.在显示方面&#xff0c;使用者可以设定欲显示的格式&#xff0c;格式设定为一个加号后接数个标记&#xff0c;其…

【AI】深度学习——前馈神经网络——全连接前馈神经网络

文章目录 1.1 全连接前馈神经网络1.1.1 符号说明超参数参数活性值 1.1.2 信息传播公式通用近似定理 1.1.3 神经网络与机器学习结合二分类问题多分类问题 1.1.4 参数学习矩阵求导链式法则更为高效的参数学习反向传播算法目标计算 ∂ z ( l ) ∂ w i j ( l ) \frac{\partial z^{…

ubuntu安装Chrome浏览器

切换暂存路径(具体根据自己) cd 下载/下载Chrome安装包 wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb安装Chrome浏览器 sudo dpkg -i google-chrome-stable_current_amd64.deb更新包 非必须 sudo apt-get -f install 启动Chrome浏览器 …

FLIP动画做拖拽排序效果

先来看效果 index.html文件 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content&quo…

系统架构设计:1论软件系统建模方法及其应用(试读)

目录 一 软件系统建模方法 1结构化建模 2信息工程建模 3面向对象建模 4功能分解法 5基于构件的开发方法 一 软件系统建模方法 软件建模体现了软件设计的思想&#xff0c;是连接需求和实现的桥梁&#xff0c;用于指导软件的具体实现。软件模型不是软件系统的完备表示&…

【Pytorch模型可视化】Netron可视化pytorch框架下的模型

文章目录 1. 下载Netron2. pth/pt转onnx3. 可视化实现 1. 下载Netron github 下载链接&#xff1a;https://github.com/lutzroeder/Netron 打开上面网页&#xff0c;显示界面中的 Windows&#xff1a;Download 处点击直接下载 .exe 可执行文件。 如果觉得下载麻烦&#xff0c…

常见的通用型项目管理软件推荐

常用项目管理软件有很多。按适合的行业来分&#xff0c;有针对各种垂直行业定制的&#xff0c;也有全行业通用的。从厂商来看&#xff0c;有国外研发的&#xff0c;也有国内厂商的&#xff0c;体现在软件的设计思路不同&#xff0c;上手的手感也很不一样。从体量来看&#xff0…

dom-to-image库是如何将html转换成图片的

dom-to-image库可以帮你把dom节点转换为图片&#xff0c;它的核心原理很简单&#xff0c;就是利用svg的foreignObject标签能嵌入html的特性&#xff0c;然后通过img标签加载svg&#xff0c;最后再通过canvas绘制img实现导出&#xff0c;好了&#xff0c;本文到此结束。 另一个…

SpringBoot之使用Redis和注解实现接口幂等性

文章目录 1 接口幂等性1.1 概念1.2 实现思路1.3 代码实现1.3.1 pom1.3.2 JedisUtil1.3.3 自定义注解ApiIdempotent1.3.4 ApiIdempotentInterceptor拦截器1.3.5 TokenServiceImpl1.3.6 TestApplication 1.4 测试验证1.4.1 获取token的控制器TokenController1.4.2 TestController…

[ICCV-23] DeformToon3D: Deformable Neural Radiance Fields for 3D Toonification

pdf | code 将3D人脸风格化问题拆分为几何风格化与纹理风格化。提出StyleField&#xff0c;学习以风格/ID为控制信号的几何形变残差&#xff0c;实现几何风格化。通过对超分网络引入AdaIN&#xff0c;实现纹理风格化。由于没有修改3D GAN空间&#xff0c;因此可以便捷实现Edit…

Matlab导入log(或txt)文件,提取数据或其他信息

导入log&#xff08;或txt)文件 先上代码&#xff1a; clc; clear; %数据导入 file1fullfile(文件路径, test1.log); % 导入文件test1.log f1fopen(file1); dt1textscan(f1,%s); %采用textscan 读取数据 %得到的dt1是元胞数组格式比如&#xff1a;有如下内容文件 导入…

java案例20:库存管理系统

思路&#xff1a; 像商场、超市这样的地方&#xff0c;都需要有自己的库房&#xff0c;并且库房商品的库存变化有专人记录&#xff0c;这样才能保证商城和超市正常运转编写程序&#xff0c;模拟库存管理系统 该系统主要包括系统首页、商品入库、商品显示和删除商品功能 每个功…

spark-03

RDD是抽象概念&#xff0c;分区是物理概念