C语言复习第9章 字符串/字符/内存函数

目录

  • 一、字符串函数
    • 1.1 读取字符串gets
      • 函数原型
      • Example
    • 1.2 字符串拷贝strcpy
      • 函数原型
      • 模拟实现
      • 官方源码
    • 1.3 求字符串长度strlen
      • 函数原型
      • 关于返回值size_与算术转换的一个易错点
      • 模拟实现:递归
      • 模拟实现:指针-指针
      • 模拟实现:暴力
      • 官方源码
    • 1.4 字符串追加strcat
      • 函数原型
      • 注意自己给自己追加的bug
      • 模拟实现
    • 1.5 字符串比较strcmp
      • 函数原型
      • 返回值的含义
      • 模拟实现
    • 1.6 长度受限制的字符串函数
      • 上述函数的问题
      • strncpy
      • strncat
      • strncmp
    • 1.7 判断是否为子串strstr
      • 函数原型
      • 模拟实现
      • 官方源码
    • 1.8 字符串分割strtock
      • 函数原型
      • 正确的打开方式
    • 1.9 返回错误码所对应的错误信息strerror
      • 函数原型
      • perror更佳(stdio.h)
  • 二、字符函数
    • 2.1 字符分类函数(ctype.h)
    • 2.2 字符转换(ctype.h)
  • 三、内存函数
    • 3.1 memcpy
      • 函数原型
      • 模拟实现
      • 自己给拷贝给自己的一个问题
    • 3.2 memmove
      • 函数原型
      • 模拟实现
    • 3.3 memcmp
    • 3.4 memset

一、字符串函数

1.1 读取字符串gets

函数原型

char * gets ( char * str )

从标准输入读取字符 直到遇到换行字符或文件结束符
如果找到换行字符 则不将其复制到str中
在将字符复制到str后 会自动添加终止字符
请注意 gets与fgets完全不同:
gets不仅使用标准输入作为源 而且不将结束换行符的字符包含在生成的字符串中 也不允许指定str的最大大小(这可能导致缓冲区溢出)
在这里插入图片描述

简单来说gets就是读取一个字符串 包括空格也读取 遇到\n或EOF就不读了
读到的内容给参数str
在这里插入图片描述
在这里插入图片描述

Example

在这里插入图片描述

1.2 字符串拷贝strcpy

函数原型

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

  • 参数2拷贝给参数2 包括第一个\0
  • 第一个\0也作为拷贝停止的标记
  • 参数1要足够大 以放得下参数2
  • 参数2一定要有结束标志\0 否则会出bug
  • 返回的是参数1 也就是拷贝完之后的首字符地址
  • 参数1必须是可修改的字符串 不可以是常量字符串(不能被修改)

在这里插入图片描述

常量字符串无法被修改 这里的*p用const修饰是比较合理的
在这里插入图片描述

模拟实现

我的思路:
注意由于要返回destination 但是下面又改变了destination 所以需要暂存destination
擅于使用const(避免运行了才出错 直接编译不通过)

#define _CRT_SECURE_NO_WARNINGS 1

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

char* myStrcpy(char* destination,const char* source)
{
	assert(destination != NULL && source != NULL);
	assert(strlen(destination) >= strlen(source));

	char* ReturnValue = destination;
	//最后一次循环肯定是把第一个\0拷贝给destination了
	while (*destination = *source)
	{
		destination++;
		source++;
	}

	return ReturnValue;
}

int main()
{
	char ch1[] = "XXXXXXXXXXXXXXXXXXXXXXXXX";//big enough
	const char ch2[] = "zc231313y\0zcy";//只拷贝到第一个\0
	printf("%s\n", ch1);

	printf("%s\n", myStrcpy(ch1, ch2));
	printf("%s\n", ch1);
	return 0;
}


我的思路可以简化成下图:
可以但没必要啊!
在这里插入图片描述


另一种写法:
这种写法必须要注意 要单独拷贝一下’\0’

