部分字符函数与字符串函数的讲解

说到字符函数,我们见过很多,比如strlen,strcpy,strcat......

这时候就会有人说还有sizeof,其实sizeof不是库函数,他其实是操作符

 但是你听说过以下库函数么?

所以说字符串的函数有很多,我们这里介绍几个常用的;

 练习一:大写转小写/小写转大写

正常情况下,看到这题我们会联想到其可以使用对应的ASCII值进行转换 (大写对应的ASCII值比其小写小32)

代码如下:(小写转大写)

int main()
{
    char a = 'a';
    a = a - 32;
    printf("%c", a);
    return 0;
}

但是如果你知道toupper这个函数就会更方便

头文件#include<ctype.h>

#include <ctype.h>
int main()
{
    char a = 'a';
    a = toupper(a);
    printf("%c", a);
    return 0;
}

打印A 

 同样有小写转大写,那就有大写转小写

#include <ctype.h>
int main()
{
    char a = 'A';
    a = tolower(a);
    printf("%c", a);
    return 0;
}

打印a

strlen的实现

其该函数就为数到'\0',停止,不计算\0 

 首先strlen的返回值为size_t

实现代码如下 

 

size_t my_strlen(const char* string)
{
	size_t count = 0;
	while (*string++ != '\0')
	{
		count++;
	}
	return count;
}
int main()
{
	char arr[] = "abcdef";
	size_t ret=my_strlen(arr);
	printf("my_strlen=%zd\n", ret);
	printf("strlen=%zd", strlen(arr));
	return 0;
}

strstr函数的实现

strstr函数的介绍:

 

实现如下:

 

char* my_strstr(const char* string, const char* str)
{
	assert(string);
	assert(str);
	char* cur = (char*)string;
	char* s2 = (char*)str;
	if (*str=='\0')
	{
		return (char*)string;
	}
	while (*cur)
	{
		string = cur;
		s2 = str;
		while (*s2 == *string && *string && *s2)
		{
			s2++;
			string++;
		}
		if (!*s2)
			return cur;
		cur++;
	}
	return NULL;
}
int main()
{
	char arr1[] = "asdasds";
	char arr2[] = "sds";
	char* ret=my_strstr(arr1, arr2);
	printf("%s", ret);
	return 0;
}

strcpy函数的实现

strcpy函数就为字符拷贝

 函数实现如下:

#include<stdio.h>
#include<string.h>
char* my_strcpy(char* strDestination, const char* strSource)
{
	char* ret = strDestination;
	while (*strSource != '\0')
	{
		*strDestination++ = *strSource++;
	}
	*strDestination = '\0';
	return ret;
}
int main()
{
	char arr1[100] = "aaaaaaa";
	char arr2[] = "bbbb";
	my_strcpy(arr1, arr2);
	return 0;
}

strcat函数的实现

strcat就为字符串连接函数

介绍如下:

 代码实现如下:

#include<stdio.h>
#include<string.h>
char* my_strcat(char* strDestination, const char* strSource)
{
	char* ret = strDestination;
	size_t sz = strlen(strDestination);
	strDestination += sz;
	while (*strSource != '\0')
	{
		*strDestination++ = *strSource++;
	}
	*strDestination = '\0';




	return ret;
}
int main()
{
	char arr1[100] = "aaaaaaa";
	char arr2[] = "bbbb";
	my_strcat(arr1, arr2);
	return 0;
}

strcmp函数的实现

代码实现如下:

#include<stdio.h>
#include<string.h>

int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 && *str2)
	{
		if (*str1 == *str2)
		{
			str1++, str2++;
		}
		else
		{
			return *str1 - *str2;
		}
	}
	if (*str1 )
	{
		return 1;
	}
	else if(*str1==*str2&&*str1=='\0')
	{
		return 0;
	}
	else
	{
		return -1;
	}
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcedf";
	int ret=my_strcmp(arr1, arr2);
	if (ret > 0)
	{
		printf("arr1>arr2");
	}
	else if (ret == 0)
	{
		printf("arr1=arr2");
	}
	else
	{
		printf("arr1<arr2");
	}
	return 0;
}

 两种报错函数:(需要引头文件#include<errnor>

第一种:strerror

使用方法:

#include <errno.h>
#include <string.h>
#include <stdio.h>
//我们打印⼀下0~10这些错误码对应的信息 
int main()
{
    int i = 0;
    for (i = 0; i <= 10; i++) 
    {
        printf("%s\n", strerror(i));
    }
    return 0;
}

但搜索相关知识后的是该库函数返回值为

对应的所有报错信息:

第二种:perror

 perror使用的更多,其输出错误信息更方便,

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    FILE* pFile;
    pFile = fopen("unexist.ent", "r");
    if (pFile == NULL)
        perror("Error opening file unexist.ent");
    return 0;
}

