整理介绍字符函数和字符串函数+内存函数

news2024/11/14 14:38:25

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

本篇重点

  • 本篇重点介绍处理字符和字符串的库函数的使用和注意事项
  • 前言:
  • 求字符串长度
    • strlen
  • 拷贝字符串函数
    • strcpy
  • (追加)连接字符串函数
    • strcat
  • 比较两个字符串函数
    • strcmp
  • 对上面改进字符串函数介绍
    • strncpy
    • strncat
    • strncmp
  • 查找子字符串函数
    • strstr
  • 将字符串拆分为标记的函数
    • strtok
  • 返回错误信息的函数
    • strerror
    • perror
  • 字符分类函数
    • islower
    • isupper
    • 归纳总结
  • 字符转换函数:
    • tolower
    • toupper
  • 针对内存的函数
    • memset
    • memcpy
    • memmove
    • memcmp

前言:

C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常要放在常量字符串中或者字符数组中。
字符串常量适用于那些对它不做修改的字符串函数

求字符串长度

strlen

在这里插入图片描述
注意点:

1. 字符串将’\0’作为结束标志,strlen函数返回的是在’\0’之前出现的字符个数但不包含‘\0’。
2. 参数指向的字符串必须要有’\0’,以’\0’为结束标志
3. 注意函数的返回值是size_t ,是无符号整数
4. 最好理解strlen函数的模拟实现

在这里我会展示3种方法来模拟实现strlen函数。
strlen函数模拟实现:
第一种:暴力法死算

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

第二种:指针-指针=指针之间元素的个数

size_t my_strlen(const char* str)
{
    assert(str);
	char* start = str;
	while (*str != 0)
	{
		str++;
	}
	return str - start;
	
}
int main()
{
	char arr[] = "abcdef";
	int ret = my_strlen(arr);
	printf("%d", ret);
	return 0;
}

第三种:递归法

size_t my_strlen(const char* str)
{
	assert(str);
	if (*str != '\0')
	{
		return 1 + my_strlen(str + 1);
	}
	else
		return 0;

}
int main()
{
	char arr[] = "abcdef";
	int ret = my_strlen(arr);
	printf("%d", ret);
	return 0;
}

还有一个题目来考考你:涉及上面的注意点喔

#include <string.h>
int main()
{
	const char* str1 = "abcdef";
	const char* str2 = "bbb";
	if (strlen(str2) - strlen(str1) > 0)
	{
		printf("str2>str1\n");
	}
	else
	{
		printf("srt1>str2\n");
	}
	return 0;
}

结果:
在这里插入图片描述
为什么呢?
计算str1的字符串大小应该为6,计算str2的字符串大小应该是3,3-6应该小于0,应该打印str1>str2才对呢。
是不是忘记了什么?strlen函数的返回值是什么呢?是size_t类型的,两个无符号数相减,得到的也是无符号数,所以-3就被当作无符号数来看啦,这将是一个非常大的数。所以肯定大于0。

拷贝字符串函数

strcpy

在这里插入图片描述

注意点:

1. 将源指向的C字符串复制到目标指向的数组中,包括
终止空字符(并在该点停止)
2. 源字符串必须以’\0’结束
3. 会将源字符串的’\0’拷贝到目的空间
4. 目标空间要足够大,以确保源字符串能存放进去
5. 目标空间必须可变,不能是常量
6. 要理解strcpy模拟实现
strcpy函数模拟实现

#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);//断言判断dest和src指针不为空指针
	char* start = dest;//记录dest的起始位置,因为最后还要将目标空间的起始地址返回
	while (*dest++ = *src++)
	{
		;//将源字符串全部拷贝到目的空间里,当*src为'\0'时,赋值给dest后该表达式为假,跳出循环,全部拷贝成功
	}
	return start;//将起始地址传回
}
int main()
{
	char arr1[20] = { 0 };//目标空间要足够大
	char arr2[] = "abcdef";
	char *ret=my_strcpy(arr1, arr2);
	printf("%s", ret);
	return 0;
}

结果:
在这里插入图片描述

(追加)连接字符串函数

strcat

在这里插入图片描述

注意点:

1. 将源字符串的副本追加到目标字符串。终止的空字符
in destination被源的第一个字符覆盖,并且包含一个空字符
在由目的地中的二者串联形成的新字符串的末尾。
2. 源字符串必须以’\0’结束
3. 目标空间必须要足够大,能容纳源字符串
4. 目的空间要能修改
5. 该函数不能用于字符串给自己追加
strcat函数模拟实现:

