字符串函数和内存函数

news2025/1/17 0:53:22

在c语言中,有非常多的库函数,比如我们经常使用的scanf和printf,除此之外,还有一些非常实用的函数,比如我们之前使用的qsort排序函数,可以对任意数据类型进行排序,strlen函数,可以计算字符串的长度,这次,我们就来了解一些和字符串以及内存相关的函数,掌握了这些函数,可以让我们在写代码时变得非常方便

目录

1.字符串函数

1.1strlen

1.2.strcpy

1.3.strcat 

1.4.strcmp

1.5.strncpy

1.6.strncat

1.7.strncmp

1.8.strstr

1.9.strtok

1.10.strerror

1.11.字符分类函数

1.12.字符转换函数

2.内存函数

2.1.memcpy

2.2memmove

2.3.memcmp

2.4.memset


1.字符串函数

1.1strlen

strlen函数是用来求字符串长度的,在我们日常写代码里也经常使用,我们之前也模拟写过strlen函数,有三种方法实现,我们先来看看这三种方法的区别

int my_strlen1(const char* str) {
	assert(str != NULL);
	int count = 0;
	while (*str != '\0') {
		count++;
		str++;
	}
	return count;
}

这种实现方法非常简单,就是遍历一遍字符串,数个数,就不多介绍

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

第二种方法就是使用递归,如果当前位置不为\0,就返回1+strlen(下一个位置),为\0时返回0即可

int my_strlen3(const char* str) {
	const char* start = str;
	assert(str != NULL);
	while (*str) {
		str++;
	}
	return str - start;
}

第三种方法就是指针减指针了,指针减指针是两个地址之间的元素个数

大家会发现,我们的三种方法,返回值类型都是int,我们看看库里边的实现是什么

我们可以看到,库里边的返回值类型为size_t,size_t是无符号整形,strlen是求字符串长度,求出的长度是不可能为负数,所以使用了size_t,不过这也有利有弊,我们看个例子

 

我们发现,这是一个非常诡异的现象,明明abc比abcdef要短,为什么会输出>呢? 

这是因为3-6=-3,但是strlen函数返回值为size_t,两个无符号数相减也会被当做一个无符号数,而-3看做无符号数时,是一个非常大的正数,所以是大于0的,但如果这里是int,就不会出现这种问题,但是库函数这么选择,也有他的道理,我们在设计函数时,要想清楚他应用的场景,要想清楚这些关系,不要一味的追求哪一种更好,要分析清楚利害关系

我们来看看strlen的一些细节

字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )
参数指向的字符串必须要以 '\0' 结束。
注意函数的返回值为size_t,是无符号的

1.2.strcpy

strcpy也是我们熟悉的一个函数,是字符串拷贝,我们来看看他的一些细节

我们可以看到,用strcpy拷贝字符串时,会把arr2里的\0也拷贝到arr1里

 

当我们提前放入\0时,字符串拷贝也会提前停止,并不会将\0之后的内容也拷贝进去

 

使用strcpy函数必须保证目标空间足够大

 

 当我们把字符串拷贝到指针时程序也会发生崩溃,这是因为p所指向的字符串是常量字符串,常量是不能被修改的,我们必须保证目标是可修改的,所以我们使用的是数组

我们来看看strcpy的库函数

接着我们来模拟实现strcpy

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

dest代表目标空间,src代表原空间,因为我们要把src拷贝到dest里,所以我们不需要改变src,于是我们加上const,断言可以帮助我们判断是否为空,接着就是进行拷贝,拷贝完后,因为dest的起始位置发生变化,所以我们需要一个变量来记录dest的起始位置,然后我们把他返回即可

我们来总结一下strcpy的细节

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

1.3.strcat 

strcat可能就有人不知道了,这是字符串连接函数,我们先看看他的使用

 strcat可以把arr2的内容拼接到arr1之后,我们来看看他的库函数

strcat的参数和返回类型,和strcpy是一样的 ,都是将原数据xx到目标数据xx,我们来看strcat的细节

strcat的拼接,是将原字符串从目标字符的\0开始替换,然后将剩余的拼接上去

源字符串必须以 '\0' 结束

