C语言常用字符串函数

news2024/11/27 20:31:35

专栏:C语言
每日一句:别在乎别人的目光,自己只管一心走路。熬过去,你就能看到柳暗花明,熬过去,你就能看到雨后彩虹,熬过去,你就能看到动人风景。

字符串函数

  • 前言
  • 一、求字符串长度:strlen
    • 1.strlen的简单介绍
    • 2.strlen的模拟实现
      • 2.1利用指针-指针实现
      • 2.2利用递归实现
      • 2.3利用循环实现
  • 二、拷贝字符串strcpy和strncpy
    • 1.strcpy的介绍
      • 1.1strcpy的模拟实现
    • 2.strncpy的简单介绍
  • 三、连接字符串strcat和strncat
    • 1.strcat的简单介绍
      • 1.1strcat模拟实现
    • 2.strncat的简单介绍
  • 四、比较字符串strcmp和strncmp
    • 1.strcmp的简单介绍
      • 1.1strcmp的模拟实现
    • 2.strncmp的简单介绍
  • 五、查找字符穿strstr
    • 1.strstr的简单介绍
      • 1.1strstr的模拟实现
  • 六、错误信息strerror和perror
    • 1.strerror的简单介绍
    • 2.perror的简单介绍
  • 七、内存函数memcpy,memmove和memset
    • 1memcpy的简单介绍
      • 1.1memcpy的模拟实现
    • 2.memmove的简单介绍
      • 2.1memmove的模拟实现
    • 3.memset的简单介绍
  • 总结


前言

本文重点介绍处理字符和字符串库函数的使用和注意事项

在这里插入图片描述

文章中的函数介绍图片来源于cplusplus.com

一、求字符串长度:strlen

1.strlen的简单介绍

在这里插入图片描述
strlen函数的作用是求字符串长度

size_t strlen(const char *str);

字符串是已‘\0'作为结束标志,strlen函数返回的是在字符串中出现在'\0'之前的有效字符的个数。
参数str指向的字符串必须要以'\0'作为结束标志
注意函数的返回值为size_t,size_t是无符号的
在这里插入图片描述

2.strlen的模拟实现

在这里,给大家介绍三种实现方式

2.1利用指针-指针实现

前面介绍过,指针-指针得到的是元素之间的个数,利用这个原理,就能实现strlen

#include <stdio.h>
#include <assert.h>
int my_strlen(const char* str)
{
	assert(str);
	const char* st = str;记录str的起始地址
	while (*++str);
	return str - st;
}
int main()
{
	char str[] = "abcdef";
	int len = my_strlen(str);
	printf("%d\n", len);
	return 0;
}

在这里插入图片描述

2.2利用递归实现

如果*str不为'\0'就可以return 1 + my_strlen(++str)这样每次都可以+1,直到遇到字符串的结束标志'\0',结束递归。

#include <stdio.h>
#include <assert.h>
int my_strlen(const char* str)
{
	assert(str);
	if (*str)
	{
		return 1 + my_strlen(++str);
	}
	else
	{
		return 0;
	}
}

int main()
{
	char str[] = "abcdef";
	int len = my_strlen(str);
	printf("%d\n", len);
	return 0;
}

在这里插入图片描述

2.3利用循环实现

利用循环实现很简单,循环只要不遇到'\0',就继续循环。

#include <stdio.h>
#include <assert.h>
int my_strlen(const char* str)
{
	assert(str);
	int cnt = 0;
	while (*str)
	{
		cnt++;
		str++;
	}
	return cnt;
}

int main()
{
	char str[] = "abcdef";
	int len = my_strlen(str);
	printf("%d\n", len);
	return 0;
}

在这里插入图片描述

二、拷贝字符串strcpy和strncpy

1.strcpy的介绍

在这里插入图片描述

char* strcpy(char* destination, const char* source);