char* myStrcp(char* destination, const char* source)
{
	//返回值是destination的值(形参) 所以需要形参的值放起来
	char* des = destination;
	char* src = source;

	while (*src != '\0')
	{
		*des = *src;
		des++;
		src++;
	}
	//上面这种循环 当src指向\0的时候 不会进来 所以需要手动实现
	*des = '\0';  //or  *des = *src;
	return destination;//这样返回的 就是原来的形参 其实也就是ch1的首地址
}
int main()
{
	char ch1[] = "**************";
	char ch2[] = "zcygst";
	printf("qian:%s\n", ch1);

	myStrcp(ch1, ch2);
	printf("hou:%s\n", ch1);
    //或者 	printf("hou:%s\n", myStrcp(ch1, ch2));
    //这就是链式访问
    //%s就是从某个起始地址 一直打印到\0
    
	return 0;
}

官方源码

在这里插入图片描述

1.3 求字符串长度strlen

函数原型

size_t strlen ( const char * str )

  • 第一次\0出现之前的字符个数 字符串的结束标志就是’\0’
  • 返回值是size_t(unsigned int) 因为字符串长度肯定不可能是负数
  • typedf unsigned int size_t

在这里插入图片描述

关于返回值size_与算术转换的一个易错点

  • 算术转换(>=int) 就高不就低
    size_t减去size_t 得到的东西肯定也是size_t
  • -3被理解成unsigned int 反正肯定不可能<0 所以会进入if 打印hehe

在这里插入图片描述

模拟实现:递归

注意不要忘记写else的return 0
如果传参的时候写++ 那必须是++s s++会导致死递归
下面三种代码 严格来说 返回值都应该是size_t
在这里插入图片描述

模拟实现:指针-指针

指针-指针=指针之间的元素个数(希望求\0和首字符之间的元素个数)
在这里插入图片描述

模拟实现:暴力

不是\0就++
返回值应该是size_t或者unsigned int
count也最好定义成unsigned int 和返回值保持一致
在这里插入图片描述

官方源码

居然是我认为可读性较差的写法!
不过可能这个源码本来就不是给人读的
因为最后一次解引用发现是\0 之后又++了一次
所以最终eos指向\0下一个字符 返回的时候需要再-1
在这里插入图片描述

1.4 字符串追加strcat

函数原型

char * strcat ( char * destination, const char * source )
和strcpy非常相似

● arr目标空间要足够大 确保能放得下追加的结果
● 目标字符串要有\0 表示追加的起始位置
● 被追加的字符串也要有\0 表示追加的停止位置
● 两者都要有\0作为结束标志 因为两者都是字符串
● 目标字符串的\0会被覆盖
在这里插入图片描述

注意自己给自己追加的bug

由于追加的时候 会把自己的/0给覆盖 就找不到追加结束的时机了
所以自己给自己追加的时候 不要用strcat函数
在这里插入图片描述

在这里插入图片描述

模拟实现

一个易错点:
在这里插入图片描述

参考代码:

char* my_strcat(char* des, const char* sour)
{
	assert(des != NULL);
	assert(sour != NULL);
	
	//需要返回目标空间的起始地址
	char* ReturnVal = des;
	//des指向第一个\0 追加的字符由此开始覆盖
	des = des + strlen(des);
	//追加字符
	while (*sour)
	{
		*des = *sour;
		des++;
		sour++;
	}
	//上述循环并不会拼接\0 所以需要手动拼接
	*des = *sour;

	return ReturnVal;
}

int main()
{
	char ch[20] = "abcab\0cabc";
	my_strcat(ch, "zc\0yyy");
	printf("%s", ch);
	return 0;
}

其他写法:
在这里插入图片描述

1.5 字符串比较strcmp

函数原型

int strcmp ( const char * str1, const char * str2 )
在这里插入图片描述

返回值的含义

不关心字符串长度的
在这里插入图片描述

模拟实现