目标空间必须足够大,能容纳下源字符串的内容

目标空间必须得有\0

目标空间必须可修改

 接着我们来模拟实现strcat

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

我们要将src连接到dest后面,src不需要修改,所以加上const,我们先要找到dest的末尾,也就是\0的位置,所以第一个while就是找到末尾,第二个while就是追加,我们还需要一个变量来记录dest的起始位置,然后返回即可,如果dest里有多个\0,我们会在遇到的第一个\0开始进行追加

另外,我们是可以将字符串常量连接到数组后的

1.4.strcmp

strcmp是字符串比较,我们先来看他的库函数说明

 

strcmp会对两个字符串进行比较,如果相等返回0,第一个大于第二个会返回>0的数,小于的话返回<0的数,我们来看个例子

 

a和a是相等,b和b相等,q大于c,所以arr1是<arr2的,会输出<

 在vs环境下,会返回的数为1,0,-1,但不是所有的环境下返回值都是这样的

知道了这些,我们来模拟实现一下strcmp

int my_strcmp(const char* str1,const char* str2) {
	assert(str1 && str2);
	while (*str1 == *str2) {
		if (*str1 == '\0') {
			return 0;
		}
		str1++;
		str2++;
	}
	if (*str1 > *str2) {
		return 1;
	}
	else {
		return -1;
	}
}

因为是字符串比较,两个字符串都不用修改,所以我们加上const,while循环,我们用来判断str1和str2是否相等,当他俩一值相等的情况下,走到\0的位置,说明这两个字符串相等,我们返回0,如果中途有不相等的情况,会跳出循环,接着我们根据大小返回1或者-1即可

因为是这个函数并没有规定一定要返回1和-1,所以我们可以把if else语句改为

return *str1 - *str2;

在有些编译器里,就是这样做的,切记返回值是大于0的数,小于0的数和0,而不是1,0,-1

我们上面介绍的这些函数,都是长度不受限制的字符串函数,比如字符串拷贝,他会把第二个参数全部拷贝到第一个参数里,一值到\0为止,而因为这个原因,这些函数会让人感觉不安全,比如目标空间不够大时,他们也会继续执行

所以我们接下来介绍长度受限制的字符串函数

1.5.strncpy

我们来看strncpy,是strcpy的升级版,我们先来看他的库函数

 strncpy相比strcpy多了一个参数,是我们要拷贝几个字符,我们来看例子

 我们发现,我们指定几个字符,strncpy就拷贝几个字符,我们的拷贝完hello后,并没有在hello后加上\0

 我们的arr2只有五个字符,但我们指定10的话,不够的位置会补\0

1.6.strncat

同样的,strncat就是strcat的升级版,也是多了一个参数

 我们来看例子

 我们发现,在第二个图片里,在追加时,在追加结束后,会在后边加上\0

1.7.strncmp

和前面两个一样,strncmp是strcmp的升级版,多了一个参数

我们来看例子

 这个函数是比较简单的

1.8.strstr

接着我们来介绍一个特殊的函数,strstr是查找子串函数,我们先来看看他的库函数

 strstr是在第一个str里找第二个str,他会返回str2在str1里第一次出现的位置,如果没有找到,会返回一个空指针

接着我们来模拟实现一下strstr

char* my_strstr(const char* str1, const char* str2) {
	assert(str1 && str2);
	if (*str2 == '\0') {
		return str1;
	}
	const char* s1 = str1;
	const char* s2 = str2;
	const 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;
}

因为是查找字符串子串,我们不需要修改,所以加上const,第一个if语句用来判断特殊情况,如果要查找的子串是空串,我们直接返回str1,cp用来记录每次匹配的起始位置,也就是从str1的起始位置一直走到\0,用cp的位置开始匹配str2,s1和s2用来进行匹配,我们不能直接动用cp进行匹配,否则位置为发现错误,所以借助s1和s2,然后每次匹配完我们把cp赋给s1,str2赋给s2,接着就是匹配,我们在匹配时,s1和s2都可能走到\0,所以我们要加上这个条件,当内层while跳出后,如果s2到了\0,说明匹配成功,我们返回cp即可,否则cp++,如果cp到了\0都没有匹配成功,说明失败,退出外层while,返回NULL,当然我们还有很多细节没有实现,效率不高,我们是暴力求解,但是这样就可以完成strstr的功能了,这样写可能会有警告,如果感觉麻烦,可以在判断特殊情况的if里把str1强制转换为char*,返回的cp也要强制转换为char*

