C语言-字符函数与字符串函数

在C语言中,我们经常要对字符或是字符串进行各种操作。那C语言究竟给了我们哪些方法呢,本篇文章就是让大家了解对字符和字符串处理相关的知识。

目录

1.字符函数

1.1字符分类函数

1.2字符转换函数

2.字符串函数

2.1strlen函数的使用和模拟实现

2.2strcpy函数的使用和模拟实现 

2.3strcat函数的使用和模拟实现

2.4strcmp函数的使用和模拟实现

2.5strncpy函数的使用和模拟实现

2.6strncat函数的使用和模拟实现

2.7strncmp函数的使用和模拟实现

2.8strstr函数的使用和模拟实现

2.9strtok函数的使用

2.10strerror函数与perror函数的使用


1.字符函数

字符函数分为字符分类函数字符转换函数。在使用字符函数前,我们要包含头文件ctype.h

1.1字符分类函数

C语言中有一系列函数是专门给字符进行分类的,称为字符分类函数,具体函数如下:

函数参数符合就返回真,反之为假
isalpha字母字符
islower小写字母
isupper大写字母
isdigit数字字符
isalnum字母、数字字符
isspace空白字符:空格" ",换页"\f",换行"\n",回车"\r",制表符"\t",垂直制表符"\v"。
iscntrl控制字符
isprint可打印字符
ispunct标点字符
isgraph图形字符

这些函数的使用方法都类似,我们这里以islower和isupper举例:

1 int islower(char c);

2 int isupper(char c);

写一个代码,将字符串中的小写字母转大写,其他字符不变。

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

int main()
{
	char arr[] = "I am a student.";
	int i = 0;
	while (arr[i] != '\0')
	{
		if (islower(arr[i]));
		{

			arr[i] -= 32;//大小写字母ASCII码相差32,如'A'为97,'a'为65
		}
		i++;
	}

	return 0;
}

这里我们就用到了islower函数,只要其中的参数是小写字符,就会返回真。其余字符分类函数都是类似的,大家自行尝试练习。

1.2字符转换函数

C语言中一共有两个字符转换函数:

tolower(char c)将大写字母c转换为小写字母
toupper(char c)将小写字母c转换为大写字母

使用也是非常的简单,我们将上面1.1中代码的转换大小写部分用toupper进行改写:

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

int main()
{
	char arr[] = "I am a student.";
	int i = 0;
	while (arr[i] != '\0')
	{
		if (islower(arr[i]));
		{

			arr[i] = toupper(arr[i]);//将字符串中的每个字符都转换为大写
		}
		i++;
	}

	return 0;
}

2.字符串函数

我们不仅仅指对字符进行操作,有时也需要对字符串进行操作。和字符串操作相关的函数称为字符串(操作)函数

2.1strlen函数的使用和模拟实现

函数原型:

 size_t strlen(const char* str);

1.strlen函数的参数是即字符串(或字符数组),即首元素地址,统计的是字符串中 '\0' 前面出现的字符个数。

2.函数的返回值是size_t,是无符号的。

3.字符串必须以'\0'结束,否则结果为随机值

4.不能传字符,函数会将其ASCII码值当做地址,由于地址偏小,可能被操作系统所使用,返回值为error

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


int main()
{

	if (strlen("abc") - strlen("abcdef") > 0)
	//if ((int)strlen("abc") - (int)strlen("abcdef") > 0)
	{
		printf("str1>str2\n");
	}
	else
	{
		printf("str1<=str2\n");
	}

	return 0;
}

上述例子中,我们能得到strlen("abc")的值是3,strlen("abcdef")的值是6,3-6的-3,所以结果为str1<=str2。

然而正确结果为str1>str2。这是因为二者的返回值是size_t类型,是无符号的一种整型,所以两个无符号的数相加减得到的数也是无符号的,结果恒为正,应为str1>str2。

5.strlen函数的模拟实现

方法一:count计数器

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

方法二:指针-指针 

size_t my_strlen(const char* str)
{
	assert(str);
	char* start = str;
	while (*str != '\0')
	{
		str++;
	}
	return str-start;
}

方法三:函数递归

