C语言进阶——字符函数和字符串函数(下)

news2024/11/28 22:31:35

在前面我们已经学习了strlen、strcpy、strcat、strcmp几个库函数,今天我们继续学习剩余的库函数。

上期链接:

C语言进阶——字符函数和字符串函数(上)_wangjiushun的博客-CSDN博客

目录:

3、长度受限制的字符串函数

        strncpy

        strncat

        strncmp

4、字符串查找

        strstr

        strtok

5、错误信息报告

        strerror

6、字符操作

7、内存操作函数

        memcpy

        memmove

        memset

        memcmp


三、长度受限制的函数字符串

1、 strncpy

函数原型:char* strncpy(char* destination, const char* source, size_t num);

1、从源字符串拷贝num个字符到目标空间

2、如果源字符串的长度大于num,则只拷贝num个字符,并不会在目标空间后追加‘\0’字符

3、如果源字符串的长度小于num,则拷贝玩源字符串之后(包括‘\0’),在目标空间的后面追加‘\0’,直到num个。

4、源指向的空间与目标空间不能重叠

5、目标空间必须可变

讲解:

(1)strncpy函数的返回类型和参数是怎么设计的?

        strncpy与strcpy相似,只是多了一个参数size_t num,可以自己决定拷贝几个字符源字符串到目标空间中(在决定拷贝几个字符时,我们会考虑目标空间是否足够大),所以相对strcpy函数安全一些。

(2)拷贝num个字符从源字符串到目标空间

        ①如果源字符串长度大于num,则只拷贝num个字符,并不会在目标后追加‘\0’

代码实例:

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

int main()
{
	char arr1[20] = "################";
	char arr2[] = "abcdef";
	//把arr2中的以首字符开始的前3个字符拷贝到arr1中
	strncpy(arr1, arr2, 3);
	printf("%s\n", arr1);
	return 0;
}

        F10调试之后,观察目标空间arr1的内存:

         ②如果源字符串的长度小于num,则拷贝玩源字符串之后(包括‘\0’),在目标空间的后面追加‘\0’,直到num个。

代码实例:

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

int main()
{
	char arr1[20] = "################";
	char arr2[] = "abcdef";
	//把arr2中的以首字符开始的前10个字符拷贝到arr1中
	strncpy(arr1, arr2, 10);
	printf("%s\n", arr1);
	return 0;
}

        F10调试之后,观察目标空间arr1的内存:

 (3)模拟实现strncpy

分析:

        strncpy函数是从源字符串拷贝num个字符到目标空间的,模拟strncpy,那函数的返回类型、参数类型应该一致。

函数体的实现:

        ①定义char* start变量存储目标空间的起始地址;

        ②将源字符串拷贝num个字符到目标空间:

                a. 拷贝源字符串:num <= 源字符串

                b. 判断num是否为0,不为0在目标后追加‘\0’

        ③返回目标空间的起始地址。

代码演示:

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

char* my_strncpy(char* dest, const char* src, size_t num)
{
	//断言指针的有效性
	assert(dest && src);
	//存储目标空间的起始地址
	char* start = dest;
	//将源指向的字符串拷贝num个字符到目标空间
	//①num <= 源字符串,拷贝源字符串
	while (num)//注意num是无符号类型,写成后置--,易错,所以在后面单独成一条语句
	{
		if ((*dest++ = *src++) == '\0')
		{
			break;
		}
		--num;
	}
	//②num > 源字符串,在目标后面追加'\0',直至拷贝num个字符
	if (num)
	{
		while (--num)
		{
			*dest++ = '\0';
		}
	}
	//返回目标空间起始地址
	return start;
}

int main()
{
	char arr1[10] = "#########";
	char arr2[] = "abcde";
	//从arr2中拷贝3个字符到arr1
	printf("%s\n", my_strncpy(arr1, arr2, 3));
	//从arr2中拷贝8个字符到arr1
	printf("%s\n", my_strncpy(arr1, arr2, 8));
	return 0;
}

        积累:当类型为无符号类型,后置--且为循环条件循环两次是,易错!(后置--,先赋值再-1,可能减到负数,负数在无符号类型下是很大的正数)

2、 strncat