1.9.strtok

strtok也是一个比较奇特的函数,相比strstr,他更加特别,我们来看看他是怎么使用的

我们有12345@qq.com这样一个字符串,他是12345,qq,和com以及@和. 构成,我们想拿到前面三个字符串,就可以使用strtok函数,strtok是字符串分割函数

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

 sep参数是个字符串,定义了用作分隔符的字符集合,比如我们上边字符串,@和.就可以看做分割符,第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记

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

意思就是说,strtok会在arr里查找@符,会把@变为\0,然后会返回12345这个字符串的首元素地址,因为strtok会直接修改字符串内容,所以使用时一定要注意

我们可以先用strcpy进行拷贝,然后切割 

strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针

 意思就是说,strtok的第一个参数可以为空,也可以不为空,不为空时会寻找第一个标记,为空时他会从保存的位置向后寻找下一个标记

所以我们后续要分割时,要传NULL,他会自己记录一个位置,和\0有关,当找不到标记时会返回NULL

我们这样写太麻烦了,如果字符串很长的话,我们不可能这样复制粘贴那么多次,所以我们要这样写

我们使用循环来写,当ret不为空时,就会持续分割打印 

1.10.strerror

char * strerror ( int errnum );

strerror的作用是返回错误码,所对应的错误信息

c语言的库函数在运行时,如果发生错误,就会将错误码存在一个变量里,这个变量是:errno,是一个全局变量,错误码是一些数字,比如1,2,3,4,5,每一个错误码都对应一个错误信息,我们需要将错误码翻译成信息,我们看几个例子

 0对应的就是没有错误,1对应的是操作被拒绝,即没有权限,2对应的是没有这个文件,3对应的是没有这个进程,4对应的是函数被打断,5对应的是输入输出错误,每一个错误码对应一个错误信息的字符串,strerror是返回首字符的地址,用%s即可打印出来,通过错误信息我们就可以明白代码哪里有错误,实际应用里不是这样使用的,我们来看看我们该如何使用

我们用fopen这个函数举例,这是打开文件函数,如果打开成功,返回有效指针,打开失败返回NULL,当他打开失败时,是因为什么原因失败,我们就可以通过strerror知道

fopen如果没有指定位置,会在当前文件夹里寻找文件,我当前的文件夹里并没有text2023.txt这个文件,所以肯定会打开失败,fclose是关闭文件

 

 假如我们这里不知道为什么会打开失败,该怎么办呢?

我们可以把错误信息打印出来,错误码来自于errno,是全局变量,想使用errno需要引入头文件errno.h,我们看此时的错误信息,是没有这个文件,此时我们就明白了为什么会打开错误

接着我们在当前文件下创建test2023.txt这个文件,我们再来打开看看

 

这次就成功打开了 ,这就是strerror的使用方法,如果有多种错误,我们也可以多次打印,他会按错误顺序打印出来

除了strerror,还有一个函数更加方便

 我们直接来看例子

 他会先将我们输入的错误信息打印出来,然后会打印一个冒号,然后才会打印错误信息,perror里的内容是我们自定义的错误信息,他会先打印出自定义错误信息,我们可以认为perror是printf加strerror两个函数的组合,这个函数虽然方便,但是他不灵活,无论如何,他都会直接打印出错误信息,所以使用时要注意区别

1.11.字符分类函数

字符分类函数的数量非常多,大家使用里进行查询即可,我们来看看有哪些字符分类函数

函数如果他的参数符合下列条件就返回真
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任何可打印字符,包括图形字符和空白字符

 我们来看几个例子

我们来使用判断是否为小写 ,他会接收一个字符,或者ASCII码值,如果是小写字符,会返回一个非0的数字,否则返回0

使用这个函数,需要引入头文件ctype.h 

 其他函数也都是这样的设计,符合条件返回非0的数,不符合返回0