思路:
从首地址开始 一对一对字符作比较 相等就找下一对继续比较
但是注意::每次找下一对比较之前 必须看看上一对是不是\0 == \0
如果已经比较到\0 == \0 那就算字符串相等了 return 0即可
因为 \0就是字符串结束标志
也许\0后面还有字符 但是在strcmp眼里 字符串已经到头了 不关心后面的内容

参考代码:

int my_strcmp2(const char* ch1,const char* ch2)
{
	assert(ch1 && ch2);
	while (*ch1 == *ch2)
	{
		if (*ch1 == '\0')
		{
			//或者ch2 == \0  因为ch1 = ch2
			return 0;//能走到这 说明字符串完全一样
		}
		ch1++;
		ch2++;
	}
	//能走到这 说明*ch1 != *ch2
	return *ch1 - *ch2;//这里的返回值 也是符合strcmp的函数原型的
}

int my_strcmp1(const char* s1, const char* s2)
{
	assert(s1 != NULL);
	assert(s2 != NULL);
	//一对一对比较 ==就往后找
	while (*s1 == *s2)
	{
		//每次一进来先判断当前的==是不是由于\0==\0导致的
		//因为即使是"zcy\0asdasdads"
		//在strcmp眼里也只有zcy\0 第一个\0就是字符串的结束标志了
		if (*s2 == '\0')
			return 0;
		s1++;
		s2++;
	}

	//执行到这 说明*s1 != *s2已经出现了
	//字符串肯定不是相等的  再判断是>0还是<0就行了
	if (*s1 > *s2)
		return 1;
	else
		return -1;
}

1.6 长度受限制的字符串函数

上述函数的问题

strcat strcmp strcpy 都是一股脑找到\0才停下
长度不受限制 其实是很不安全的
比如说strcpy
它并不关心能不能放得下 反正目标是拷贝到\0
在这里插入图片描述

为了解决这些问题 引入了长度受限制的字符串函数: strncpy strncat strncmp
多了第三个参数 n 即需要操作的字符的个数
在这里插入图片描述

strncpy

char *strncpy( char *strDest, const char *strSource, size_t count )

如果够三个 那就拷贝abc 不会自己加\0
如果不够 那就补\0 缺几个补几个

在这里插入图片描述

在这里插入图片描述

strncat

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

字面常量"defqwer" 其实本质是d的地址 从起始地址开始 往后追加4个 然后再补一个\0
因为追加完 肯定还是一个字符串 那就需要一个\0
当然如果不够4个 那追加到\0就停止了
从参数2往后n个字符的过程 遇到\0 就提前终止
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

strncmp

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

比较arr1前四个和arr2前四个
即比较abcd和abcz
在这里插入图片描述

1.7 判断是否为子串strstr

函数原型

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

可能有多个子串 但只返回第一个子串的首地址
找不到 返回NULL
在这里插入图片描述
在这里插入图片描述

模拟实现

暴力法思路:
比如ABBBBCD和BCD
首先str1 和 str2 记录当前判断字符串的起始位置
tmp1 和 tmp2 真正的进行判断 同时都会++ 一对一对比较
每次比较完得出结果 都会更新str2的值(其实就是++) 然后把新的str赋给tmp
str2不会变 str1会+1+1+1+1…直到strlen(tmp1) >= strlen(tmp2)
比较思路:
如果*tmp1 = *tmp2了 而且*(tmp2 + 1) == '\0' 这就说明已经匹配成功
如果匹配失败 则需要让tmp2重回起点(即str2) 同时让tmp1指向str1的下一位
在这里插入图片描述

参考代码:

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);

	const char* tmp1 = str1;
	const char* tmp2 = str2;
	//空串不做匹配
	assert((*str1 != '\0') && (*str2 != '\0'));

	while (strlen(tmp1) >= strlen(tmp2))
	{
		//比较当前tmp1和2锁定的字符串
		while (*tmp2 == *tmp1)
		{
			if (*(tmp2 + 1) == '\0')
				return (char*)str1;
			tmp2++;
			tmp1++;
		}
		//上一对匹配失败 寻找下一对(或者说这个str1不是匹配的起点 继续找下一个)
		str1++;
		
		//更新下标 重新开始匹配
		tmp1 = str1;
		tmp2 = str2;
	}

	return NULL;
}
	