不能创建临时变量计数器的方式

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

2.2strcpy函数的使用和模拟实现 

函数原型:

char* strcpy(char* destination, const char* source);
1.ctrcpy函数是将源字符串source的内容拷贝到目标字符串destination中,因此我们不希望源字符串被改变,类型为const char*。
2.源字符串必须以 '\0' 结束,并且 会将源字符串中的 '\0' 拷拷贝到目标空间。
3.目标字符串的空间 必须足够大,以确保能存放源字符串。
#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[20] = "Wow, ";
	char arr2[] = "fantastic!";

	strcpy(arr1, arr2);

	printf("%s\n", arr2);

	return 0;
}

显然上面代码的结果为fantastic!

4.strcpy函数的模拟实现

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

我们让src的每一位都赋值给dest,然后++,直到*src为'\0'时,赋值结束,同时也会将'\0'赋值过去。但是我们返回的是dest原来那个位置的地址,所以我们再最开始要定义一个指针ret等于dest,和dest指向相同位置,最后返回这个位置即ret。

2.3strcat函数的使用和模拟实现

函数原型:

char* strcat(char* dest, const char* src);
1.strcat函数是将源字符串source追加到目标字符串后面,因此我们不希望源字符串被改变,类型为const char*。
2.源字符串和目标字符串中必须含有'\0',否则无法知道从哪里开始追加。
3. 目标字符串的空间 必须足够大,以确保能容纳下源字符串的内容。
#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[20] = "Wow, ";
	char arr2[] = "fantastic!";
	strcat(arr1, arr2);
	printf("%s\n", arr1);

	return 0;
}

上面代码将arr2连接到arr1后面,结果显然为Wow, fantastic!

4.strcat函数的模拟实现

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

其实和strcpy函数模拟实现相差不大,只是要将dest位置移到'\0'的位置,再将src拷贝过来就行了。

5.自己给自己追加

当一个字符串arr自己追加自己的时候,也就是my_strcat(arr,arr),这样代码是有问题的。我们可以仔细看看我们模拟实现的代码再结合当两个字符串都相同进行分析,就会发现当dest移动到'\0'位置将*src++赋值给*dest++时,字符串中的'\0'被不断覆盖,而while循环结束的条件是*src=='\0',也就是程序会不断在while循环中不停止,造成程序崩溃。下图是第一个'\0'被覆盖的情形:

但是我们库函数中的strcat是可以实现字符串的自身追加的,我们的模拟函数在这一点其实是有缺陷的,也许是因为VS中strcat的实现方法和我们不同。但是这也给我们提了个醒,当涉及到字符串自身的追加时,我们还是尽量不要使用strcat,万一不行呢?那具体用什么方法我在之后篇章会写到。

2.4strcmp函数的使用和模拟实现

函数原型:

int strcmp(const char* str1, const char* str2);
1.strcmp函数比较的是两个字符串的内容,因此我们不希望两个字符串的内容发生改变,二者都为
const char*类型。 标准规定stcmp函数:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
字符串比较大小比较的是两个字符串中对应位置上字符ASCII码值的大小。
#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[] = "apple";
	char arr2[] = "applf";
	char arr3[] = "Apple";
	printf("%d\n", strcmp(arr1, arr2));//-1
	printf("%d\n", strcmp(arr2, arr3));//1
	printf("%d\n", strcmp(arr1, arr3));//1
	printf("%d\n", strcmp(arr1, arr1));//0

	return 0;
}

2.strcmp函数的模拟实现

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

虽然VS上的结果分别为-1,0,1,但是我们只需要做到标准规定的要求就行了,即保证是负数、0、正数即可。如果两者开始字母都相等,那就往后一个一个比较,直到二者都为'\0'即两字符串相同,返回0。

2.5strncpy函数的使用和模拟实现

函数原型:

char* strncpy(char* destination, const char* source, size_t num);

1.strncpy函数是将源字符串的num个字符拷贝到目标字符串中,因此我们不希望源字符串被改变,类型为const char*。

2.如果源字符串的长度小于num,则拷贝完源字符串之后,在目标空间的后边追加0,直到num个。