输出:Error opening file unexist.ent: No such file or directory

库函数带n系列

比如说strcat与strncat:

 

区别在于:

  1. strcat 没有指定追加的长度限制,会一直追加直到遇到第一个空字符('\0')为止,因此需要确保目标字符串有足够的空间来容纳被追加的字符串。

    例如:strcat(dest, src);

  2. strncat 则允许指定最多追加的字符数,避免了可能的缓冲区溢出问题。第三个参数指定要追加的最大字符数。

    例如:strncat(dest, src, n);

因此,如果你能够确定目标字符串有足够的空间来容纳被追加的字符串,可以使用 strcat;如果想要避免潜在的缓冲区溢出问题,可以使用 strncat 并指定追加的最大字符数。

 所以带n的可以避免很多问题;

strncat

其代码接收时利用char* 按照字节单位进行函数内的操作,返回值同样为char* 

代码实现如下:

 

char* my_strncat(char* str1, const char* str2)
{
	char* ret = str1;//保存头
	while (*str1)//一直到\0
	{
		str1++;
	}
	while (*str2)
	{
		*str1 = *(char*)str2;
		str1++;
		str2++;
	}


	//添加\0
	*str1='\0';
	return ret;
}
int main()
{
	char arr1[150] = "asdfg";
	char arr2[] = "sss";
	char* ret=my_strncat(arr1,arr2);
	printf("%s", ret);
	return 0;
}

代码其实与strcat差不多

strncpy

实现代码如下:

 

#include<stdio.h>
#include<string.h>
#include<assert.h>


char* my_strncpy(char* str1, const char* str2, int n)
{
	assert(str1 && str2);
	int i = 0;
	for (i = 0; str2 != '\0' && i < n; i++)
	{
		str1[i] = str2[i];
	}
	if (i < n)//符合库函数给的标准
	{
		str1[i] = '\0';
	}
	return str1;
}
int main()
{
	char arr1[150] = "asdfgh";
	char arr2[] = "asd";
	char* ret=my_strncpy(arr1,arr2,3);
	//char* ret=strncpy(arr1,arr2,3);
	printf("%s", ret);
	return 0;
}

mem系列

 

memcpy和strcpy是C语言中常用的字符串处理函数,它们的区别主要在于功能和用法上:

  1. strcpy:用于将一个字符串复制到另一个字符串中,直到遇到空字符'\0'为止。其函数原型为:

char *strcpy(char *dest, const char *src);

其中,dest表示目标字符串的指针,src表示源字符串的指针。strcpy会复制整个源字符串(包括'\0'结束符)到目标字符串中,如果源字符串比目标字符串长,可能会导致缓冲区溢出。

  1. memcpy:用于将一段内存区域的数据复制到另一段内存区域中,可以复制任意类型的数据,不仅限于字符串。其函数原型为:

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

其中,dest和src分别表示目标内存区域和源内存区域的指针,n表示要复制的字节数。memcpy只关心字节数,不会在遇到'\0'时停止复制,因此更适合用于处理二进制数据或非字符串数据的复制操作。

总的来说,strcpy适用于字符串的复制操作,而memcpy适用于一般的内存数据复制操作。在使用时需要根据具体的需求选择合适的函数。

 其需要注意的是接收使用的void*类型的指针

void* 类型指针不能进行解引用需要进行强制类型转化

代码实现如下:

 