源字符串必须以'\0'为结束标志
会将源字符串中的'\0'拷贝到目标空间
目标空间必须足够大,以确保能够存放源字符串
目标空间必须可变

1.1strcpy的模拟实现

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

char* my_strcpy(char* str1, const char* arr2)
{
	assert(str1 && arr2);
	char* ret = str1;
	while (*str1++ = *arr2++);
	return ret;
}

int main()
{
	char str1[20] = "";
	const char arr2[] = "h h x x";
	my_strcpy(str1, arr2);
	printf("%s", str1);
	return 0;
}

在这里插入图片描述

注:strcpy的返回值是目标字符串的起始地址

2.strncpy的简单介绍

在这里插入图片描述

char * strncpy ( char * destination, const char * source, size_t num );

拷贝num个字符从源字符串到目标字符串中
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标字符串的后面追加0,直到够num个为止

在这里插入图片描述

三、连接字符串strcat和strncat

1.strcat的简单介绍

在这里插入图片描述

char * strcat ( char * destination, const char * source );

源字符串必须以'\0'为结束标志
目标空间必须足够大,以确保能够容纳源字符串的内容
目标空间必须可变

1.1strcat模拟实现

要模拟实现strcat,需要先找到目标字符串的尾,也就是’\0’的位置,然后让源字符串的内容连接在目标字符串后面即可

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

char* my_strcat(char* arr, const char* str)
{
	assert(arr && str);
	char* ret = arr;
	while (*++arr);
	
	while (*arr++ = *str++);
	return ret;
}

int main()
{
	char arr[20] = "hao hao";
	const char str[10] = " xue xi";
	my_strcat(arr, str);
	printf("%s", arr);
	return 0;
}

在这里插入图片描述

2.strncat的简单介绍

在这里插入图片描述

char * strncat ( char * destination, const char * source, size_t num );

如果源字符串的长度小于 num,则仅复制源字符串的结束标志之前的内容。

在这里插入图片描述

四、比较字符串strcmp和strncmp

1.strcmp的简单介绍

在这里插入图片描述

int strcmp ( const char * str1, const char * str2 );

这个strcmp是比较字符串的函数,但它并不是一串一串的比较,而是一个字符一个字符的比较。
如果str1 > str2 则返回 1
如果str1 = str2 则返回 0
如果srt1 < str2 则返回 -1

1.1strcmp的模拟实现

#include <stdio.h>
#include <assert.h>
#include <string.h>
int my_strcmp(const char* arr, const char* str)
{
	assert(arr && str);
	
	while (*arr == *str)
	{
		if (!*arr)
		{
			return 0;
		}
		arr++;
		str++;
	}

	if (*arr > *str)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}

int main()
{
	char arr[20] = "ba";
	const char str[10] = "bd";
	int cmp = my_strcmp(arr, str);
	printf("%d\n%d", cmp, strcmp(arr, str));
	return 0;
}

在这里插入图片描述

2.strncmp的简单介绍

在这里插入图片描述

int strncmp ( const char * str1, const char * str2, size_t num );

在这里,num是要比较的字符个数。

在这里插入图片描述

五、查找字符穿strstr

1.strstr的简单介绍

在这里插入图片描述

char * strstr ( const char * str1, const char * str2 );

str2 中指定的整个字符序列在 str1 中首次出现的位置,如果序列在 str1 中不存在,则返回null 指针。

1.1strstr的模拟实现

#include <stdio.h>

int n, m;

int ne[20];

char* my_strstr(char* str, char* ch)
{
	for (int i = 2, j = 0; i <= n; i++)
	{
		while (j && str[i] != str[j + 1])
		{
			j = ne[j];
		}
		if (str[i] == str[j + 1])
		{
			j++;
		}
		ne[i] = j;
	}

	for (int i = 1, j = 0; i <= m; i++)
	{
		while (j && ch[i] != str[j + 1])
		{
			j = ne[j];
		}
		if (ch[i] == str[j + 1])
		{
			j++;
		}
		if (j == n)
		{
			return ch + i + 1 - n;
			break;
		}
	}
}