#include <stdio.h>
#include <string.h>
	
int main()
	{
		char arr1[20] = "anvelope";
		char arr2[] = "happy";
		strncpy(arr1, arr2, 5);

		printf("%s\n", arr1);//happyope

		return 0;
	}

3.strncpy函数的模拟实现

char* my_strncpy(char* dest, const char* src, size_t num)
{
	assert(dest && src);
	char* str = dest;
	for (size_t i = 0; i < num; i++)
	{
		*dest++ = *src++;

	}
	return str;
}

我们只要在strcpy的基础上再外加一个循环就行了,循环num次即可。(暂不考虑加0的情况)。

2.6strncat函数的使用和模拟实现

函数原型:

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

1.将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 '\0' 。因此我们不希望源字符串被改变,类型为const char*。

2.如果source指向的字符串的长度小于num的时候,只会将字符串中到'\0'的内容追加到destination指向的字符串末尾。

#include <stdio.h>
#include <string.h>
	
int main()
{
	char arr1[] = "anvelope ";
	char arr2[20] = "happy";
	strncat(arr2, arr1, 8);

	printf("%s\n", arr2);//happy anvelope

	return 0;
}

3.strncat函数的模拟实现

char* my_strncat(char* dest, const char* src, size_t num)
{
	assert(dest && src);
	char* str = dest;
	while (*dest != '\0')
		dest++;
	for (size_t i = 0; i < num; i++)
	{
	    *dest++ = *src++;
	}
    *dest='\0';
	return str;
}

仍然在strncat的基础上外加一层循环,最后再追加一个'\0'即可。 

2.7strncmp函数的使用和模拟实现

函数原型:

int strncmp(const char* str1, const char* str2, size_t num);
1.strncmp比较的是str1和str2两个字符串的前num个字符,如果相等就继续往后比较,最多比较到第num个字符。

2.同strcpy标准,但是只比较前num个字符:

第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[] = "anvelope ";
	char arr2[] = "happy";
	int ret = strncmp(arr1, arr2, 3);//-1

	printf("%d\n", ret);

	return 0;
}

3.strncpy函数的模拟实现

int my_strncmp(const char* str1, const char* str2, size_t num)
{
	assert(str1 && str2);
	while ((*str1 == *str2) && --num)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;
}
依然在原strcmp函数的基础上外加一层循环就行了。注意--num不要写成num--,不然会多一次循环。 

2.8strstr函数的使用和模拟实现

函数原型:

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

1.strstr函数返回字符串str2在字符串str1中第⼀次出现的位置,因此并不希望字符串被改变,顾指针类型为const char*。

2.如果str2的第一个字符为'\0',则返回str1。

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

int main()
{
	char arr1[] = "An apple a day keeps a doctor away.";
	const char* p = "keep";
	char* ret = strstr(arr1, p);
	if (ret != NULL)
	{
		printf("%s\n", ret);
	}
	else
	{
		printf("没找到\n");
	}

	return 0;
}

上述代码要现在arr1中找到p第一次出现的位置,即第一个字符串中k的位置,返回这个位置,得到的就是从k开始,'\0'结束的字符串,即keeps a doctor away。

3.strstr函数的模拟实现

这个函数的模拟实现比之前的字符串函数难度要高一些,我们要考虑多种情况,也需要涉及多个指针。我们先看下面一种比较简单的情况:

在这种情况中,我们需要几个指针:cur用来遍历str1,当满足相等条件时,用s1和s2来判断后面的几个字符是否都和str2相等,这是最基本的情况,我们接下来看复杂一点的情况:

这种情况和第一种有什么区别呢?主要是在于当cur遍历到第一个字符e的时候,s1和s2会判断cur后面4个字符是否和str2相等,而且这是不相等的情况,因为从第一个e开始是eees,和str2不同。此时我们应该让cur++,从第二个e的位置开始重新利用s1和s2进行比较,发现和s2相等,即返回此时的cur。我们再看一种情况:

这种情况就是,str2并没有再str1中出现,那么我们直接返回NULL就好了。