#include <stdio.h>
#include <assert.h>
char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);//断言判断
	char* start = dest;
	//首先要找到目的空间的'\0'
	while (*dest!='\0')
	{
		dest++;
	}
	//再将字符串追加到'\0'的后面,包括'\0'
	while (*dest++ == *src++)
	{
		;
	}
	return start;//最后返回目标空间的起始地址
	
}
int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	char* ret =my_strcat(arr1, arr2);
	printf("%s",ret );
	return 0;
}

结果:
在这里插入图片描述

比较两个字符串函数

strcmp

在这里插入图片描述

注意点:

1. 此函数开始比较每个字符串的第一个字符。如果它们相等,它继续使用,直到字符不同或终止达到空字符。
2. 标志规定:

第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数

3. 比较的是相同位上字符的ASCII 码值
模拟实现strcmp函数

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	//先比较第一个字符,如果相同则比下一个,后面的类似。
	//直到相同位的字符不一样比较字符ASCII码值
	while (*str1 == *str2)
	{
		if (*str1 == '\0')//在这个循环里,如果str1和str2中有一个等于0则表示两个字符串是相等的,因为在str1==str2的条件下,又等于0
		{//肯定是相等的
			return 0;
		}
		str1++;
		str2++;
	}
	return *str1 - *str2;

}
int  main()
{
	char arr1[] = "abc";
	char arr2[] = "abd";
	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;
}

结果:
在这里插入图片描述
还有一个注意点:

  1. 在VS编译器环境下strcmp比较两个字符串时,第一个字符串大于第二个字符串返回的是1,第一个字符串小于第二字符串返回的是-1,相同时返回是0,但在不同的环境下,strcmp函数的返回的值可能不是1,-1,所以不能一概而论。
    比如这题这样写你觉得合适吗?
int  main()
{
	char arr1[] = "abc";
	char arr2[] = "abd";
	int ret=my_strcmp(arr1, arr2);
	if (ret==1)
	{
		printf("arr1>arr2");
	}
	else if (ret==-1)
	{
		printf("arr1<arr2");
	}
	else
		printf("arr1=arr2");
	return 0;
}

虽然也能算出来,但在不同的环境下,就不一定能算出来了所以最好还是写成大于0,小于0的形式比较保险。

对上面改进字符串函数介绍

strncpy

是对strcpy函数的改进版,增加了可以拷贝几个字符的功能,其他都一样。
在这里插入图片描述
注意点:

1. 将源的前num个字符复制到目标。如果源C字符串的结尾
(由空字符发出信号)在num个字符被复制之前被发现,
目标用零填充,直到总共写入num个字符。
2. 拷贝num个字符从源字符串到目的空间
3. 如果源字符串的长度小于num,则拷贝源字符串后,在目标的后面追加0,直到num为止。

strncat

是对strcat函数的改进版,增加了可以追加几个字符的功能,其他的都一样。
在这里插入图片描述
注意点:
将源的前num个字符追加到目标,加上终止的空字符。
如果源代码中的C字符串的长度小于num,则仅复制终止空字符之前的内容。

strncmp

是strcmp函数的改进版,可以选择比较前num个字符的大小
在这里插入图片描述
注意点:
比较出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。

查找子字符串函数

strstr

在这里插入图片描述
注意点:

1. 返回值是指向str1中首次出现str2所指向的代表的字符的地址,如果序列在str1中不存在,则返回NULL指针
2. 是查找str1中是否有str2这个字符子串。

例子:

int main()
{
	char str[] = "This is a simple string";
	char* ret;
	ret = strstr(str, "simple");
	//strstr返回的是在str数组中首次出现"simple"的指针,如果没有出现就返回NULL;
	printf("%s", ret);
	return 0;
}

结果:
在这里插入图片描述
模拟实现strstr函数:

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	if (*str2 == '\0')
	{
		return str1;
	}
	char* s1 = NULL;
	char* s2 = NULL;
	char* cp = str1;
	//
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cp;
		}
		cp++;
	}
	return NULL;
}
int main()
{
	char arr1[] = "abbbcd";
	char arr2[] = "bc";
	char* ret = my_strstr(arr1, arr2);
	printf("%s", ret);
	return 0;
}

结果:
在这里插入图片描述