int main()
{
	char str[20], ch[20];
	scanf("%d%s%d%s", &n, (str + 1), &m, (ch + 1));
	printf("%s", my_strstr(str, ch));
	return 0;
}

在这里插入图片描述

六、错误信息strerror和perror

1.strerror的简单介绍

在这里插入图片描述

char * strerror ( int errnum );

返回错误码所对应的错误信息。

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

int main()
{
	printf("%s\n", strerror(0));
	printf("%s\n", strerror(1));
	printf("%s\n", strerror(2));
	printf("%s\n", strerror(3));
	printf("%s\n", strerror(4));
	printf("%s\n", strerror(5));

	return 0;
}

在这里插入图片描述
这就是一些错误信息。

2.perror的简单介绍

在这里插入图片描述

void perror ( const char * str );

打印报错信息

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

int main()
{
	FILE* fp = fopen("Haifan.txt", "r");//这里并没有该文件
	if (fp == NULL)
	{
		perror("fp");
	}
	/*fclose(fp);
	fp = NULL;*/
	return 0;
}

在这里插入图片描述

七、内存函数memcpy,memmove和memset

1memcpy的简单介绍

在这里插入图片描述

void * memcpy ( void * destination, const void * source, size_t num );

函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
这个函数在遇到’\0’的时候并不会停下来。
如果source和destination有任何的重叠,复制的结果都是未定义的。

1.1memcpy的模拟实现

#include <stdio.h>
#include <string.h>
#include <assert.h>
void* my_memcpy(void* arr1, const void* arr2, size_t num)
{
	assert(arr1 && arr2);
	void* ret = arr1;
	while (num--)
	{
		*((char*)arr1) = *((char*)arr2);
		arr1 = (char*)arr1 + 1;
		arr2 = (char*)arr2 + 1;
	}
	return ret;
}

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[5] = { 0 };
	my_memcpy(arr1, arr2, 8);
	return 0;
 }

在这里插入图片描述

2.memmove的简单介绍

在这里插入图片描述

void * memmove ( void * destination, const void * source, size_t num );

和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。

2.1memmove的模拟实现

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

void* my_memmove(void* arr1, const void* arr2, size_t num)
{
	assert(arr1 && arr2);
	void* ret = arr1;
	if (arr1 < arr2)
	{
		while (num--)
		{
			*((char*)arr1) = *((char*)arr2);
			arr1 = (char*)arr1 + 1;
			arr2 = (char*)arr2 + 1;
		}
	}
	else
	{
		while (num--)
		{
			*((char*)arr1 + num) = *((char*)arr2 + num);
		}
	}
	return ret;
}

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	my_memmove(arr1+1, arr1, 16);
	int arr2[] = { 1,2,3,4,5 };
	memmove(arr2 + 1, arr2, 16);
	return 0;
}

在这里插入图片描述

3.memset的简单介绍

在这里插入图片描述

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

这个函数是对ptr按字节把ptr每一个字节初始化成value,一共是num个字节

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

int main()
{
	int arr[5] = { 0 };
	memset(arr, 0x3f, sizeof(arr));
	return 0;
}

在这里插入图片描述
在这里插入图片描述
这样,就能把arr的每个字节变成了0x3f

总结

以上是对常用字符串函数的总结,希望对大家有所帮助。

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

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

相关文章

UDS - 10.3 ECUReset (11) service

10.3 电子控制单元复位&#xff08;11&#xff09;服务 来自&#xff1a;ISO 14229-1-2020.pdf 10.3.1 服务说明 客户端使用ECUReset服务请求服务器重置。 此服务请求服务器基于ECUReset请求消息中嵌入的resetType参数值的内容有效地执行服务器重置。ECUReset肯定响应消息&am…

剑指 Offer 26树的子结构(相关话题:对称性递归,在线算法)