int main()
{
	//char arr1[] = "hello world";
	//char arr2[] = "world";	
	char arr1[] = "abbbcdefbbc";
	char arr2[] = "bbc";
	char* p = my_strstr(arr1, arr2);
	if (p == NULL)//找不到返回的是空指针
	{
		printf("找不到\n");
	}
	else
	{
		printf("%s", p);//good,haha,good
	}
	return 0;
}

官方源码

思路:
cp在一个一个往后找(不用cp也行 可能是为了不改变形参的值 更规范)
然后cp找到的字符串和s2匹配
和我不同的是 它认为如果str2是空串 那直接返回str1的首地址 即空串是任何串的子串
这样理解确实更合理

下面匹配的思路跟我也有所不同
我认为调用strlen是节省开销 但是仔细一想好像不一定啊!
下图的思路就是如果*s1 == *s2 并且 s2还没有指向\0 那么s1 s2就成对的往前走 继续比较下一个字符
如果有一天内存while结束了 有可能是:
1.*s2指向\0了 那就说明上一对比较的s1 s2就是最后一对了 已经匹配成功
2.*s1 != *s2了 这种情况 就说明当前cp开始匹配的字符串就不是子串了 那就需要cp++继续下一对
3.外存循环的条件是cp没有指向\0 如果有一天能出了外存循环 就说明一直到cp指向\0 还没执行过return (cp) 那就不可能找到了 所以返回NULL
在这里插入图片描述

1.8 字符串分割strtock

函数原型

char * strtok ( char * str, const char * delimiters )

sep参数是个字符串 定义了用作分隔符的字符集合
第一个参数指定一个字符串 它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
strtok函数找到str中的下一个标记 并将其用 \0 结尾 返回一个指向这个标记的指针:下图就会找到第一个. 然后改成\0 并返回z的地址 这个时候用%s打印就是zcyxd
在这里插入图片描述

注:
strtok函数会改变被操作的字符串 所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改
第一次调用传参没有传NULL:找到第一个分隔符 改为\0 并记住了这个位置
第二次调用传参传的是NULL:记住了第一次\0的位置 从下一个字符串开始再找分隔符 上图就是从\0往后找 找到一个foxmail 然后把第二个.换成\n 同时返回f的地址 并记录这次\0的位置
第2+n次调用传参传的都是NULL: 都会重复上述动作 直到找不到分隔符了 那就开始返回NULL
\0不能作为分隔符 都说了是字符串!! 字符串的结束标志就是\0!!
在这里插入图片描述
在这里插入图片描述

正确的打开方式

这个函数仿佛有记忆功能
所以猜测里面应该有一个static静态变量
要不然每次调用 函数栈帧都会销毁的

一开始就传参arr2 且只需要调用一次
之后每次都用NULL作为参数 调用一次打印一次 直到返回值是NULL
每次都会拿到一个子串的首地址
打印 或者是拷贝到别的地方 就看具体需求了在这里插入图片描述

1.9 返回错误码所对应的错误信息strerror

函数原型

char * strerror ( int errnum )
在这里插入图片描述
在这里插入图片描述

● 文件如果打开失败 fopen()会把错误码放到全局变量errno(errno.h) 里面去

● 返回NULL就说明打开失败了 strerror就能把错误码转换成错误信息 可以得知为什么打开失败了
在这里插入图片描述
这样写只知道打开失败了 但是 不知道为什么
在这里插入图片描述

perror更佳(stdio.h)

在这里插入图片描述

它会自己主动去捕获errno的错误码
perror的头文件是:stdio.h
strerror只是获得错误信息的起始地址 不会打印
perror拿到错误信息 会直接打印出错误信息
在这里插入图片描述

二、字符函数

2.1 字符分类函数(ctype.h)

函数:如果他的参数符合下列条件就返回真(非0)