将字符串拆分为标记的函数

strtok

在这里插入图片描述

注意点:

  1. 参数 deli是个字符串,定义了用作分隔符的字符集合
  2. 第一个参数指定了要一个字符串,它必须包含0个或多个由deli字符串中一个或者多个分隔符分割的标志
  3. strtok函数找到str中的一个标记,会将其用’\0’替换,返回一个指向这个标记的指针。(strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容)
  4. strtok函数的第一个参数不为NULL,函数将会找到str中的第一个标记,strtok函数将保存它在字符串中的位置
  5. strtok的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
  6. 如果字符串中不存在更多的标记,则返回NULL指针

例子:

#include <string.h>
int main()
{
	char arr1[] = "xiao tao lailo@qq.com";//要分割的字符串C
	char arr2[] = "@.";//分割符形成的集合分割符@ 和 分割符 .
	char arr3[100] = { 0 };
	strcpy(arr3, arr1);//将数据临时拷贝一份,处理arr1中的内容
	char*ret=strtok(arr3, arr2);//第一次要将完整的要分割的字符串作为参数
	printf("%s\n", ret);
	ret = strtok(NULL, arr2);//第二次就不需要字符串了,只需要NULL作为参数就可以
	printf("%s\n", ret);
	ret = strtok(NULL, arr2);//第三次也是一样
	printf("%s\n", ret);
	return 0;
}

在这里插入图片描述
也可以把分割的过程写成一个循环,因为就第一次不同,后面的都是一样的可以写成下面这样:

#include <string.h>
int main()
{
	char arr1[] = "xiao tao lailo@qq.com";//要分割的字符串C
	char arr2[] = "@.";//分割符形成的集合分割符@ 和 分割符 .
	char arr3[100] = { 0 };
	strcpy(arr3, arr1);//将数据临时拷贝一份,处理arr1中的内容
	//char*ret=strtok(arr3, arr2);//第一次要将完整的要分割的字符串作为参数
	//printf("%s\n", ret);
	//ret = strtok(NULL, arr2);//第二次就不需要字符串了,只需要NULL作为参数就可以
	//printf("%s\n", ret);
	//ret = strtok(NULL, arr2);//第三次也是一样
	//printf("%s\n", ret);
	char* ret = NULL;
	for (ret = strtok(arr3, arr2); ret != NULL; ret = strtok(NULL, arr2))
	{
		printf("%s\n", ret);
	}
	return 0;
}

返回错误信息的函数

strerror

在这里插入图片描述
注意点:这个函数的功能是,返回错误码,所对应的错误信息
例子:

#include <errno.h>//使用该库函数需要引用头文件
#include <string.h>
int main()
{
	FILE* pFile = fopen("unexist.txt", "r");//打开一个不存在的文件
	if (pFile == NULL)//打开失败会进行报错
	{
		printf("%s", strerror(errno));//错误信息打印
	}
	else
		fclose(pFile);
	return 0;
}

结果:在这里插入图片描述

perror

这个相比较上面的更方便些,因为这个直接可以打印报错
在这里插入图片描述
例子:

#include <string.h>
int main()
{
	FILE* pFile = fopen("unexist.txt", "r");//打开一个不存在的文件
	if (pFile == NULL)//打开失败会进行报错
	{
		perror("fopen");//参数是在哪个过程会报错呢就写哪个过程。
	}
	else
		fclose(pFile);
	return 0;
}

结果:
在这里插入图片描述

字符分类函数

在这里插入图片描述

islower

判断是否是小写字母函数
在这里插入图片描述
返回值:
在这里插入图片描述

是—返回非0,不是返回0.
例子:

#include <stdio.h>
#include <ctype.h>
int main()
{
	int ret1 = islower('A');
	int ret2 = islower('a');
	printf("%d\n", ret1);//不是小写字母返回0
	printf("%d\n", ret2);//是小写字母返回非0

	return 0;
}

在这里插入图片描述

isupper

1.检查字符是否为大写字母
在这里插入图片描述
2.返回值:
在这里插入图片描述
是大写字母就返回非0,不是就返回0.
3.例子:

#include <stdio.h>
#include <ctype.h>
int main()
{
	int ret1 = isupper('A');//是大写字母返回非0
	int ret2 = isupper('a');//不是大写字母返回0
	printf("%d\n", ret1);
	printf("%d\n", ret2);

	return 0;
}

在这里插入图片描述