出了上面三种情况,同时我们还需要注意一些特殊的情况,就是我们是认为*s1和*s2如果相等的话就继续比下一对,只要相等就一直往下比,那就有可能出现下面这种情况:

也就是如果*s1和*s2都为'\0'的时候,s1和s2就会造成越界访问,我们应该避免这种情况。

了解了以上的情况之后,我们就可以开始写代码了

char* my_strstr(const char* str1, const char* str2)
{
	const char* s1 = NULL;
	const char* s2 = NULL;
	const char* cur = str1;
	if (*str2 == '\0')
		return (char*)str1;
	while (*cur)
	{
		s1 = cur;
		s2 = str2;
		while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0')
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return (char*)cur;
		cur++;
	}
	return NULL;
}

需要注意内层while循环的条件是在*s1等于*s2的同时*s1和*s2都不能为'\0',在这种情况下如果跳出了循环是因为*s2为'\0',那就说明str2在str1中出现了,此时我们返回cur就可以了。特殊地,当s2本身里面就是空的,也就是*s2就已经为'\0',我们直接返回str1就好了,这是极其特殊的情况,我们单独处理即可。

2.9strtok函数的使用

函数原型:

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 指针。
#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[] = "has@been.slained";
	char arr2[30] = { 0 };
	strcpy(arr2, arr1);//保护arr1
	const char* sep = "@.";
	char* ret = strtok(arr2, sep);
	printf("%s\n", ret);

	char* ret = strtok(NULL, sep);//strtok会记住其位置,当第二次传参为NULL,继续寻找下一个标记
	printf("%s\n", ret);

	char* ret = strtok(NULL, sep);
	printf("%s\n", ret);

	return 0;
}

这样写的话当分隔符较多时比较复杂,此时我们可以用for循环来简化代码:

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

int main()
{
	char arr1[] = "has@been.slained";
	char arr2[30] = { 0 };
	strcpy(arr2, arr1);
    const char* sep = "@.";

	char* ret = NULL;
	for (ret = strtok(arr2, sep); ret != NULL; ret = strtok(NULL, sep))
	{
		printf("%s\n", ret);
	}

	return 0;
}

2.10strerror函数与perror函数的使用

函数原型:

char * strerror ( int errnum );
1.s trerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
2.在不用的系统与C语言标准库的实现中都规定了一些错误码,一般是放在errno.h这个头文件当中说明的,C语言成语启动的时候就会使用一个全局的变量errno来记录程序当前的错误码,只不过程序启动时的错误码是0,即没有错误。当我们再使用标准库中的函数发生了某种错误,就会将对应的错误码存放在errno中,而一个错误码的数字都有对应的错误信息,strerror的作用就是将错误对应的错误信息字符串的地址返回。

我们可以多试试几个错误码,看看它所对应的错误信息分别是什么: 

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

int main()
{
	for (int i = 0; i <= 10; i++)
	{
		printf("%d:		%s\n", i, strerror(i));
	}
	
	return 0;
}

大家可以自己在编译器上试试,在Windows11+VS2022环境下输出的结果如下:

  1  No error
  2  Operation not permitted
  3  No such file or directory
  4  No such process
  5  Interrupted function call
  6  Input/output error
  7  No such device or address
  8  Arg list too long
  9  Exec format error
 10  Bad file descriptor
 11  No child processes

我们再来看一个常见的例子:

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

int main()
{
	//fopen以读的形式打开文件,如果文件不存在,就打开失败
	FILE* pf = fopen("test.txt", "r");

	if (pf == NULL)
	{
		printf("%s\n",strerror(errno));
		return 1;
	}
	//读文件
	//......

	//关闭文件
	fclose(pf);

	return 0;
}

输出:

No such file or directory

当我们打开文件test.txt时打开失败,即pf为空指针的时候,我们就让它返回错误的信息。那么接下来,我们来看看perror函数。

函数原型:

void perror(const char* str);

perror函数相当于是对strerror的使用进行了封装。我们上面的代码要用printf函数来打印出错误信息,而perror函数直接将错误信息打印出来。perror函数打印完参数部分的字符串后,再打印一个冒号和一个空格,再打印错误信息。所以上述代码我们也可以写成:

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