常用:
isdigit:十进制数字 0~9
islower:小写字母a~z
isupper:大写字母A~Z
isalpha:字母a-z或A-Z
isalnum:字母或者数字 a-z或A-Z或0-9

了解:
isxdigit:是不是十六进制数字 包括所有十进制数字,小写字母a-f,大写字母A-F
ispunct:标点符号 任何不属于数字或者字母的图形字符
isgraph:任何图形字符
isprint:任何可打印字符 包括图形字符和空白字符
iscntrl:任何控制字符
iscntrl:任何控制字符

判断是不是小写 不是就返回0 否则是非0
在这里插入图片描述

2.2 字符转换(ctype.h)

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

可以看出 都是值传递
所以只会返回当前字母对应的大小写字母的码值
不会直接修改当前字母
在这里插入图片描述

三、内存函数

3.1 memcpy

函数原型

void * memcpy ( void * destination, const void * source, size_t num )
在这里插入图片描述

● strcpy只能拷贝字符串 如果我想拷贝其他类型的呢?
● 拷贝12345 --一共20个字节

在这里插入图片描述
● 指针变量的一个优势
在这里插入图片描述

模拟实现

写法1:

void* my_memcpy(void* destination, const void* source, size_t num)
{
	char* start1 = (char*)destination;
	char* start2 = (char*)source;

	for (int i = 0; i < num; i++)
	{
		*start1 = *start2;
		start1++;
		start2++;
	}

	//返回目标des的地址(初始状态的)
	return destination;
}

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

写法2:
有一个注意点
这种写法是临时的强转 dest++的时候
dest的类型仍然是void* 是不可以++的
在这里插入图片描述
在这里插入图片描述

这样才对 前置对 后置不对
在这里插入图片描述
在这里插入图片描述

自己给拷贝给自己的一个问题

● 这里实际上拷贝的是1 2 1 2 1
内存重叠-->memmove
在这里插入图片描述

3.2 memmove

函数原型

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

memmove已经包含了memcpy的功能
但是他能实现重叠内存的拷贝

但是实际上:
C语言对memcpy的要求只有60分
但是 在VS里 VS对memcpy的实现有一百昏!
所以在VS里用memcpy 并不会出现3.1的问题
在这里插入图片描述

模拟实现

需要分情况讨论:

  1. 如果dest在src的左边 从src开始 按顺序从左往右拷贝给dest即可
    在这里插入图片描述
  2. 如果dest在src的右边 从src最右边的7开始 从dest最右边开始 从右往左把src的值拷贝给dest
    在这里插入图片描述
  3. 总结 其实右三种可能
    即dest在src的左边:前–>后
    dest在src之间:后–>前
    deest在src末尾的右边–>不重叠 无所谓

在这里插入图片描述
4. 注意要么dest和src都从右 要么都从左

参考代码:无所谓的时候选后-->前 选src作为分界处

void* my_memmove(void* des, const void* src, size_t num)
{
	assert(des && src);
	char* src2 = (char*)src;
	char* des2 = (char*)des;

	//目标地址在src左边 从低到高拷贝(从前到后)
	if (des < src)
	{
		for (int i = 0; i < num; i++)
		{
			*des2 = *src2;
			des2++;
			src2++;
		}
	}

	//这里des==src的情况 其实可以直接不拷贝
	//否则从高到到低拷贝(从后到前) 
	else
	{
		for (int i = num - 1; i >= 0; i--)
		{
			*(des2 + i) = *(src2 + i);
		}
	}

	return des;
}

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr1 + 2, arr1, 20);
	return 0;
}

另一种写法:
如果是写给别人看的 比如考试 建议用for
如果只是实现一个函数给别人用 这个也好
在这里插入图片描述

3.3 memcmp

int memcmp ( const void * ptr1, const void * ptr2, size_t num )
在这里插入图片描述

一个字节一个字节比较(其实大小端的比较结果都是一样的) 当==的时候 继续往下比较
在这里插入图片描述

3.4 memset

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

字节为单位 来设置内存中的数据

在这里插入图片描述
在这里插入图片描述