目录 开篇引言 题目描述 代码实现 题目拓展 拓展解读 一类 100. 相同的树 226. 翻转二叉树 104. 二叉树的最大深度 110. 平衡二叉树 543. 二叉树的直径 617. 合并二叉树 572. 另一个树的子树 965. 单值二叉树 二类 101. 对称二叉树 解题总结 开篇引言 力扣上…

Vue引入并使用Element-UI组件库的两种方式

前言 在开发的时候&#xff0c;虽然我们可以自己写css或者js甚至一些动画特效&#xff0c;但是也有很多开源的组件库帮我们写好了。我们只需要下载并引入即可。 vue和element-ui在开发中是比较般配的&#xff0c;也是我们开发中用的很多的&#xff0c;下面就介绍下如何在eue项…

【力扣/牛客刷题】二叉树篇

作者&#xff1a;✿✿ xxxflower. ✿✿ 博客主页&#xff1a;xxxflower的博客 专栏&#xff1a;【力扣、牛客刷题】篇 语录&#xff1a;⭐每一个不曾起舞的日子&#xff0c;都是对生命的辜负。⭐ 文章目录100. 相同的树572. 另一棵树的子树226. 翻转二叉树平衡二叉树101.对称二…

C++11之后的decltype类型指示符

C11之后的decltype类型指示符一、什么是decltype类型指示符二、typeid运算符三、使用decltype指示符四、decltype和引用五、decltype(auto)六、本章代码汇总一、什么是decltype类型指示符 有时会遇到这种情况&#xff1a;希望从表达式的类型推断出要定义的变量的类型&#xff…

深度对比学习综述

本文综合考察了对比学习近年的发展和进步, 提出一种新的面向对比学习的归类方法, 并基于提出的归类方法, 对现有对比研究成果进行系统综述, 并评述代表性方法的技术特点和区别, 系统对比分析现有对比学习方法在不同基准数据集上的性能表现。 摘要 在深度学习中, 如何利用大量、…

Linux - 目录与文件操作

目录1.操作目录1.1 目录切换1.2 浏览目录1.3 目录创建1.4 目录删除1.5 复制目录1.6 移动或重命名目录2. 操作文件2.1 查找文件2.2 查看文件信息2.3 查看文件内容2.4 创建文件2.5 文件修改-vim2.6 删除文件2.7 复制和重命名文件3. 文件或目录进行压缩或解压3.1 压缩3.2 解压1.操…

链路追踪工具之Zipkin

Zipkin是一个分布式跟踪系统&#xff0c;Zipkin的设计是基于谷歌的Google Dapper论文&#xff0c;它可以帮助收集时间数据&#xff0c;在microservice架构下&#xff0c;通过链路追踪&#xff0c;可以便捷的分析服务调用延迟问题。每个应用程序向Zipkin server端报告数据&#…

【高光谱、多光谱和全色图像融合】

HyperFusion: A Computational Approach for Hyperspectral, Multispectral, and Panchromatic Image Fusion &#xff08;超融合&#xff1a;高光谱、多光谱和全色图像融合的计算方法&#xff09; 高空间分辨率的高光谱图像&#xff08;HSI&#xff09;和多光谱图像&#xff…

链表热门面试题(二)

目录前言一、删除链表的倒数第 N 个结点二、两两交换链表中的节点三、旋转链表四、删除排序链表中的重复元素五、删除排序链表中的重复元素 II六、反转链表II七、删除链表中的节点八、奇偶链表前言 一、删除链表的倒数第 N 个结点 题目&#xff1a; 方法1&#xff1a;找到删除…

【Java多线程】创建多线程方式一

线程的创建和启动 *Java语言的JVM允许程序运行多个线程&#xff0c;它通过java.lang.Thread类来体现。 *Thread类的特性 每个线程都是通过某个特定Thread对象的run()方法来完成操作的&#xff0c;经常 把run()方法的主体称为线程体 通过该Thread对象的start()方法来启动这个…