int main()
{
	//fopen以读的形式打开文件,如果文件不存在,就打开失败
	FILE* pf = fopen("test.txt", "r");

	if (pf == NULL)
	{
		perror("fopen fail!");
		return 1;
	}
	//读文件
	//......

	//关闭文件
	fclose(pf);

	return 0;
}

输出:

fopen fail!: No such file or directory

那以上就是字符函数与字符串函数相关的重要知识。当然函数并不止这几个,上述只是我们经常用到或比较重要的。大家在熟练运用本章的函数后可以自行拓展学习新的函数。

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

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

相关文章

腾讯云幻兽帕鲁一键开服教程

腾讯云作为领先的云计算服务提供商&#xff0c;为广大用户提供了便捷、高效的游戏服务器搭建解决方案。其中&#xff0c;幻兽帕鲁一键开服功能&#xff0c;更是让游戏开服变得简单易懂。本文将为大家详细介绍腾讯云幻兽帕鲁一键开服的步骤&#xff0c;帮助大家轻松搭建自己的游…

cesium 指定点旋转rectangle Primitive方式 矩阵篇

cesium中rectangle是水平垂直于正北方向的&#xff0c;rectangle的属性中有rotation&#xff0c;但是rotation是以矩形的中心点进行旋转的&#xff0c;旋转过程中矩形的形状可能会变形&#xff0c;如果需要以矩形的顶点为原点进行旋转&#xff0c;可以采用primitive的方式添加p…

详解playwright 官方Javascript demo(适合小白)

如果大家刚上手playwright&#xff0c;并看到了Javascript脚本的官方demo&#xff0c;代码如下&#xff1a; const { webkit } require(playwright);(async () > {const browser await webkit.launch();const page await browser.newPage();await page.goto(http://what…

uni-starter的微信登录拿不到登录者的昵称,头像,手机号问题记录

uni-starter的微信登录竟然拿不到登录者的昵称&#xff0c;头像&#xff0c;手机号 获取手机号的方法在另外一篇文章中&#xff0c;需要认证&#xff0c;需要有营业执照 uni.login({"provider": type,"onlyAuthorize": true,// #ifdef APP"univerif…

嵌入式工程师如何利用周末提升自己?

提升自己一定要趁早&#xff0c;这是作为中年人的我&#xff0c;对年轻人的忠告。 以前年轻&#xff0c;觉得时间多&#xff0c;总是幻想着&#xff0c;很多人也大器晚成啊&#xff0c;晚点努力也不晚。 前阵子小米汽车火了&#xff0c;雷总说这是他最后一次重大创业&#xff0…

GEE APP——土壤水分资源管理器

摘要 由于土壤水分含量与地球气候和天气以及干旱、洪水或山体滑坡等现象有关,因此对许多科学和专业用户来说都非常宝贵。遥感技术为连续测量这一变量提供了独特的可能性。特别是在农业领域,对高空间分辨率绘图的需求非常强烈。然而,目前可操作的土壤水分产品只有中粗空间分…

RS232、RS485、RS422、TTL、CAN各自的区别

目录 一&#xff1a;工业串口通信标准RS232、RS485、RS422的区别 第一个区别、硬件管脚接口定义不同 第二个区别、工作方式不同 第三个区别、通信方式不同 第四个区别&#xff0c;逻辑特性不同 第五个区别、抗干扰性、传输距离和传输速率也不同 二&#xff1a;RS232、RS…

判断字符串为空的几种方法

1,关于null和""的区别&#xff1a; &#xff08;1&#xff09; null表示不指向任何东西&#xff0c;调用的话会报空指针异常&#xff1b; 空字符串""表示一个长度为0的字符串&#xff0c;调用是安全的&#xff1b; &#xff08;2&#xff09; null 不是对象…

LLM推理中的参数:beam_search、num_sequences、do_sample、temperature、top_k、top_p

原文&#xff1a; https://huggingface.co/blog/how-to-generate beam_search&#xff1a;动态规划每个step保留几个top解&#xff1b; num_sequences: generate输出几个top序列。num_sequences<beam_search。 do_sample: 设为True&#xff0c;则每个输出都进行采样&#…