void* my_memcpy(void *dest,void* str,size_t count)
{
	assert(dest);
	assert(str);
	void* ret = dest;
	while (count--)
	{
		*(char*)dest = *(char*)str;
		dest = (char*)dest+1;
		str = (char*)str+1;
	}


	return ret;
}
int main()
{
	char arr1[150] = "iiiiiiiii";
	char arr2[] = "ssssss";
	my_memcpy(arr1, arr2,5);
	printf("%s", arr1);
	return 0;
}

但是如果我们传参为arr1+2与arr1呢?,那么这个代码就会出现问题,这时候就需要利用函数memmove:

实现如下:

void* my_memmove(void* dest,const void* str, size_t count)
{
	assert(dest);
	assert(str);
	void* ret = dest;
	char* s1 = (char*)dest;
	char* s2 = (char*)str;
	if (dest < str)//从前 -》 后
	{
		while (count--)
		{
			*s1++ = *s2++;
		}
	}
	else//后 -》 前
	{
		s1 = s1 + count;
		s2 = s2 + count;
		while (count--)
		{
			*s1-- = *s2--;
		}
	}
	return ret;
}


int main()
{
	char arr1[150] = "iissssiii";
	char arr2[] = "ssssss";
	my_memmove(arr1, arr1+2,5);
	printf("%s", arr1);
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Photomator:专业级照片编辑的利器

Photomator软件是一款功能强大的照片编辑和管理工具&#xff0c;专注于提供高质量的图像处理体验和便捷的工作流程。以下是关于Photomator软件功能特色的详细介绍&#xff1a; 高级颜色调整功能&#xff1a;Photomator提供了大量前沿的颜色调整工具&#xff0c;包括AI驱动的自…

【数据结构】单链表详解

前言 为了解决顺序表存在的一些问题&#xff0c;我们引入了单链表~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 顺序表存在一定的问题 与顺序表的对比 认识链表 链表结构 打印节点 头文件SList.h 源…

opencv安装(C++)并配置vs

准备工作&#xff1a; 1.opencv安装包(此教程使用4.9) 2.visual studio(此教程使用vs2019) opencv安装&#xff1a; 1、下载opencv&#xff1a; 1.1 官网下载&#xff1a;Releases - OpenCV 1.2 百度网盘&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1NpEoFjbbyQJtFD…

HANA VIEW 用 ABAP 创建CDS VIEW,在生成ODATA

这里我们做ADT来创建 场景介绍:把hana中的一个底表,创建成ABAP的 CDS VIEW ,在把CDS VIEW 生成 OData 服务。 一、创建CDS Table Function 红框内根据自身情况填写 选择 Define Table Function with Parameters 创建 Data Definition 完整代码,定义 结构 , 也可以定义参…

基于springboot+vue的火锅店管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

javaSwing推箱子游戏

一、简介 策略性游戏可以锻炼人的思维能力还能缓解人的压力&#xff0c;使人们暂时忘却生活当中的烦恼&#xff0c;增强人们的逻辑思维能力&#xff0c;游戏的艺术美也吸引着越来越多的玩家和厂商&#xff0c;寓教于乐&#xff0c;在放松人们心情的同时还可以活跃双手。在人类…

支小蜜校园防欺凌系统怎么识别到学生打架?

校园欺凌行为已经成为一个全球性的社会问题&#xff0c;它不仅影响了学生的身心健康&#xff0c;也破坏了校园的和谐氛围。为了有效预防和应对这一现象&#xff0c;许多学校开始引入校园防欺凌系统。那么&#xff0c;校园防欺凌系统是如何识别到学生打架的呢&#xff1f;本文将…

腾讯云轻量2核2G3M服务器优惠价61元一年性能测评

阿里云轻量应用服务器2核2G3M带宽优惠价一年61元&#xff0c;100%CPU性能&#xff0c;3M带宽下载速度384KB/秒&#xff0c;40GB SSD系统盘&#xff0c;月流量200GB&#xff0c;折合每天6.6GB流量&#xff0c;超出月流量包的流量按照0.8元每GB的价格支付流量费&#xff0c;地域节…

网络——入门基础

目录 协议 网络协议 OSI七层模型 网络传输基本流程 网络传输流程图 局域网通信 数据包的封装和解包 广域网通信 网络地址管理 IP地址 MAC地址 协议 关于什么是局域网&#xff0c;什么是广域网&#xff0c;我这里就不过多赘述了&#xff0c;我们直接来谈一下什么…

数据结构:10、排序

本文将会介绍8种排序&#xff0c;并在文章末附上代码 一、排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;…

二、阅读器的开发(初始)-- 1、阅读器简介及开发准备工作

1、阅读器工作原理及开发流程 1.1阅读器工作原理简介 电子书&#xff08;有txt、pdf、epub、mobi等格式&#xff09;->解析&#xff08;书名、作者、目录、封面、章节等&#xff09;->&#xff08;通过阅读器引擎&#xff09;渲染 -> 功能&#xff08;字号、背景色、…

学生信息管理系统--修改信息(非常详细的修改,更新,撤销,删除逻辑)

目录 概述修改包括的操作修改在每个模块中的应用 详解修改与更新取消删除 特殊概念数据集游标 总结 概述 学生信息管理系统&#xff0c;功能相对简单且代码重复性高&#xff0c;应该采用复用的思想来减少代码的冗余和提高代码的可维护性。然而&#xff0c;对于基础入门项目来说…

SQL数据库和事务管理器在工业生产中的应用

本文介绍了关系数据库在工业生产中的应用以及如何使用事务管理器将生产参数下载到PLC&#xff0c;以简化OT/IT融合过程。 一 什么是配方&#xff08;Recipe&#xff09; 我们以一家汽车零件制造商的应用举例&#xff0c;该企业专业从事汽车轮毂生产制造。假设该轮毂的型号是“…

echart trigger 为 axis 的时候不显示 tooltip 解决办法

echart trigger 为 axis 的时候不显示 tooltip 解决办法 在项目 vitetsvue3 中使用 echart 显示了一个曲线图&#xff1a; 但当把图表的 trigger 设置成 axis 的时候&#xff0c;鼠标扫过并不显示具体的数值&#xff0c;如上图所示。 但 trigger item 的时候是正常的。 解决…

浏览器工作原理与实践--仅仅打开了1个页面,为什么有4个进程?

无论你是想要设计高性能Web应用&#xff0c;还是要优化现有的Web应用&#xff0c;你都需要了解浏览器中的网络流程、页面渲染过程&#xff0c;JavaScript执行流程&#xff0c;以及Web安全理论&#xff0c;而这些功能是分散在浏览器的各个功能组件中的&#xff0c;比较多、比较散…

idea创建maven-archetype-quickstart框架无法显示src/目录

一、配置好idea中Maven目录 1、不使用idea自带Maven&#xff0c; 2、配置好Maven环境变量M2_HOME 3、修改maven中 setting.xml文件 <?xml version"1.0" encoding"UTF-8"?><settings xmlns"http://maven.apache.org/SETTINGS/1.2.0"…

【C语言】—— 指针三 : 参透数组传参的本质

【C语言】—— 指针三 &#xff1a; 参透数组传参的本质 一、数组名的理解二、使用指针访问数组2.1、指针访问数组2.2、[ ] 的深入理解2.3、数组与指针的区别 三、一维数组的传参本质四、数组指针变量4.1、数组指针变量是什么4.2、 数组指针的初始化 五、二维数组传参的本质 一…

【LabVIEW FPGA入门】插值、输出线性波形

概述 NI 的可重配置 I/O (RIO) 硬件使开发人员能够创建自定义硬件&#xff0c;以在坚固耐用、高性能和模块化架构中执行许多任务&#xff0c;而无需了解低级 EDA 工具或硬件设计。使用 RIO 硬件轻松实现的此类任务之一是模拟波形生成。本教程介绍了使用 CompactRIO 硬件和 LabV…

计算机网络:计算机网络概述

计算机网络&#xff1a;计算机网络概述 因特网概述网络&#xff0c;互连网&#xff0c;因特网因特网发展的三个阶段因特网的标准化工作因特网组成 计算机网络的定义计算机网络的分类按使用者分类按传输介质分类按网络的覆盖范围分类按拓扑结构分类 因特网概述 网络&#xff0c…

投简历没回复?9位DBA公众号集结,快上车!

&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&#x1f61c;&#x1f61c; 中国DBA联盟(ACD…