1.12.字符转换函数

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

这两个函数就非常简单,一个是小写转换为大写,一个是大写转换为小写

 非常简单,我们就不多介绍

2.内存函数

上面我们介绍了字符函数,比如字符串拷贝,字符串连接等等,但他们只能对字符串使用,我们在使用中,会有很多别的情况,比如我们需要拷贝一个整形数据,就不能使用strcpy进行拷贝,这时我们就需要内存函数

2.1.memcpy

memcpy是内存拷贝函数,我们来看看他的函数原型

 我们发现,他的参数是void*,返回值也是void*,这是因为我们可能对任何数据进行拷贝,所以使用了void*,我在上一期博客里详细介绍了void*,大家不了解的话可以去看看

(5条消息) 万字讲解!进阶指针!_KLZUQ的博客-CSDN博客

memcpy和strncpy参数很像,strncpy最后一个参数是拷贝字符的数量,memcpy的最后一个参数是拷贝字节的数量,我们来看个例子

我们将arr1里的5个元素拷贝到arr2里,因为数组是整形, 拷贝5个元素,5*4=20,所以我们拷贝20个字节,我们还可以跳着拷贝,比如我们拷贝3,4,5,6,7到arr2里

我们想怎么拷贝,就怎么拷贝,根据实际需求来看,我们也可以只拷贝17个字节

 

因为大小端的关系,所以这里数据没有影响

接着我们来模拟实现memcpy函数

void* my_memcpy(void* dest,const void* src, size_t num) {
	void* ret = dest;
	assert(dest && src);
	while (num--) {
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

因为void*指针不能直接使用,所以我们需要强制转换,又因为不确定类型,所以我们只能一个字节一个字节拷贝,所以我们强转为char*类型,然后让dest和src+1,+1时也需要进行强制转换,最后我们再返回起始地址即可

我们还可以这样写,用前置++来完成dest和src的+1操作,但是不能后置++,在某些编译器下是不行的

我们来看看memcpy的一些细节

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

知道了这些内容,那我们该想想我们代码的一些问题了,如果我们要将arr1里的34567拷贝到arr1的12345的位置,会发生什么呢?

此时就发生了问题,因为1先替换3,2先替换4,我们再要拷贝3时,3已经变成了1,4已经变成了2,那我们该怎么解决呢? 

我们可以倒着拷贝,1,2,3,4,5,6,7,8,9,我们先把5拷贝到7的位置,再把4拷贝到6的位置,然后是3到5的位置,依此类推,这样就不会出现问题了,那我们之后拷贝都从后往前拷贝行吗?答案是不行的,如果我们想把3,4,5,6,7拷贝到1,2,3,4,5的位置就会出现我们最开始的问题,所以我们要根据情况的不同,来选择不同的拷贝方式

我们发现当dest的起始位置在src起始位置的左边时,我们需要从前向后拷贝,而其他情况我们则可以从后向前拷贝,而实现这个方法的就是我们的memmove函数

2.2memmove

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

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

 我们来模拟实现memmove函数

void* my_memmove(void* dest, const void* src, size_t num) {
	void* ret = dest;
	assert(src && 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);
		}
	}
}

我们先判断src和dest的位置情况,然后进行if-eles选择,从前向后拷贝和memcpy的逻辑是一样的,从后向前拷贝,我们需要找到末尾位置,while循环的num会先进行-1,比如20变成19,然后再进行拷贝,而起始位置加上此时的num刚好是末尾位置,+1是第二个位置,+19自然是第20的位置,当前在使用src和dest前我们需要将他们强制转换,然后加上num,再解引用即可,此时我们不需要对dest和src进行操作,因为我们是对他们加上了num

其实在vs的环境下,memcpy也是可以对重叠空间进行操作的,效果和memmove是一样的,但是在其他编译器下就不一定了

2.3.memcmp

int memcmp ( const void * ptr1,const void * ptr2,size_t num );

从名字就可以看出,这是内存比较函数,使用方法也是一样的,最后一个参数是字节数,和strcmp是类似的,我们来看个例子

 前8个字节是相等的,返回0

 当我们比较第9个字节后,arr2是比arr1大的,所以返回<0的数(因为大小端的关系,比较9和比较12是一样的)