函数原型:char* strncat(char* destination, const char* source, size_t num);

1、从源字符串的第一个字符开始拷贝num个字符到目标空间字符串的尾部,追加完后再外加一个‘\0’字符;(说明:①目标空间的‘\0’被源字符串的第一个字符覆盖②注意只拷贝源字符串‘\0’之前的字符,不拷贝‘\0’)

2、注意:如果源字符串的长度小于num,则只拷贝‘\0’之前的内容;

3、源指向的空间与目标空间不可以重叠;

4、目标空间可变。

讲解:

(1)模拟strncat

分析:

        strncat函数是从源指向的第一个字符开始拷贝num个字符到目标空间字符串的尾部,追加完后再外加终止‘\0’字符,模拟strncat,那函数的返回类型、参数类型应该一致。

函数体的实现:

        ①定义char* start变量存储目标空间的起始地址;

        ②从源字符串开始拷贝num个字符到目标空间的尾部,追加完后在加终止‘\0’字符:

                a. 找到目标空间的终止‘\0’字符

                b. 追加num个字符到目标空间,当满足条件num > 源字符串长度时,则拷贝完源字符串(包括‘\0’)后,直接返回目标空间起始地址

                c. num < 源字符串长度,追加完num个字符后,再外加终止‘\0’字符

                d. 返回目标空间起始地址(num < 源字符串)

代码演示:

//模拟strncat
#include<stdio.h>
#include<assert.h>

char* my_strncat(char* dest, const char* src, size_t num)
{
	//断言指针的有效性
	assert(dest && src);
	//存储目标空间的起始地址
	char* start = dest;
	//追加num个字符到目标空间
	//①找到目标空间的\0
	while (*dest)
	{
		dest++;
	}
	//②追加num个字符到目标空间
	while (num)
	{
		//如果num > 源字符串的长度,则拷贝到\0退出函数
		if ((*dest++ = *src++) == '\0')
		{
			return start;
		}
		num--;
	}
	//num < 源字符串长度,追加完后附加\0
	*dest = '\0';
	return start;
}

int main()
{
	char arr1[10] = "######";
	char arr2[] = "abc";
	printf("%s\n", my_strncat(arr1, arr2, 2));
	return 0;
}

3、 strncmp

函数原型:int strncmp(const char* str1, const char* str2, size_t num);

1、比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完

2、返回值与strncmp一样

讲解:

(1)模拟strncmp

分析:

        strncmp函数是str1和str2比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完,模拟strncmp,那函数的返回类型、参数类型应该一致。

函数体的实现:

        ①while循环比较num个对应字符:

                a. 当满足情况——比较到不同字符,*str1 > *str2,返回1,*str1 < *str2,返回-1

                b. 当满足情况——一个字符串结束(即相等),返回0

        ②比较完num个字符,均未出现不同字符,即相等,返回0

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