归纳总结

以上字符分类函数的结构都是一样的,返回值也是差不多的,如果是真就返回非0的数,如果是假就返回0。
都是只有一个参数,一个整数返回值。参数取决于是分类什么。

字符转换函数:

tolower

在这里插入图片描述
例子1:

#include <ctype.h>
int main()
{
	int ret=tolower('A');//将大写转换为小写
	printf("%c", ret);
	return 0;
}

在这里插入图片描述
例子2:

#include <ctype.h>
int main()
{
	int i = 0;
	char arr[] = "Xiao Tao Lai Lo";
	char c;
	while (arr[i])
	{
		c = arr[i];
		if (isupper(c))//如果是大写
		{
			c = tolower(c);//转换成小写
		}
		putchar(c);//输出
		i++;
	}
	return 0;
}

结果:
在这里插入图片描述

toupper

将小写字母转换为大写字母
在这里插入图片描述
例子:

#include <ctype.h>
int main()
{
	int ret=toupper('a');//将小写转换为大写
	printf("%c", ret);
	return 0;
}

在这里插入图片描述

以上函数都是针对字符或者字符串的,下面将介绍可以改变各种类型的函数————内存函数

针对内存的函数

memset

在这里插入图片描述
注意点:

1. 这是内存设置函数
2. 以字节为单位来设置内存中的数据

例子:

#include <string.h>
int main()
{
	char arr[] = "xiao tao lai lo";
	memset(arr, 'x', 4);//第一个参数是要指向设置的内存块的指针
	                    //第二个参数是要设置的值
	                    //第三个参数是要设置多少字节数
	printf("%s\n", arr);
	memset(arr + 5, 'y', 3);
	printf("%s\n", arr);
	return 0;
}

在这里插入图片描述
注意:这个是以字节为单位改变内存的

int main()
{
    int arr[10] = { 0 };
    memset(arr, '1', 40);//要将arr这个内存块40个字节全部设置成1可以吗?

    return 0;
}

![在这里插入图片描述](https://img-blog.csdnimg.cn/2188d9e7

可是通过监测分析arr中每个数都是一个很大的数字这是为什么呢?
这是因为memset是以字节为单位来改变内存的,它每次修改一个字节,也就是每次将一个字节修改为1,所以一个int类型4个字节,就改成了4个1了。
在这里插入图片描述

一开始内存中都是0,使用memset函数后看内存中是什么样子呢?

在这里插入图片描述
所以在使用memset函数时要注意这点,不然容易出错。一般memset函数用于将一个变量初始化为0,比较容易。

memcpy

在这里插入图片描述

例子:

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1, 40);//参数1是要拷贝的目标空间,参数2是拷贝的源数据,参数3是拷贝的数量
	return 0;
}

在这里插入图片描述
我们可以来深入的理解这个函数,来模拟实现下
memcpy函数模拟实现:

void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;//记录一下目标空间的起始地址,最后返回要用
	//由于void*类型无法使用我们需要把它强制类型转换为char*
	while (num--)//循环num次
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
		//注意这里不能写成(char*)dest++这种形式,因为强制类型转换的只是暂时的,++后还是void*类型的
		//但是可以++(char*)dest这样写
	}
	return ret;//返回目标空间的起始地址
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr1, 40);
	return 0;
}

在这里插入图片描述
注意点2:
在这里插入图片描述
该函数要求要拷贝的空间与源数据的空间不能由重叠
举个例子:

在这里插入图片描述
它要求使用memmove这个函数来处理有重叠部分。其实在VS环境下,memove的功能与memcpy功能是差不多的都可以处理
但有的环境不可以,所以保险起见,当处理有重叠部分的需要使用memove函数,接下来就介绍memove函数

memmove

在这里插入图片描述
这个功能结构都是与memcpy是一样的,只不过更全面可以用于重叠部分的拷贝

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr, arr + 2, 20);
	//要求将 3 4 5 6 7拷贝到 1 2 3 4 5内容去,
	return 0;
}

在这里插入图片描述
那怎么实现重叠部分的拷贝的呢?
分情况讨论下,1.当目标空间在源数据空间的左边时
在这里插入图片描述在这里插入图片描述

2.当目标空间在源数据的右边时
在这里插入图片描述
所以总结下,当目的空间地址小于源数据空间时,从前往后交换
当目的空间地址大于源数据空间时,从后往前交换
模拟实现下这个memmove函数吧

