进阶C语言——字符串和内存函数

news2024/11/24 16:39:04

今天我们学点库函数

字符函数和字符串函数

求字符串长度函数->strlen

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
strlen需要的头文件是string.h ,那它的作用是什么呢??
他是来求字符串长度的,统计的是’\0’前的字符串长度

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdef";
	size_t len = strlen(arr1);
	printf("%d", len);
	return 0;
}

size_t是无符号的意思

学会了strlen函数怎么使用,那我们现在模拟实现一下strlen

之前讲过三种方式来实现,大家是否还记得呢?分别是计数的方式,函数递归的方式,还有我们的指针

计数器的方式

#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* arr)
{
	assert(*arr);
	int count = 0;
	while (*arr++)
	{
		count++;
	}
	return count;
}
int main()
{
	char arr[] = "abcdef";
	size_t len = my_strlen(arr);
	printf("%d\n", len);
	return 0;
}

函数递归

#include<stdio.h>

size_t my_strlen(const char* arr)
{
	
	if (*arr != 0)
	{
		return 1 + my_strlen(arr + 1);
	}
	
}
int main()
{
	char arr[] = "abcdef";
	size_t len = my_strlen(arr);
	printf("%d\n", len);
	return 0;
}

指针运算

#include<stdio.h>
int my_strlen(char* arr)
{
	char* str = arr;
	while (*arr)
	{
		arr++;
	}
	return arr - str;
}
int main()
{
	char arr[] = "abcdef";
	int len = my_strlen(arr);
	printf("%d\n", len);
	return 0;
}

strcpy函数
在这里插入图片描述
strcpy的作用是把我们的后面字符拷贝到前面字符,但是我们也有相应的前提

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

那我们用代码来看看效果吧

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "xxx";
	printf("%s", strcpy(arr1, arr2));
	return 0;
}

在这里插入图片描述
我们可以看到其实我们在拷贝的时候,把’\0‘也拷贝进去,下面再给大家看一个特殊例子
在这里插入图片描述
观察到我们拷贝的时候,是\0之前,这也符合我们上面的规定
现在我们写一个函数来模拟实现这个效果吧

#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
	assert(*dest && *src);
	char* ret = dest;
		while (*dest++ = *src++)
		{
			;
		}
		return dest;
}
int main()
{
	char arr1[] = "xxxxx";
	char arr2[] = "abcd";
	char* arr3 = my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

我们只是模拟实现,不可能实现vs中的strcpy的功能,比如上面我们的代码缺陷就是不能自己copy自己,会存在覆盖现象,导致不能达到我们想要的效果
stract
在这里插入图片描述
源字符串必须以 ‘\0’ 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。

这是一个追加的字符串,比如我们要想在arr1字符串后面追加一个hello,这样就可以用我们的strcat

我们用代码看一下它该怎么使用

#include<stdio.h>
#include<string.h>
int main()
{

	char arr1[] = "hello";
	char arr2[] = " CSDN";
	char* ret = strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

那我们接下来就是模拟实现函数

#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest, const char* str)
{
	assert(*dest && *str);
	char* ret = dest;
	while (*++dest)
	{
		;
	}
	while (*dest++ = *str++ )
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[] = "hello";
	char arr2[] = " CSDN";
	char* ret = my_strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

strcmp
这是一个比较字符串的函数,但是大家可不要误以为是比较长度的,它的作用是比较ASCII的,一个字符一个字符进行比较
在这里插入图片描述
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
所以我们的strcmp函数的返回值应该是整型
下面我们就写个代码看看效果吧

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcde";
	char arr2[] = "abcdq";
	int len = strcmp(arr1, arr2);
	printf("%d", len);
	return 0;
}

那我们也来模拟实现一下strcmp

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

}
int main()
{
	char arr1[] = "abcde";
	char arr2[] = "abcdq";
	int len = my_strcmp(arr1, arr2);
	printf("%d", len);
	return 0;
}

strstr
在这里插入图片描述

#include <stdio.h>
#include <string.h>
int main()
{
	char str[] = "This is a simple string";
	char* pch;
	pch = strstr(str, "simple");
	if (pch == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("找到了\n");
	}
	
	return 0;
}

模拟实现

#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* dest, const char* str)
{
	assert(dest && str);
	char* s1 = dest;
	char* s2 = str;
	char* cul = dest;
	while (*cul)
	{
		s1 = cul;
		s2 = str;
		while (*s1 == *s2)
		{
			s1++;
			s2++;
			if (*s2)
			{
				return cul;
			}
		}
		cul++;
	}
	return NULL;
}
int main()
{
	char str[] = "This is a simple string";
	char arr[] = "simple";
	char* p = my_strstr(str, arr);
	if (p == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("找到了\n");
	}
	return 0;
}

strstr最大作用就是找这个里面有没有我们想要的字符串,如果有就返回查找字符串内该字符串的地址,如果没有就返回空指针

strtok

char * strtok ( char * str, const char * sep );

sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针。

代码演示

#include <stdio.h>
#include <string.h>
int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
 {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
 }
  return 0;
}
#include <stdio.h>
int main()
{
   char *p = "tangjiale@lj.sy";
 const char* sep = ".@";
 char arr[30];
 char *str = NULL;
 strcpy(arr, p);//将数据拷贝一份,处理arr数组的内容
 for(str=strtok(arr, sep); str != NULL; str=strtok(NULL, sep))
 {
 printf("%s\n", str);
 }
}