int my_strncmp(const char* str1, const char* str2, size_t num)
{
	//断言指针的有效性
	assert(str1 && str2);
	//比较num个对应字符的ASCII值
	while (num)
	{
		//①比较到不同的字符
		if (*str1 != *str2)
		{
			//如果str1 > str2,返回1,否则返回-1
			if (*str1 > *str2)
			{
				return 1;
			}
			else
			{
				return -1;
			}
		}
		//②一个字符串结束,返回0
		if (*str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
		--num;
	}
	//比较完num个字符,均相同,返回0
	return 0;
}

int main()
{
	char arr1[] = "abcqw";
	char arr2[] = "abcaw";
	int ret = my_strncmp(arr1, arr2, 4);
	if (ret > 0)
	{
		printf("arr1 > arr2\n");
	}
	else if (ret == 0)
	{
		printf("arr1 = arr2\n");
	}
	else
	{
		printf("arr1 < arr2\n");
	}
	return 0;
}

四、字符串查找

1、 strstr

函数原型:char* strstr(const char* str1, const char* str2);

1、strstr函数查找子字符串;

2、在str1中找str2中第一次出现的位置,如果找到返回一个指针,指向str2在str1中第一次出现的位置;如果找不到(即str2不是str1的子集),就返回一个NULL指针。

讲解:

(1)代码演示:strstr

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

int main()
{
	char str[] = "This is a simple string";
	//接收strstr的返回值
	char* pch;
	//将str字符串中的simple子串修改为sample
	//①得到子串在str中第一次出现的位置
	pch = strstr(str, "simple");
	if (pch != NULL)
	{
		//②将sample拷贝到子串的位置
		strncpy(pch, "sample", 6);
		//输出修改后的str
		puts(str);
	}
	else
	{
		printf("str中子串不存在\n");
	}
	return 0;
}

(2)模拟strstr

分析:

        strstr函数是查找字符串,判断str2是否为str1的子集,是则返回str1中str2第一次出现得我位置,否则返回NULL。

函数体的实现:

        ①特殊情况:str为‘\0’是,直接返回str1(“特事特办”)

        ②遍历str1,当满足情况str2是str1的子集或str1结束:

              a. cp指针用来遍历str1,给s1赋值;

              b. c. s1指针用来每次判断该位置是否为str1中子集str2的位置,不是则str1遍历;

               c.  s2指针用来遍历str2是否与s1相等,相等则返回s1的起始地址(即cp),不相等则重新回到str2的位置;

代码演示:

//模拟strstr
/*
	分析:strstr函数查找子字符串,判断str2是否为str1的子集。是则返回子字符串的位置,否则返回NULL
*/
#include<stdio.h>
#include<assert.h>

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	//特殊情况:str2为'\0'时,直接返回str1
	if (*str2 == '\0')
	{
		return (char*)str1;
	}
	//s1用于从主字符串的第一个字符开始遍历主字符串是否包含子串,
	//遍历到不同于子串的字符,又从主字符串的第二个字符开始遍历;
	//直至遍历到包含,或遍历到主字符串的\0
	const char* s1 = NULL;
	//s2每一次新遍历时都会重新回到str2的位置
	const char* s2 = NULL;
	//存放子串可能的位置,从主字符串的首字符开始
	const char* cp = str1;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 != '\0' && *s2 != '\0' && * s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)cp;
		}
		else if (*s1 == '\0')
		{
			return NULL;
		}
		cp++;
	}
	return NULL;
}

int main()
{
	char arr1[] = "abbcdbba";
	char* ret = my_strstr(arr1, "bbbd");
	if (ret != NULL)
	{
		printf("%s\n", ret);
	}
	else
	{
		printf("没有找到\n");
	}
	return 0;
}

2、 strtok

函数原型:char* strtok(char* str,const char* sep);

1、sep参数是个字符串,定义了用作分隔符的字符集合;

2、第一个参数指定一个字符串,它包含了0个或多个由sep字符串中一个或者多个分隔符分割的标记;

3、strtok函数找到str中的下一个标记,并将其用‘\0’结尾,返回一个指向这个标记的指针(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。);

4、strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置;

5、strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记;

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

代码演示:

代码1:

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

int main()
{
	char arr[] = "2809552931@qq.com";
	//分割邮箱
	//2809552931  qq  com
	//分割符集合:@.
	char* sep = "@.";
	//注意:strtok函数会改变被操作的字符串,所以在使用strtok分割的字符串
	//一般都是临时拷贝的内容并且可修改。
	char arr1[20];
	strcpy(arr1, arr);
	//strtok函数找到arr中的标记,并将其用\0结尾,返回一个指向这个标记的指针
	//①strtok函数的第一个参数不为NULL,函数将找到arr1中第一个标记,
	//strtok函数将保存它在字符串中的位置
	char* ret = strtok(arr1, sep);
	printf("%s\n", ret);
	//②strtok函数的第一个参数为NULL,函数将在同一个字符串中
	//被保存的位置开始,开始查找下一个标记
	ret = strtok(NULL, sep);
	printf("%s\n", ret);
	//③如果字符串不存在更多的标记,则返回NULL指针
	ret = strtok(NULL, sep);
	printf("%s\n", ret);
	return 0;
}

代码2:

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