void* my_memmove(void* dest, void* src, size_t num)
{
	void* ret = dest;//记录一下目标空间的起始地址,最后返回要用
	if (dest < src)
	{
		//从前往后交换,跟memcpy一样直接复制过来就可以
		
		while (num--)//循环num次
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//从后完前交换
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr+2, arr, 20);
	//要求将 1 2 3 4 5拷贝到 3 4 5 6 7内容去,
	return 0;
}

memcmp

在这里插入图片描述
返回值:
在这里插入图片描述

例子:

int main()
{
	int arr1[] = { 1,2,3 };
	int arr2[] = { 1,2,4 };
	int ret=memcmp(arr1, arr2, 8);//前两个都一样所以最后结果应该为0
	printf("%d", ret);
	return 0;
}
int main()
{
	int arr1[] = { 1,2,3 };
	int arr2[] = { 1,2,4 };
	int ret=memcmp(arr1, arr2, 12);//前两个都一样,但第三个不同进行比较,3小于4,所以最好结果为<0
	printf("%d", ret);
	return 0;
}

在这里插入图片描述

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

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

相关文章

Mac应用程序无法打开或文件损坏的处理方法

很多用户在安装 盗版 Mac软件的时候&#xff0c;经常会遇到提示“xxx.app已损坏&#xff0c;打不开。您应该将它移到废纸篓“或”打不开的xxx.app&#xff0c;因为它来自身份不明的开发者”&#xff0c;等多种打不开盗版软件的各种提示&#xff0c;正版软件则不会出现。 错误截…

17种编程语言实现排序算法-基数排序

开源地址 https://gitee.com/lblbc/simple-works/tree/master/sort/ 覆盖语言&#xff1a;C、C、C#、Java、Kotlin、Dart、Go、JavaScript(JS)、TypeScript(TS)、ArkTS、swift、PHP。 覆盖平台&#xff1a;安卓(Java、Kotlin)、iOS(SwiftUI)、Flutter(Dart)、Window桌面(C#)、…

事件冒泡和时间捕获

事件冒泡和事件捕获 最近&#xff0c;在复习Vue的时候&#xff0c;发现自己对于事件冒泡和事件捕获的理解存在一定的错误。于是想写一份笔记来总结一下事件冒泡和事件捕获。✌✌✌ 一、事件 1、事件的三个阶段&#xff1a;事件捕获->事件目标->事件冒泡 捕获阶段&am…

MySQL 性能优化浅析及线上案例

作者&#xff1a;京东健康 孟飞 1、 数据库性能优化的意义 业务发展初期&#xff0c;数据库中量一般都不高&#xff0c;也不太容易出一些性能问题或者出的问题也不大&#xff0c;但是当数据库的量级达到一定规模之后&#xff0c;如果缺失有效的预警、监控、处理等手段则会对用户…

设计模式学习(十二):Decorator装饰器模式

一、什么是Decorator模式假如现在有一块蛋糕&#xff0c;如果只涂上奶油&#xff0c;其他什么都不加&#xff0c;就是奶油蛋糕。如果加上草莓&#xff0c;就是草莓奶油蛋糕。如果再加上一块黑色巧克力板&#xff0c;上面用白色巧克力写上姓名&#xff0c;然后插上代表年龄的蜡烛…

JavaEE5-Spring更简单的读取和存储对象

目录 1.存储Bean对象 1.1.前置工作&#xff1a;在配置文件中设置bean扫描的根路径&#xff08;重要&#xff09; 1.2.添加注解存储Bean对象到Spring中 1.2.1.类注解(添加到某个类上&#xff0c;将当前的类存储到Spring中)&#xff1a;Controller&#xff0c;Service&#x…

树,堆,二叉树的认识

1.树概念及结构 1.1树的概念 注意&#xff1a;树形结构中&#xff0c;子树之间不能有交集&#xff0c;否则就不是树形结构 1.2 树的相关概念 1.3 树的表示 树结构相对线性表就比较复杂了&#xff0c;要存储表示起来就比较麻烦了&#xff0c;既然保存值域&#xff0c;也要保存…

Gateway服务网关

Gateway服务网关一、网关介绍二、gateway快速入门1.创建gateway服务&#xff0c;引入依赖2.编写启动类3.编写基础配置和路由规则4.重启测试5.网关路由的流程图三、断言工厂四、过滤器工厂1.路由过滤器的种类2.请求头过滤器3.默认过滤器4.总结五、全局过滤器1.全局过滤器作用2.自…