主要解释第二个代码,因为我们的(str=strtok(arr, sep)只循环一次,这样就可以用for语句来实现,然后strtok是从该内容的后面开始查找,而我们遇到分隔符,其实就相当于变成’\0’,就是空指针,这样我们就写成一个循环,代码优化

strerror

char * strerror ( int errnum );

#include <stdio.h>
#include <string.h>
#include <errno.h>//必须包含的头文件
int main()
{
	FILE* pFile;
	pFile = fopen("unexist.ent", "r");
	if (pFile == NULL)
		printf("Error opening file unexist.ent: %s\n", strerror(errno));
	//errno: Last error number
	return 0;
}

在这里插入图片描述
我们的errno就是错误信息,要包含头文件,其实strerror和perror差不多,都是为了找出错误信息,我们也看看perror

在这里插入图片描述

函数 如果他的参数符合下列条件就返回真
iscntrl 任何控制字符
isspace 空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
isdigit 十进制数字 0~9
isxdigit 十六进制数字,包括所有十进制数字,小写字母af,大写字母AF
islower 小写字母a~z
isupper 大写字母A~Z
isalpha 字母az或AZ
isalnum 字母或者数字,az,AZ,0~9
ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph 任何图形字符
isprint 任何可打印字符,包括图形字符和空白字符

以上是一些字符函数的,大家下去一定要试试,这里小编就不一一举例子了

就介绍几个吧

isdigit 十进制数字 0~9
就比如这个,这个的作用就是我们再isdigit只能输入数字,这和while(x>‘0’ && x<‘9’)的效果一样

还有这个

int tolower ( int c );
int toupper (int c)

字符转换

#include <stdio.h>
#include <ctype.h>
int main ()
{
  int i=0;
  char str[]="Test String.\n";
  char c;
  while (str[i])
 {
    c=str[i];
    if (isupper(c)) 
        c=tolower(c);
    putchar (c);
    i++;
 }
  return 0;
}

在这里插入图片描述
转为小写

memcpy
在这里插入图片描述
模拟实现

void * memcpy ( void * dst, const void * src, size_t count)
{
        void * ret = dst;
 assert(dst);
   assert(src);
        /*
         * copy from lower addresses to higher addresses
         */
        while (count--) {
                *(char *)dst = *(char *)src;
                dst = (char *)dst + 1;
                src = (char *)src + 1;
       }
        return(ret);
}

memmove
在这里插入图片描述
模拟实现

#include<stdio.h>
void* memmove(void* dst, const void* src, size_t count)
{
	void* ret = dst;
	if (dst <= src || (char*)dst >= ((char*)src + count)) {
	
		while (count--) {
			*(char*)dst = *(char*)src;
			dst = (char*)dst + 1;
			src = (char*)src + 1;
		}
	}
	else {
		
		dst = (char*)dst + count - 1;
		src = (char*)src + count - 1;
		while (count--) {
			*(char*)dst = *(char*)src;
			dst = (char*)dst - 1;
			src = (char*)src - 1;
		}
	}
	return(ret);
}

strncpy
这个其实和strcpy差不多就是加了一个我们拷贝多少字节的内容,我就不过多讲解了

在这里插入图片描述

拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个
strncat
在这里插入图片描述

它可以给自己追加

/* strncat example */
#include <stdio.h>
#include <string.h>
int main ()
{
 char str1[20];
 char str2[20];
 strcpy (str1,"To be ");
 strcpy (str2,"or not to be");
 strncat (str1, str2, 6);
 puts (str1);
 return 0;
}

strncmp

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

在这里插入图片描述

#include <stdio.h>
#include <string.h>
int main ()
{
  char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
  int n;
  puts ("Looking for R2 astromech droids...");
  for (n=0 ; n<3 ; n++)
  if (strncmp (str[n],"R2xx",2) == 0)
 {
    printf ("found %s\n",str[n]);
 }
  return 0;
}

他的返回值是一个整型

今天的内容就讲完了。我们下次再见,谢谢大家

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

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

相关文章

office CVE-2022-30190 RCE 复现

简介: 当用户点击word等应用程序时&#xff0c;会使用URL协议调用MSDT,随即启动msdt.exe程序造成远程代码执行漏洞。简单来说就是攻击者可以恶意构造一个word文档&#xff0c;诱骗受害者点击&#xff0c;从而导致系统被黑。 0x01 环境部署 1. 测试版本 Microsoft Office LTSC …

FPGA XDMA 中断模式实现 PCIE3.0 视频采集 OV5640摄像头 提供2套工程源码和QT上位机源码

目录 1、前言2、我已有的PCIE方案3、PCIE理论4、总体设计思路和方案视频采集和缓存XDMA简介XDMA中断模式QT上位机及其源码 5、vivado工程1-->单路视频采集6、vivado工程2-->双路视频采集7、上板调试验证8、福利&#xff1a;工程代码的获取 1、前言 PCIE&#xff08;PCI …

springboot整合feign实现RPC调用

目录 一、服务提供者 二、服务消费者 三、测试效果 feign/openfeign和dubbo是常用的微服务RPC框架&#xff0c;由于feigin内部已经集成ribbon&#xff0c;自带了负载均衡的功能&#xff0c;当有多个同名的服务注册到注册中心时&#xff0c;会根据ribbon默认的负载均衡算法将…

用 perfcollect 洞察 Linux 上.NET程序CPU爆高

一&#xff1a;背景 1. 讲故事 如果要分析 Linux上的 .NET程序 CPU 爆高&#xff0c;按以往的个性我肯定是抓个 dump 下来做事后分析&#xff0c;这种分析模式虽然不重但也不轻&#xff0c;还需要一定的底层知识&#xff0c;那有没有傻瓜式的 CPU 爆高分析方式呢&#xff1f;…

使用testify包辅助Go测试指南

我虽然算不上Go标准库的“清教徒”&#xff0c;但在测试方面还多是基于标准库testing包以及go test框架的&#xff0c;除了需要mock的时候&#xff0c;基本上没有用过第三方的Go测试框架。我在《Go语言精进之路》[2]一书中对Go测试组织的讲解也是基于Go testing包和go test框架…

【Java|golang】415. 字符串相加

给定两个字符串形式的非负整数 num1 和num2 &#xff0c;计算它们的和并同样以字符串形式返回。 你不能使用任何內建的用于处理大整数的库&#xff08;比如 BigInteger&#xff09;&#xff0c; 也不能直接将输入的字符串转换为整数形式。 示例 1&#xff1a; 输入&#xff…

五笔衰落,PC和OCR惹得祸?

许多人认为五笔输入法的衰落主要因素是败给了拼音输入法&#xff0c;是被拼音输入法给“打残”了&#xff0c;取代了&#xff0c;其实这只是表面原因&#xff0c;笔者认为&#xff0c;其关键因素是PC的衰落和OCR技术的不断改进和发展&#xff0c;理由如下&#xff1a; 1、PC出…

TCP/IP详解

目录 一、OSI参考模型 1.图示 2.OSI七层模型各自作用 3.七层通信过程 二、IP协议 1.IPv4首部 2.IPv6首部 三、TCP协议 1.tcp首部格式 2.握手挥手图示 3.握手流程 4.为什么要三次握手&#xff1f; 5.四次挥手流程 6.为什么要四次分手&#xff1f; 7.为什么要等待…

kafka接收外部接口的数据,并实现转发

目录 一、什么是kafka 二、kafka接收外部接口数据 三、kafka收到数据后转发 四、kafka总结 一、什么是kafka Kafka是一种分布式流式处理平台&#xff0c;最初由LinkedIn开发。它设计用于高吞吐量、低延迟的数据处理&#xff0c;能够处理大规模的实时数据流。Kafka采用发布…

[PHP]解决exec执行unzip出现中文文件名乱码的问题

查看Linux编码&#xff0c;例如下图可看出Linx编码是zh_CN.UTF-8 问题截图&#xff1a; 以下代码都会产生乱码 exex(unzip -d /xxx /x/test.zip); exex(unzip -O zh_CN.UTF-8 -d /xxx /x/test.zip); exex(unzip -I zh_CN.UTF-8 -d /xxx /x/test.zip); 解决方法&#xff1a; …

Java线程的创建和使用

目录 基本概念 线程的创建和使用 线程的生命周期 基本概念 程序(program) 程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码&#xff0c;静态对象。 进程(process) 进程(process)是程序的一次执行过程&#xff0c;或是正在运行的一个程…

ESP32+MQTT+MySQL实现发布订阅【气味数据收集】

ESP32MQTTMySQL实现发布订阅【气味数据收集】 &#x1f52e;&#x1f52e;&#x1f52e;&#x1f52e;&#x1f52e;相关文章&#x1f52e;&#x1f52e;&#x1f52e;&#x1f52e;&#x1f52e; ESP32连接MQ Sensor实现气味反应 &#x1f517; https://blog.csdn.net/ws1516…

指针知多少

作者简介&#xff1a;დ旧言~&#xff0c;目前大一&#xff0c;现在学习Java&#xff0c;c&#xff0c;Python等 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 望小伙伴们点赞&#x1f44d;收藏✨加关注哟&#x1f495;&#x1f495; ⛵前言 不知道大家还记…

avi格式怎么转换成mp4?教你几种简单转换小技巧

由于 AVI 格式的文件结构&#xff0c;它们不适合用于流式传输。这意味着&#xff0c;如果你想在线观看一个 AVI 格式的视频&#xff0c;你需要等待整个文件下载完成后才能开始观看。这对于那些希望尽快开始观看视频的人来说可能是一个问题。那么我们怎么将AVI格式的视频转换成M…

【C语言】memcpy,memmove,memcmp,memset函数详解

memcpy,memmove,memcmp,memset函数详解 memcpy函数一、 memcpy函数的定义&#xff1a;二、memcpy函数的功能&#xff1a;三、memcpy函数模拟memcpy注意事项 memmove函数一、memmove函数简介二、memmove函数的模拟1.两种情况2模拟实现 memcmp函数memecmp函数介绍 memset函数mems…

Cell 子刊 - 4D打印一只可变形的蜘蛛

国自然“十四五”优先发展领域公布&#xff0c;共计115项&#xff01;&#xff08;生物医学领域节选&#xff0c;近 50 项&#xff09;中提到 4D打印是一个重要方向。 凝胶状墨水使得3D打印应用于电子设备的金属物体更容易。 3D打印在经济性、设计自由度和效率方面均超越了传统…

Matplotlib中文乱码解决方案(两种方式)

Matplotlib 默认不支持中文字体&#xff0c;这因为 Matplotlib 只支持 ASCII 字符&#xff0c;但中文标注更加符合中国人的阅读习惯。因此&#xff0c;本节重点讲解如何在 Windows 环境下让 Matplotlib 显示中文。 Matplotlib中文乱码 当不对 Matplotlib 进行设置&#xff0c…

网页版五子棋设计实现自动化测试

目录 一、设计测试用例 二、执行测试 登录页面 功能测试 界面测试 注册界面 功能测试 界面测试 游戏大厅 功能测试 界面测试 游戏房间 功能测试 界面测试 一、设计测试用例 二、执行测试 在执行测试之前首先获取到驱动。 登录页面 功能测试 首先定义star…

2023年9月长沙/郑州/济南DAMA-CDGA/CDGP认证考试报名

据DAMA中国官方网站消息&#xff0c;2023年度第三期DAMA中国CDGA和CDGP认证考试定于2023年9月23日举行。 报名通道现已开启&#xff0c;相关事宜通知如下&#xff1a; 考试科目: 数据治理工程师(CertifiedDataGovernanceAssociate,CDGA) 数据治理专家(CertifiedDataGovernanc…

Spark(26):Spark通讯架构

目录 0. 相关文章链接 1. Spark通信架构概述 2. Spark 通讯架构解析 0. 相关文章链接 Spark文章汇总 1. Spark通信架构概述 Spark 中通信框架的发展&#xff1a; Spark 早期版本中采用 Akka 作为内部通信部件。Spark1.3 中引入 Netty 通信框架&#xff0c;为了解决 Shuf…