int main()
{
	char arr[] = "2809552931@qq.com";
	//分割邮箱
	//2809552931  qq  com
	//分割符集合:@.
	char* sep = "@.";
	//注意:strtok函数会改变被操作的字符串,所以在使用strtok分割的字符串
	//一般都是临时拷贝的内容并且可修改。
	char arr1[20];
	strcpy(arr1, arr);
	char* ret = NULL;
	//strtok函数:除第一次调用,其余调用都是传null,这样才会继续向后寻找分隔符
	for (ret = strtok(arr1, sep); ret != NULL; ret = strtok(NULL, sep))
	{
		printf("%s\n", ret);
	}
	return 0;
}

五、错误信息报告

1、strerror

头文件:“string.h”

函数原型:char* strerror(int errnum);

1、返回错误码,所对应的错误信息

2、注意:要配合printf才能打印出错误信息。

讲解:

(1)函数的返回类型和参数:

        返回类型:char* ——字符指针,指向错误码所对应的错误信息的字符串首字符地址

        参数:int ——错误码是一些整数

(2)返回错误码,所对应的错误信息

        C语言的库函数在调用的时候,如果发生错误,就会将错误码存在一个变量中,这个变量是:errno(头文件:“errno.h”)。

        错误码是一些数字:0 1 2 3 4 5

        每一个错误码都对应一个错误信息。

代码演示:

#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;
}

        运行结果:

(3)strerror的正确使用:

        当C语言的库函数调用时发生错误,会将错误码存放在(全局)变量errno中,使用strerror可以获得错误码所对应的错误信息的字符串首地址,配合printf将错误码打印出来。

 代码示例:如打开文件失败,想知道为什么打开失败

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