2.4.memset

memset是内存设置函数 ,他可以把我们的内存设置为我们想要的内容,但是也是以字节来进行设置的,所以出现的效果和我们想象中的是不一样的,我们来看个例子

比如这样,我们就是把arr数组的前5个字符改为x

 

接着我们把world改为y 

我们还可以用0填充,不过改为0后就什么都看不到了

 

 我们要把数组里10个0全部改为1,10个整形40个字节,我们这样写会出现这种情况,我们把数字改为16进制大家就明白了

 这就是我们说的memset是按字节为单位来修改的原因,我们再通过内存来看

 以上就是我们的全部内容,希望大家可以有所收获

如有错误,还请指正

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

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

相关文章

1.5万字总结 Redis 常见面试题知识点

以下内容来源于于我开源的 JavaGuide (Java学习&&面试指南,Github 130k star,370人共同参与爱完善), 万字总结,质量有保障! Redis 基础 什么是 Redis? Redis 是一个基于 C 语言开发的开源数据库(BSD 许可),与传统数据库不同的是 Redis 的数据是存在内存中的…

磨金石教育插画技能干货分享|学习插画可以从事什么工作?

近几年插画师这个行业越来越热&#xff0c;许多有一定绘画基础的朋友&#xff0c;都在跃跃欲试&#xff0c;想要走进插画这个行业。但不少人都有一种担忧&#xff0c;就是插画师这个职位平时听的很少&#xff0c;认为这是个冷门行业&#xff0c;是不是难以就业&#xff0c;风险…

边双连通分量

如果还未学习强连通分量&#xff0c;建议先学习强连通分量的tarjan算法强连通分量&#xff08;tarjan算法&#xff09; 1&#xff0c;定义 相对于在单向图的强连通分量&#xff0c;双连通分量是在无向图中&#xff0c;无向图有一个特点&#xff0c;可以以任何一个点为根节点建…

Java开发常见漏洞及解决方案

文章目录1.健康监控Actuator暴露端口2.SSRF漏洞攻击3.富文本XSS攻击4.暴力破解短信验证码登录5.恶意短信轰炸骚扰用户6.低版本Fastjson导致RCE漏洞7.SQL注入漏洞8.水平越权信息泄露9.权限绕过漏洞1.健康监控Actuator暴露端口 ​ Actuator是Springboot提供的用来对应用系统进行…

html 判断视频是否播放