fpga实操训练(系统开发和硬件接口)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 相信很多学习fpga的同学都会有这样的一个感受,一开始fpga学习还比较简单,但是一旦涉及到呼吸灯、uart、spi、iic、ddr2后面就会越来越难。遇到这样的困难之后,学习的激情一下子少…

从零搭建一个组件库(一)项目环境搭建

文章目录前言monorepo架构1.monorepo架构的优势2.使用pnpm搭建monorepo架构&#xff08;1&#xff09;全局安装pnpm&#xff08;2&#xff09;初始化项目&#xff08;3&#xff09;新建workspace.yaml文件4.不同包之间的相互引用TypeScript支持1.安装TypeScript2.初始化TypeScr…

http三次握手四次挥手详解

1、 TCP的三次握手和四次挥手实质就是TCP通信的连接和断开。 三次握手&#xff1a;为了对每次发送的数据量进行跟踪与协商&#xff0c;确保数据段的发送和接收同步&#xff0c;根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系&#xff0c;并建立虚连接。 四次挥…

C++6:STL-模拟实现string

string时STL中的模板库之一&#xff0c;类似于专门处理字符串的数据结构&#xff0c;在模拟实现并探讨其中构造的巧妙之处之前&#xff0c;我们短浅的认识一下STL是什么 目录 什么是STL STL的诞生 关于string string的模拟实现 构造函数和析构函数 实现简单的string打印 …

【蓝桥杯】简单数论2——快速幂矩阵快速幂

1、快速幂 1.1运算模 定义&#xff1a;模运算为a除以m的余数&#xff0c;记为a mod m&#xff0c;有a mod m a % m。 模运算是大数运算中的常用操作&#xff1a;如果一个数太大&#xff0c;无法直接输出&#xff0c;或者不需要直接输出&#xff0c;可以把它取模后&#xff0…

Android 深入系统完全讲解(37)

7.5 源码讲解 dlopen 打开动态库 dlsym 找到符号 (*print_func)(); 调用方法 我们可以看到&#xff0c;要使用一个 so 库的某个方法&#xff0c;就上面三步骤&#xff0c;加载 &#xff0c;查找 &#xff0c;使用 。我 们这里调用了 so 库中的 my_print 方法。 7.6 运行 我们把…

Linux——进程间通信

文章目录前言1. 进程间通信方式的一些标准&#xff1a;2. 管道2.1 什么是管道2.2 管道的原理2.3 匿名管道2.3.1 实例代码1. demo代码2. 总结管道的特点&#xff0c;理解以前的管道 |3. 扩展——进程池2.4 管道读写规则2.5 命名管道2.5.1 创建一个命名管道2.5.2 命名管道的打开规…

Python break用法详解

我们知道&#xff0c;在执行 while 循环或者 for 循环时&#xff0c;只要循环条件满足&#xff0c;程序将会一直执行循环体&#xff0c;不停地转圈。但在某些场景&#xff0c;我们可能希望在循环结束前就强制结束循环&#xff0c;Python 提供了 2 种强制离开当前循环体的办法&a…

路由处理及功能(实现了权限控制vue admin)

界面简化 将 template 改为&#xff1a; <template><div class"login-container"><el-formref"loginForm":model"loginForm":rules"loginRules"class"login-form"autocomplete"on"label-positio…

Mybatis遇到的脑残问题

一、MySQL的版本问题 有的教程mysql是8.0版本使用jar包不一样 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0</version></dependency>然后我查了一下我的mysql版本是5.7版…

分支语句与循环语句

文章目录 什么是语句&#xff1f; 分支语句&#xff08;选择结构&#xff09;循环语句goto语句前言 一、什么是语句&#xff1f; C语句可分为以下五类&#xff1a; 1. 表达式语句 2. 函数调用语句 3. 控制语句 4. 复合语句 5. 空语句 控制语句用于控制程序的执行流程&#xff0…

第九层(1):初识STL

文章目录前情回顾初识STLSTL的诞生STL的基本概念STL六大组件STL中的容器、算法、迭代器容器算法迭代器容器、算法、迭代器的配合使用vector中的嵌套使用石碑倒下...后面还有石碑&#xff1f;本章知识点&#xff08;图片形式&#xff09;&#x1f389;welcome&#x1f389; ✒️…