int main()
{
	//打开文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//读文件
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

         运行结果:

2、perror

头文件:“stdio.h”

函数原型:void perror(const char* str);

1、直接打印错误信息,在打印错误信息前,会先打印自定义的信息。

2、可理解为:perror = printf + strerror

讲解:

(1)函数的返回类型和参数:

        返回类型:void —— 没有返回值

        参数:C字符串,包含要在错误信息本身之前打印的自定义信息。如果是NULL,则不会打印前面的自定义信息,但仍会打印错误信息。按照惯例,应用程序本身的名称通常用作参数。

(2)代码演示:如打开文件失败,想知道为什么打开失败

#include<stdio.h>

int main()
{
	//打开文件
	//‘r’——打开方式:只读(如果该文件路径下,没有该文件则读取失败)
	FILE* pf = fopen("test.txt", "r");
	//如果文件打开失败,打印失败原因
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

        运行结果:

六、字符操作

1、字符分类函数:(头文件:“ctype.h”)

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

代码演示:islower

#include<stdio.h>
#include<ctype.h>

int main()
{
	char ch = 0;
	//多组输入,判断输入值是否为小写字母
	while ((scanf("%c", &ch)) != EOF)
	{
		//islower函数判断它的参数是否为小写字母
		//是小写字母,为真返回非零的数字
		//不是小写字母,为假返回0
		printf("%d\n", islower(ch));
		//清空缓存区
		getchar();
	}
	return 0;
}

        运行结果:

2、字符转换

头文件:ctype.h

1、大写转小写

int tolower(int c);

2、小写转大写

int toupper(int c);

代码演示:

代码1:

#include<stdio.h>
#include<ctype.h>

int main()
{
	//大写字母转小写字母
	printf("%c\n", tolower('A'));
	//小写字母转大写字母
	printf("%c\n", toupper('b'));
	return 0;
}

        运行结果:

        代码2:将字符串中的小写字母转换为大写字母

#include<stdio.h>
#include<ctype.h>

int main()
{
	char arr[] = "I Have An Apple.";
	int i = 0;
	while (arr[i])
	{
		//如果为小写字母转换为大写字母
		if (islower(arr[i]))
		{
			arr[i] = toupper(arr[i]);
		}
		printf("%c", arr[i]);
		i++;
	}
	return 0;
}

        运行结果:

七、内存操作函数

        之前我们学习的库函数只能操作字符串函数,那我们要操作其他类型的数组该怎么办呢?

        答案是:内存操作函数。

1、memcpy

函数原型:void* memcpy(void* destination, const void* source, size_t num);

1、函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存空间;

2、这个函数在遇到‘\0’的时候并不会停下来;

3、如果source和destination有任何的重叠,复制的结果都是未定义的。(在VS的平台上memcpy进行了优化与memmove一样,但是不保证所有平台都进行优化)

讲解:

(1)函数的返回类型和参数:

        返回类型:void* —— 指向目标空间的起始地址

        参数:①void* dest —— 不知道是指向什么类型地址

                   ②const char* src —— 不知道是指向什么类型地址,且源指向的内容不变

                    ③size_t num —— 拷贝的字节数

(2)如果source和destination有任何的重叠,复制的结果都是未定义的。(在VS的平台上memcpy进行了优化与memmove一样,但是不保证所有平台都进行优化)

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

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//将arr1中的1,2,3,4,5拷贝到arr1+2中
	memcpy(arr1 + 2, arr1 , 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

        图示:

        (3)模拟实现memcpy

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

void* my_memcpy(void* dest, const void* src, size_t num)
{
	//断言指针的有效性
	assert(dest && src);
	//存储目标空间的起始地址
	void* ret = dest;
	//从src指向的位置拷贝num个字节的数据到dest
	//void* 不能直接使用,必须转化为确定的类型才能使用
	while (num)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
		--num;
	}
	return ret;
}

int main()
{
	int arr1[10] = { 0 };
	int arr2[10] = { 1,2,3,4,5,6,7,8 };
	//将arr2中的3,4,5,6,7拷贝到arr1中
	my_memcpy(arr1, arr2+2, 20);
	//打印arr1
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

2、memmove

函数原型:void* memmove(void* destination, const void* source, size_t num);

1、和memcpy的差别就是memmove函数处理的源内存块和目标空间内存块是可以重叠的;

2、如果源空间和目标空间出现重叠,就得使用memmove函数处理。

讲解:

(1)模拟memmove

分析:

        memmove函数是实现源指向的内容拷贝到目标空间,源空间和目标空间可以重叠。

函数体实现:(如图)

        代码演示:

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

void* my_memmove(void* dest, const void* src, size_t num)
{
	//断言指针有效性
	assert(dest && src);
	//保存目标空间的起始地址
	void* ret = dest;
	//①如果目标空间起始地址 < 源内存起始地址
	if (dest < src)
	{
		//从前向后拷贝,前 ----- 后
		while (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 arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//将arr1中的1,2,3,4,5拷贝到arr1+2中
	my_memmove(arr1 + 2, arr1 , 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

3、memcmp

函数原型:int memcmp(const void* ptr1,const void* ptr2,size_t num);

①比较从ptr1和ptr2指针开始的num个字节、

②标准规定:

        ptr1 > ptr2,返回正数

        ptr1 = ptr2,返回零

        ptr1 < ptr2,返回负数

代码演示:

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

int main()
{
	int arr1[] = { 1,2,3 };
	//VS——小端存储:低位存放低地址
	//0x:01 00 00 00 02 00 00 00 03 00 00 00
	int arr2[] = { 1,2,5 };
	//0x:01 00 00 00 02 00 00 00 05 00 00 00
	//比较整形数组,从arr1和arr2开始的9个字节
	int ret = memcmp(arr1, arr2, 9);
	printf("%d\n", ret);
	return 0;
}

        运行结果:

4、memset

函数原型:void* memset(void* ptr,int value,size_t num);

1、以字节为单位来设置内存中的数据;

2、填充内存块,将某一块内存中的内容全部设置为指定的值, 通常为新申请内存做初始化工作。

讲解:

(1)函数返回类型和参数:

        返回类型:void* ——返回ptr指向的地址

        参数:①void* ptr —— 指向要填充内存块的指针(因为不知道类型,所以设为空指针)

                   ②int value —— 要设置的值(为整形家族的值且要注意不要太大,因为是以字节为单位来填充内存的)

                   ③size_t num —— 去设置填充的字节数(因为不知道是什么类型)

代码演示:

代码1:可以使用memset把整形数组初始化为1吗

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

int main()
{
	int arr[5] = { 1,2,3,4,5 };
	memset(arr, 1, 20);
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

        运行结果:

        我们发现结果和我们预期结果不同,因为memset函数是以字节为单位来设置内存中的数据的。

        我们F10调试起来,观察arr内存

  

        代码2:

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

int main()
{
	char arr[] = "hello world";
	//将arr中的world改为yyyyy
	memset(arr + 6, 'y', 5);
	printf("%s\n", arr);
	//将arr中的hello改为xxxxx
	memset(arr, 'x', 5);
	printf("%s\n", arr);
	return 0;
}

        运行结果:

 字符串函数、内存函数就完结了,希望对大家有帮助。

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

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

相关文章

Redis(四)持久化策略

文章目录 持久化策略1、为什么Redis需要持久化2、Redis提供的两种持久化方式(1)RGB持久化详解概述RGB持久化的两种触发策略手动触发实例测试&#xff1a;自动触发实例测试&#xff1a; 查看rdb的状态信息info Persistence rdb模式的优缺点 (2)AOF持久化详解AOF持久化步骤&#…

近期复盘 | 想多了都是问题,想开了都是答案

文章目录 &#x1f339;四月坚持背单词&#xff0c;五月坚持利用AI写文章&#x1f60a;六月会坚持干什么&#x1f64c;23年7月&#xff1a;毕业两年&#xff0c;参保两年&#x1f440;强制存储&#xff0c;消费降级&#xff0c;开源节流&#x1f61c;好好深耕能力&#x1f381;…

JavaScript 进阶 (一)

目录 作用域 局部作用域 函数作用域 块作用域 全局作用域 作用域链 JS垃圾回收机制 闭包 变量提升 函数进阶 函数提升 函数参数 箭头函数 基本语法 箭头函数参数 箭头函数this 解构赋值 数组解构 对象解构 遍历数组 forEach 方法&#xff08;重点&#xff09; …

shell SNAT与DNAT

文章目录 SNATSNAT原理与应用SNAT实验 DNATDNAT原理与应用DNAT实验 SNAT SNAT原理与应用 SNAT 应用环境&#xff1a;局域网主机共享单个公网IP地址接入Internet&#xff08;私有不能早Internet中正常路由&#xff09; SNAT原理&#xff1a;修改数据包的源地址。 SNAT转换前提…

文心一言 VS 讯飞星火 VS chatgpt (23)-- 算法导论4.2 5题

五、V.Pan 发现一种方法&#xff0c;可以用 132 464 次乘法操作完成 68 x 68 的矩阵相乘&#xff0c;发现另一种方法&#xff0c;可以用 143 640 次乘法操作完成 70 x 70 的矩阵相乘&#xff0c;还发现一种方法&#xff0c;可以用155 424次乘法操作完成 72 x 72 的矩阵相乘。当…

数据安全治理科技产品能力-数据安全复合治理框架和模型解读(2)

数据治理,数据安全治理行业在发展,在实践,所以很多东西是实践出来的,哪有什么神仙理论指导,即使有也是一家之说,但为了提高企业投产比,必要的认知是必须的,落地数据安全治理科技水平差异直接决定产品和项目是否可持续性,当前和未来更需要专业和有效创新。数据安全治理…

自动驾驶业内动态简讯

1. 引言 参与自动驾驶领域相关研发工作已有多年&#xff0c;针对该领域的快速发展&#xff0c;收集业内各大科技公司最新进展和技术突破&#xff0c;供伙伴们交流探讨。 闲话少说&#xff0c;直接开始吧! 2. 博世 据新闻介绍&#xff0c;博世在德国道路上测试L4级无人驾驶汽…

java 区分缺陷Defects/感染Infections/失败Failure

java 区分缺陷Defects/感染Infections/失败Failure 缺陷Defects 软件故障总是从代码中一个或多个缺陷的执行开始。 缺陷只是一段有缺陷、不正确的代码。 缺陷可能是程序语句的一部分或完整部分&#xff0c;也可能对应于不存在但应该存在的语句。 尽管程序员要对代码中的缺陷负…

基于SSM的甜品店商城系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着社会经济的发展和…

Altium Designer 相同电路多组复制布线

在进行设计开发的时候&#xff0c;总会遇到相同的电路&#xff0c;或者模块&#xff0c;这些电路可以使用相同的布局和走线。我们可以画好其中一部分&#xff0c;然后直接复制&#xff0c;就可以提高效率。下面记录我自己的实际操作过程&#xff0c;有一些地方遇到了问题&#…

Android | Android OS 源码结构

参考&#xff1a;AndroidXRef (http://androidxref.com/)版本&#xff1a;Pie - 9.0.0_r3 整体结构 对于 Android OS 的源码目录来说&#xff0c;各个版本的结构大同小异&#xff0c;随不同版本特性会有个别目录差异。编译后会额外产生一个 out 文件夹用于存储编译产生的文件。…

Unity使用SteamVR2.0实现基本功能(瞬移,抓取物品,射线点击,UI交互等)

基础设置 把SteamVR的Player预制件拖到一个空场景,删掉场景内原本的相机 一.瞬移 新建一个Plane,当做地板找到SteamVR的人物瞬移控制器 Teleporting ,把它拖到场景里 1. 范围移动 我们需要在可以移动的区域,也就是碰撞器上,挂TeleportArea脚本 这个脚本会自动修改你的材质球…

抖音seo源码--开源,支持二开不加密

抖音seo源码&#xff0c;抖音seo矩阵系统源码技术搭建&#xff0c;抖音seo源码技术开发思路梳理搭建 开发思路&#xff1a; 抖音seo源码如何搭建&#xff1f;抖音seo排名优化系统软件部分源码分析&#xff0c;代码打包中。。。 场景&#xff1a;在 python 中&#xff0c;你可…

windows下修改PyCharm默认terminal 在Git Bash中使用conda

windows下修改PyCharm默认terminal & 在Git Bash中使用conda windows下修改PyCharm默认terminal在Git Bash中使用conda windows下修改PyCharm默认terminal PyCharm的terminal默认使用的是powershell&#xff0c;但是conda环境是通过cmd运行的&#xff0c;因此可以将PyChar…

安捷伦N5182A是德KEYSIGHT N5182B 100KHZ至3G/6G信号发生器

Agilent N5182A、Keysight N5182A MXG 射频矢量信号发生器&#xff0c;100 kHz - 3 GHz 或 6 GHz ​Keysight N5182A (Agilent) MXG 射频矢量信号发生器具有快速频率、幅度和波形切换、带电子衰减器的高功率和高可靠性 – 所有这些都集成在两个机架单元 (2RU) 中。Keysight N5…

H743 USBHOST协议栈 CPU占用率高的问题。

经过查看&#xff0c;是因为USBHOST频繁的进入中断导致&#xff0c;单步执行发现&#xff0c;是因为发生了USB_OTG_HCINT_CHH或者USB_OTG_HCINT_NAK中断了&#xff0c;只在CHH中断服务函数里&#xff0c;给USB主线程发了1个消息&#xff0c;又引起了USBH_Process_OS主线程的频繁…

YOLOV7训练TT100K交通标识符数据集

《临江仙》 作者&#xff1a;缠中说禅 浊水倾波三万里&#xff0c;愀然独坐孤峰。龙潜狮睡候飙风。无情皆竖子&#xff0c;有泪亦英雄。 长剑倚天星斗烂&#xff0c;古今过眼成空。乾坤俯仰任穷通。半轮沧海上&#xff0c;一苇大江东。 一、yolov7环境搭建 参…

【内网穿透】远程访问RabbitMQ服务

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 转载自cpolar内网穿透的文章&#xff1a;无公网IP&…

【C语言】刷题训练营 —— 每日一练

文章目录 前言 BC113 小乐乐定闹钟BC114 小乐乐排电梯BC115 小乐乐与欧几里得BC116 小乐乐改数字BC107 矩阵转置BC117 小乐乐走台阶BC118 小乐乐与序列BC119 小乐乐与字符串BC121 小乐乐学编程BC122 小乐乐算平均分完结 前言 大家好&#xff0c;继续更新专栏 c_牛客&#xff0…

【C++】二叉搜索树Binary Search Tree

Binary Search Tree 二叉搜索树的概念二叉搜索树的操作二叉搜索树的实现查找插入删除 二叉搜索树的应用二叉搜索树的性能分析 二叉搜索树的概念 二叉搜索树又被称为二叉排序树&#xff0c;顾名思义&#xff0c;当我们使用中序遍历时&#xff0c;会得到一个有序的序列。二叉搜索…