html 判断视频是否播放 html <video id"video" loop preload"auto" autoplay><source src"1.mp4" type"video/mp4">您的浏览器不支持Video标签。 </video> js代码 var videodocument.querySelector("#vide…

phpstudy如何安装PHP扩展sg11

1、下载sg11扩展文件压缩包&#xff0c;下载地址&#xff1a;PHP扩展sg11.zip - 蓝奏云 2、解压下载好的sg11压缩包&#xff0c;选择对应你自己的服务器系统文件夹&#xff0c;我的是Windows 64-bit 3、打开Windows 64-bit&#xff0c;复制对应PHP版本的.win文件&#xff0c;…

电脑一键重装系统win11步骤教程

win11系统是微软目前最新的操作系统&#xff0c;很多人都想给电脑重装系统win11体验。那么具体要怎么重装系统win11呢?我们可借助一键装机工具实现&#xff0c;下面就演示下简单的一键重装系统win11步骤教程 工具/原料&#xff1a; 系统版本&#xff1a;Windows 11 品牌型号…

基于轻量级ShuffleNetv2+YOLOv5的DIC-C2DH-HeLa细胞检测识别分析系统

ShuffleNetv2可以说是目前轻量级网络模型中的翘楚&#xff0c;将ShuffleNetv2于yolov5整合开发可以使得模型更加轻量化&#xff0c;在提升模型速度的同时保证有效的精度。本文的主要工作就是将ShuffleNetv2整合进yolov5中来开发构建细胞检测模型&#xff0c;首先看下效果图&…

4-3文件管理-磁盘组织与管理

文章目录一.磁盘的结构二.磁盘调度算法&#xff08;一&#xff09;一次读/写磁盘需要的时间&#xff08;二&#xff09;磁盘调度算法1.先来先服务FCFS2.最短寻找时间优先SSTF3.扫描算法/电梯调度算法SCAN4.循环扫描算法C-SCAN&#xff08;三&#xff09;减少磁盘延迟时间的方法…

再谈模板(19)

目录 1、非类型模板参数 2、模板的特化 1、定义 2、函数模板特化 3、类模板特化 1、全特化 2、偏特化 3、分离编译 1、什么是分离编译 2、模板不支持分离编译 4、模板总结 1、非类型模板参数 模板参数&#xff1a;类型形参与非类型形参。 类型形参&#xff1a;出现…

Leetcode - 24 - 两两交换链表中的节点

24. 两两交换链表中的节点 题目描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;h…

重写部分调试体系的DebugPort隐藏

背景逛世界上最大的交友网站的时候发现了一个开源的vt调试器&#xff0c;抱着学习的心态&#xff0c;下载下来学习学习。但是呢&#xff0c;实际编译出来的程序和release发布的有很大的区别&#xff0c;而且源码很乱&#xff0c;release版本的驱动至少能调试程序&#xff0c;但…

文件IO操作

日升时奋斗&#xff0c;日落时自省 目录 1、文件基本认知 1.1、文件路径 1.2、相对路径 1.3、文件类型 2、Java的文件操作 2.1、文件操作类File 3、数据流读写 3.1字节流读文件 3.2、字节流写文件 3.3、字符流读操作 3.4、字符流写操作 4、文件操作案例 4.1、删除…

【自学Python】Python类型转换

Python类型转换 Python类型转换教程 虽然 Python 是弱类型编程语言&#xff0c;不需要像 Golang 或 C/C 语言那样还要在使用 变量 前声明变量的类型&#xff0c;但在一些特定场景中&#xff0c;仍然需要用到类型转换。 对 Python 内置的数据类型进行转换时&#xff0c;可以使…

valgrind callgrind使用

valgrind --toolcallgrind --dump-instryes ./foo # ,这里会运行很久,执行完毕后会生成一个callgrind.out.1266511如果你调试的程序是多线程&#xff0c;你也可以在命令行中加一个参数 -separate-threadsyes。这样就会为每个线程单独生成一个性能分析文件。如下&#xff1a;val…

好玩的小游戏系列 (一)基于html+js 原生贪吃蛇

一朵花如果只被用来观赏那只呈现出它的外在意义只是它生命的一部分若是不能够将其内在更实质的美发挥出来充其量也不过就是一朵死的花而已。 目录 一、前言 二、代码介绍 三、效果显示 四、编码实现 index.html jquery-1.10.2.js 五、获取源码 获取源码&#xff1f;私信…

【vue2】组件进阶与插槽(匿名·具名·作用域插槽详解)

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;v-modedl表单双向绑定、ref|$ref操作dom、dynamic动态组件、$nextTick同步、匿名插槽、具…

Java常用开发工具有哪些

本节介绍一下 Java 常用的几个开发工具。下面这些工具或许功能和作用不同&#xff0c;但是有着一个共同的主旨&#xff0c;那就是——它们都是为了给 Java 编码和开发提供卓越的支持。 常用源码编辑工具介绍 Java 源代码本质上其实就是普通的文本文件&#xff0c;所以理论上来…

【阶段三】Python机器学习16篇:机器学习项目实战:集成模型介绍、随机森林模型的基本原理与随机森林分类模型

本篇的思维导图: 集成模型介绍 集成学习模型使用一系列弱学习器(也称为基础模型或基模型)进行学习,并将各个弱学习器的结果进行整合,从而获得比单个学习器更好的学习效果。集成学习模型的常见算法有Bagging算法和Boosting算法两种。 算法类型 模型名称

lua 入门

安装 linux 下安装方式 curl -R -O http://www.lua.org/ftp/lua-5.4.4.tar.gz tar zxf lua-5.4.4.tar.gz cd lua-5.4.4 # 编译并测试没有问题 make all test make install卸载 cd lua-5.4.4 # 删除相关配置,之后可以删除 lua-5.4.4 make uninstall执行 文件以 .lua 结尾 方…