这是按照字节处理的 1写成俩16进制位就是01
但是数组元素每个都是4字节 是01010101对应的十进制
在这里插入图片描述
在这里插入图片描述

注意第二个参数是int char也属于整型家族
在这里插入图片描述

一般memset这么用 把每个字节都改成0
每个字节都变成0 相当于每个元素都是0在这里插入图片描述

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

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

相关文章

使用Matlab神经网络工具箱

综述 在大数据和人工智能时代&#xff0c;神经网络是一种最为常见的数据分析和拟合工具。本报告以常用分析软件Matlab为例&#xff0c;介绍其中神经网络工具箱使用方法。 Step 1: 打开matlab 安装matlab 2018以上版本后&#xff0c;双击图标打开。 Step 2: 打开神经网络拟合…

ffmpeg视频滤镜:组合两个视频为立体视频- framepack

视频描述 framepack 官方网址 > FFmpeg Filters Documentation 这个滤镜会将两个视频进行组合&#xff0c;有个前提是这两个视频的帧率、分别率必须一样。比如输入的是两个852x480 视频&#xff0c;输出可能是1704*480&#xff08;左右拼接&#xff09;、852*960&#xf…

Spring Security 框架篇-深入了解 Spring Security 的授权核心功能(RBAC 权限模型、自定义异常处理器、校验权限方法)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 权限系统 1.1 引入 1.2 RBAC 权限模型 1.3 数据库设计 2.0 Spring Security 核心功能-授权 2.1 思路分析 2.2 编写 SQL 语句 2.3 将用户权限进行封装 2.4 获取用户…

STM32G0xx使用LL库将Flash页分块方式存储数据实现一次擦除可多次写入