判断两条线段是否相交

参考链接&#xff1a; 1 2 一、判断线段是否相交需要下面两步&#xff1a; &#xff08;1&#xff09;快速排斥实验 &#xff08;2&#xff09;跨立实验 二、第一步快速排斥实验 对上图两条L1,L2线段来说&#xff0c;L1 x的最大值为d端点x5&#xff0c;L2 x的最小值为a端点x…

RobotFramework环境安装和入门

环境安装1、安装python建议版本3.7&#xff0c;Robot Framework不支持python最新版。 可以通过以下地址下载https://www.python.org/ftp/python/3.7.3/python-3.7.3-amd64.exe安装过程中选择添加到环境变量。2、安装Robot Framework以及所需组件注意各个组件的版本号&#xff0…

LVGL学习笔记15 - 文本框TextArea

目录 1. Parts 2. 样式 2.1 修改背景bg 2.2 修改边界border 2.3 修改文本 2.3.1 lv_textarea_add_char 2.3.2 lv_textarea_add_text 2.3.3 lv_textarea_set_text 2.3.4 设定可输入的字符 2.3.5 删除字符 2.3.6 设定字符串最大长度 2.4 滚动条 2.4.1 滚动方向 2.4.2 …

RHCE学习笔记-133-1

RH133-01 installation 光盘引导后,在提示符下输入:linux askmethod 可以支持:local cdrom,hard drive,nfs image,ftp,http方式 cpu on x86 2个物理超线程CPU 使用smp or hugemem kernel可以支持 32个物理cpus 内存 标准x86 kernel 4G smp i686/athlon kernel 16G hugemem SMP …

创建新分支,基于某一分支创建新分支,git push --set-upstream origin

背景&#xff1a; 基于hcc1.2的开发分支拉去hcc_hotfix_1.2.0分支&#xff0c;解读&#xff1a;在仓库中基于某个分支&#xff0c;创建一个新的分支 做法&#xff08;解决&#xff09;&#xff1a; 1、第一步&#xff1a;git branch hcc_hotfix_1.2.0 2、第二步&#xff1a;g…

葡萄城邀您参与「表格技术开发者新年分享会」,共话表格技术新未来!

数据资产是企业最重要的资产之一&#xff0c;表格也是企业最普遍的数据整理手段。在数字经济时代&#xff0c;各行业飞速发展&#xff0c;拥抱数字化、进行数字化升级已成为大势所趋&#xff0c;企业对协同办公、大数据分析、表格智能化应用等领域的需求也呈爆发式增长&#xf…

GrapeCity Documents Image Viewer JavaScript Crack

GrapeCity Documents Image Viewer 是跨平台 JavaScript 图像查看器 允许用户使用我们的 JavaScript 图像查看器在您的 Web 应用程序中查看和编辑图像。采集 by Ω578867473 支持多种图像格式 适用于所有现代浏览器和框架&#xff0c;包括 Edge、Chrome、Firefox、Opera、Saf…

【UE4 第一人称射击游戏】33-创建一个小地图

上一篇&#xff1a;【UE4 第一人称射击游戏】32-添加击杀AI的提示功能&#xff08;使用到控件蓝图的动画功能&#xff09;本篇效果&#xff1a;可以看到左上角完成了小地图的制作步骤&#xff1a;打开名为“FPSHUD”的控件蓝图&#xff0c;拖入一个图像控件&#xff0c;表示迷你…

Diffusion 和Stable Diffusion的数学和工作原理详细解释

扩散模型的兴起可以被视为人工智能生成艺术领域最近取得突破的主要因素。而稳定扩散模型的发展使得我们可以通过一个文本提示轻松地创建美妙的艺术插图。所以在本文中&#xff0c;我将解释它们是如何工作的。 扩散模型 Diffusion 扩散模型的训练可以分为两部分: 正向扩散→在图…