【项目实战】记录一次PG数据库迁移至GaussDB测试(下)

上一篇分享了安装、迁移&#xff0c;本篇将继续分享迁移前操作、 DRS迁移数据、迁移后一致性检查、问题总结及解决方法。 目录 四、迁移前操作 4.1 源端(PG) 4.2 目标端(GaussDB库) 五、DRS迁移数据 5.1 创建复制用户 5.2创建迁移任务。 六、迁移后一致性检查 6.1使用…

GLIB: The Main Event Loop

主事件循环机制&#xff08;MEL&#xff1a;the Main Event Loop)在GLib和GTK应用中管理可用的事件源。事件源的类型包括&#xff1a;文件描述符&#xff08;管道、套接字和常规文件&#xff09;和定时器超时。 guint g_source_attach (GSource* source, GMainContext* contex…

无线网络安全之WiFi Pineapple初探

背景 WiFi Pineapple&#xff08;大菠萝&#xff09;是由国外无线安全审计公司Hak5开发并售卖的一款无线安全测试神器。集合了一些功能强大的模块&#xff0c;基本可以还原钓鱼攻击的全过程。在学习无线安全时也是一个不错的工具&#xff0c;本文主要讲WiFi Pineapple基础配置…

「GO基础」文件名规范、关键字与标识符

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

WebShell简介

WebShell简介 1、WebShell分类 • JSP类型 • ASP类型 • PHP类型 2、WebShell用途 • 站长工具 • 持续远程控制 • 权限提升 • 极强隐蔽性 3、WebShell检测方法 • 基于流量的 WebShell 检测 • 基于文件的 WebShell 检测 • 基于日志的 WebShell 检测 WebShe…

BCLinux8U6系统部署oceanbase分布式数据库社区版之一、准备 OBD 中控机

本文记录了在BCLinux8U6操作系统的虚拟服务器准备oceanbase开源数据库的 OBD 中控机的过程。 一、中控机环境 1、虚拟服务器硬件配置 2、操作系统版本信息 [rootlocalhost ~]# cat /etc/os-release NAME"BigCloud Enterprise Linux" VERSION"8.6 (Core)&qu…

Superset 二次开发之工具篇 Pycharm 搭建

环境:win10、conda、superset 3.0、node 18、npm 9.8 conda安装和使用教程 File-Settings-Project | Project Interpreter addlocalInterpreter添加本地解释器">Add Interpreter →> add local Interpreter 添加本地解释器 本地虚拟环境 superset4 conda execut…

Win10 启动时数字键盘不亮怎么办?

首先&#xff0c;按住winr 运行 windows 运行框&#xff0c;输入regedit 打开注册表编辑器 1.查找current_user选项下的Control Panel 中的keyboard 点击八initialkeyboard 值设置成2&#xff0c;如图所示即可。2.选择hkey_user 中的。default 下的control Panel 选项下的keyb…

聚酰亚胺PI的特性有哪些?UV胶水能够粘接聚酰亚胺PI吗?又有哪些优势呢?

聚酰亚胺&#xff08;Polyimide&#xff0c;PI&#xff09;是一种高性能的聚合物材料&#xff0c;具有许多优异的特性。以下是聚酰亚胺的主要特性&#xff1a; 1. 高耐热性&#xff1a;聚酰亚胺的玻璃化转变温度和熔点都很高&#xff0c;可在非常高的温度下工作&#xff0c;其…

蚂蚁云科技集团应用研究院院长李亚锋先生受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 蚂蚁云科技集团应用研究院院长李亚锋先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“探索AI技术对项目管理发展的影响”。大会将于5月25-26日在北京举办&#xff0c;敬请关注&#xff01; 议题简要&#xff1a; 19…

利用国产库libhv动手写一个web_server界面(二)

目录 一、配置参数解析与响应 1.读取参数 2.设置参数 3.恢复默认参数 二、整体的界面实现以及交互效果 三、关于yaml文件乱码问题解决 四、参考文章 一、配置参数解析与响应 使用cJSON解析库&#xff0c;解析接收到的JSON数据字段&#xff0c;区别接收到的配置参数是请…