STM32G0xx使用LL库将Flash页分块方式存储数据实现一次擦除可多次写入 参考例程例程说明一、存储到Flash中的数据二、Flash最底层操作(解锁&#xff0c;加锁&#xff0c;擦除&#xff0c;读写)三、从Flash块中读取数据五、测试验证 参考例程 STM32G0xx HAL和LL库Flash读写擦除操…

Spark SQL大数据分析快速上手-DataFrame应用体验

【图书介绍】《Spark SQL大数据分析快速上手》-CSDN博客 《Spark SQL大数据分析快速上手》【摘要 书评 试读】- 京东图书 大数据与数据分析_夏天又到了的博客-CSDN博客 本节主要介绍如何使用DataFrame进行编程。 4.1.1 SparkSession 在旧版本中&#xff0c;Spark SQL提供…

QT信号和槽与自定义的信号和槽

QT信号和槽与自定义的信号和槽 1.概述 这篇文章介绍下QT信号和槽的入门知识&#xff0c;通过一个案例介绍如何创建信号和槽&#xff0c;并调用他们。 2.信号和槽使用 下面通过点击按钮关闭窗口的案例介绍如何使用信号和槽。 创建按钮 在widget.cpp文件中创建按钮代码如下 …

YOLO11改进 | 融合改进 | C3k2融合 Context Anchor Attention 【两个版本融合-独家创新】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 本文给大家带来的教程是将YOLO11的C3k2替…

机械制造工控自动化监控界面:功能与美观兼具

机械制造工控自动化监控界面需做到功能与美观兼具。在功能方面&#xff0c;清晰展示设备运行状态、参数指标等关键信息&#xff0c;提供实时监控和预警功能&#xff0c;确保生产安全高效。 界面布局应合理&#xff0c;操作简便&#xff0c;便于工作人员快速掌握和操作。而在美…

SpringBoot项目集成ONLYOFFICE

ONLYOFFICE 文档8.2版本已发布&#xff1a;PDF 协作编辑、改进界面、性能优化、表格中的 RTL 支持等更新 文章目录 前言ONLYOFFICE 产品简介功能与特点Spring Boot 项目中集成 OnlyOffice1. 环境准备2. 部署OnlyOffice Document Server3. 配置Spring Boot项目4. 实现文档编辑功…

explain执行计划分析 ref_

这里写目录标题 什么是ExplainExplain命令扩展explain extendedexplain partitions 两点重要提示本文示例使用的数据库表Explain命令(关键字)explain简单示例explain结果列说明【id列】【select_type列】【table列】【type列】 【possible_keys列】【key列】【key_len列】【ref…

AIDOVECL数据集:包含超过15000张AI生成的车辆图像数据集,目的解决旨在解决眼水平分类和定位问题。

2024-11-01&#xff0c;由伊利诺伊大学厄巴纳-香槟分校的研究团队创建的AIDOVECL数据集&#xff0c;通过AI生成的车辆图像&#xff0c;显著减少了手动标注工作&#xff0c;为自动驾驶、城市规划和环境监测等领域提供了丰富的眼水平车辆图像资源。 数据集地址&#xff1a;AIDOV…

24/11/7 算法笔记 PCA主成分分析

假如我们的数据集是n维的&#xff0c;共有m个数据(x,x,...,x)。我们希望将这m个数据的维度从n维降到k维&#xff0c;希望这m个k维的数据集尽可能的代表原始数据集。我们知道数据从n维降到k维肯定会有损失&#xff0c;但是我们希望损失尽可能的小。那么如何让这k维的数据尽可能表…

2-142【软件无线电原理与应用作业】基于matlab的圆形阵列的波束形成进行仿真

【软件无线电原理与应用作业】基于matlab的圆形阵列的波束形成进行仿真&#xff0c;具有14页文档。假设发射信号载频为1GHz&#xff0c;圆形阵列半径为0.8米&#xff0c;在圆周上均匀布置30个阵元。1.画出指向0度的方向图。2.如果目标在0度&#xff0c;有一不相干的干扰信号在3…

<项目代码>YOLOv8 苹果腐烂识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…

python练习相关代码

一元二次方程的求根公式为&#xff1a; import mathdef quadratic(a, b, c):discriminant b**2 - 4*a*cif discriminant < 0:return Noneelif discriminant 0:return [-b / (2*a)]else:root1 (-b math.sqrt(discriminant)) / (2*a)root2 (-b - math.sqrt(discriminant)…

2024软件测试面试热点问题

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 大厂面试热点问题 1、测试人员需要何时参加需求分析&#xff1f; 如果条件循序 原则上来说 是越早介入需求分析越好 因为测试人员对需求理解越深刻 对测试工…

windows、linux安装jmeter及设置中文显示

系列文章目录 1.windows、linux安装jmeter及设置中文显示 2.jmeter常用配置元件介绍总结之安装插件 3.jmeter常用配置元件介绍总结之取样器 windows、linux安装jmeter及设置中文显示 前言一、jdk安装1.windows安装jdk1.1.复制环境变量快捷跳转 2.linux安装jdk 二、下载安装jmet…

各种数据库介绍

1. 关系型数据库&#xff08;RDBMS&#xff09; MySQL • 特点&#xff1a;开源、免费&#xff0c;社区版功能强大且稳定。支持大量的并发连接&#xff0c;常用于Web应用。 • 适用场景&#xff1a;中小型网站、博客、电商等。 PostgreSQL • 特点&#xff1a;功能丰富&#xf…

【linux】查看不同网络命名空间的端口

在部署harbor时&#xff0c;内部用的是数据库postgresql&#xff0c;端口默认是: 5432&#xff0c;一开始以为这个数据库docker容器是在本命名空间中&#xff0c;一直用ss -lnt查询系统的端口&#xff0c;找不到5432端口。但是harbor要能正常使用&#xff0c;所有怀疑harbor的容…

使用ffmpeg和mediamtx模拟多通道rtsp相机

首先下载ffmpeg&#xff0c;在windows系统上直接下载可执行文件&#xff0c;并配置环境变量即可在命令行当中调用执行。 下载地址&#xff1a; https://ffmpeg.org/再在github上下载mediamtx搭建rtsp服务器&#xff0c;使用ffmpeg将码流推流到rtsp服务器。 下载地址&#xff1…