【C语言(十)】

字符函数和字符串函数

一、字符分类函数

C语言中有⼀系列的函数是专门做字符分类的,也就是⼀个字符是属于什么类型的字符的。这些函数的使用都需要包含⼀个头文件是 ctype.h

这些函数的使用方法非常类似,我们就讲解⼀个函数的事情,其他的非常类似: 

int islower ( int c );  

islower 是能够判断参数部分的 c 是否是小写字母的。 通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0。

练习:

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

#include <stdio.h>
#include <ctype.h>
int main ()
{
     int i = 0;
     char str[] = "Test String.\n";
     char c;
     while (str[i])
     {
         c = str[i];
         if (islower(c)) 
                c -= 32;
         putchar(c);
         i++;
     }
     return 0;
}
//把一个字符串转换成全小写
int main()
{
	char arr[] = "I Am A Student";
	int i = 0;
	while (arr[i])
	{
		if (isupper(arr[i]))
		{
			//arr[i] = arr[i] + 32;
			arr[i] = tolower(arr[i]);
		}
		putchar(arr[i]);
		i++;
	}
	return 0;
}

二、字符转换函数 

C语⾔提供了2个字符转换函数: 

上面的代码,我们将小写转大写,是-32完成的效果,有了转换函数,就可以直接使用 tolower 函数。

#include <stdio.h>
#include <ctype.h>
int main ()
{
     int i = 0;
     char str[] = "Test String.\n";
     char c;
     while (str[i])
     {
         c = str[i];
         if (islower(c)) 
         c = toupper(c);
         putchar(c);
         i++;
     }
 return 0;
}

三、strlen的使用和模拟实现

字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前⾯出现的字符个数(不包
'\0' )。
参数指向的字符串必须要以 '\0' 结束。
注意函数的返回值为size_t,是无符号的( 易错 )
strlen的使用需要包含头文件
学会strlen函数的模拟实现
int main()
{
	//3 - 6 = -3 --> 无符号整型 - 无符号整型 = 无符号整型,故-3被当成无符号整型,所以它是一个非常大的正数
	if (strlen("abc") - strlen("abcdef") > 0)
	{
		printf("大于\n");
	}
	else
	{
		printf("小于等于\n");
	}
	return 0;
}

改良: 

int main()
{
	if ((int)strlen("abc") - (int)strlen("abcdef") > 0)
	{
		printf("大于\n");
	}
	else
	{
		printf("小于等于\n");
	}
	return 0;
}

从这个代码中其实可以学到很多知识:

①unsigned int类型比int类型容量大,因为对于32/64位机器最前面一位对于int类型而言均是符号位,而对于unsigned int类型最高位不是符号位是可以存数据的。

②,当unsigned int类型和int类型运算时,如果没有指出转化类型,它会进行隐式转换为unsigned int 类型。同时当两个类型运算要进行隐式转换时一般会转换成容量较大的那个。

③printf打印的是%d,是整型,所以unsigned int 会转换成int类型,故a+b的值打印出就是3+-6=-3

④对于if ()逻辑语句中的a+b中的int类型便会转换为unsigned int 类型,-6对应的int类型原码为1000 0000 0000 0000 0000 0000 0000 0110,反码是1111 1111 1111 1111 1111 1111 1111 1001,补码为1111 1111 1111 1111 1111 1111 1111 1010,故补码的这串数会直接放进unsigned int 中,对应数为4294967290,再加上3为4294967293>0,所以输出为大于。

strlen的模拟实现: 

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

size_t my_strlen2(const char* str)
{
	assert(str);
	char* start = str;
	while (*str)
	{
		str++;
	}
	return str - start;
}
//写一个函数,不能创建临时变量,求字符串长度 - 递归
//my_strlen("abcdef")
//1+my_strlen("bcdef")
//1+1+my_strlen("cdef")
//1+1+1+my_strlen("def")
//1+1+1+1+my_strlen("ef")
//1+1+1+1+1+my_strlen("f")
//1+1+1+1+1+1+my_strlen("")
//1+1+1+1+1+1+0
size_t my_strlen(const char* str)
{
	if (*str == '\0')
		return 0;
	else
		return 1 + my_strlen(str + 1);
}

int main()
{
	char arr[] = "abcdef";
	size_t len = my_strlen(arr);
	printf("%zd\n", len);
	return 0;
}

补充: 

NULL --->  本质也是0,一般用于指针的初始化

\0 ---> \ddd 形式的转义字符,本质也是0,一般字符串的末尾会有\0是字符串的结束标志

0 ---> 数字0

null(NUL) ---> \0

'0' ---> 字符0,本质是 48

四、strcpy的使用和模拟实现 

Copies the C string pointed by source into the array pointed by destination, including the
terminating null character (and stopping at that point).
源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 拷贝到目标空间。
⽬标空间必须足够大,以确保能存放源字符串。
⽬标空间必须可修改。
学会模拟实现。

strcpy的使用:  

int main()
{
	//char arr1[5] = { 0 };//目标空间必须足够大
	//char arr2[] = "hello world";
	//strcpy(arr1, arr2);
	//printf("%s\n", arr1);

	char* p = "abcdefghilmkqwer";//常量字符串,不能修改
	char arr2[] = "hello world";
	strcpy(p, arr2);//目标空间必须是可修改的
	printf("%s\n", p);
	return 0;
}

 strcpy的模拟实现:

//模拟实现strcpy函数
char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;

	/*assert(dest != NULL);
	assert(src != NULL);*/

	/*assert(dest);
	assert(src);*/

	assert(dest && src);

	//while (*src)
	//{
	//	//*dest = *src;
	//	//dest++;
	//	//src++;
	//	*dest++ = *src++;
	//}
	//*dest = *src;
	while (*dest++ = *src++);
	return ret;
}

int main()
{
	char arr1[20] = { 0 };
	char arr2[] = "abcdef";
	printf("%s\n", my_strcpy(arr1, arr2));
	return 0;
}

五、strcat的使用和模拟实现 

Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included
at the end of the new string formed by the concatenation of both in destination.
源字符串必须以 '\0' 结束。
⽬标字符串中也得有 \0 ,否则没办法知道追加从哪⾥开始。
⽬标空间必须有足够的⼤,能容纳下源字符串的内容。
⽬标空间必须可修改。
字符串不能自己给自己追加,会产生覆盖。
char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);
	//1.找到目标空间的\0
	while (*dest)
	{
		dest++;
	}
	//2.拷贝
	while (*dest++ = *src++);
	return ret;
}

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	my_strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

 六、strcmp的使用和模拟实现

This function starts comparing the first character of each string. If they are equal to each
other, it continues with the following pairs until the characters differ or until a terminating
null-character is reached.
标准规定:
第⼀个字符串大于第⼆个字符串,则返回大于0的数字
第⼀个字符串等于第⼆个字符串,则返回0
第⼀个字符串小于第⼆个字符串,则返回小于0的数字
那么如何判断两个字符串?比较两个字符串中对应位置上字符ASCII码值的大小。

strcmp函数的模拟实现: 

int my_strcmp (const char * str1, const char * str2)
{
     int ret = 0 ;
     assert(src != NULL);
     assert(dest != NULL);
     while(*str1 == *str2)
     {
         if(*str1 == '\0')
         return 0;
         str1++;
         str2++;
     }
     return *str1-*str2;
}

补充:

%zd 用来格式化 ssize_t 类型(有符号整数类型)或 size_t 类型(无符号整数类型)的值。这个占位符是用于确保正确的格式化,并目可以在有符号和无符号整数之间正确切换。

当你使用 %zd 时,它可以用于 ssize_t 和 size_t 类型,因此适用于带符号和无符号整数。

那么%d和%zd的区别到底在哪里呢?

区别在于 %d 适用于有符号整数,而 %zd 适用于既有符号整数又有无符号整数,可以避免数据类型不匹配的问题。如果你要输出size_t类型的值,最好使用 %zd 以确保正确的格式化。

简而言之,如果你要输出无符号整数类型(如 size_t),请使用 %zd 以避免潜在的问题。如果你要输出有符号整数,那么可以使用%d。

那么我们继续来讨论%zu的作用:

%zu是用来格式化size_t类型的整数值的标准占位符。 (这并不难理解,因此我们简略介绍)

总结:

%d是仅用来打印有符号整型

%zd则既能打印无符号整型又能打印有符号整型

%zu是size_t的标准占位符

七、strncpy函数的使用 

Copies the first num characters of source to destination. If the end of the source C string
(which is signaled by a null-character) is found before num characters have been copied,
destination is padded with zeros until a total of num characters have been written to it.
拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

八、strncat函数的使用

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

Appends the first num characters of source to destination, plus a terminating null-character. (将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 \0 字符)。
If the length of the C string in source is less than num, only the content up to the terminating null-character is copied.(如果source 指向的字符串的长度小于num的时候,只会将字符串中到 \0 的内容追加到destination指向的字符串末尾)。
/* strncat example */
#include <stdio.h>
#include <string.h>
int main ()
{
     char str1[20];
     char str2[20];
     strcpy (str1,"To be ");
     strcpy (str2,"or not to be");
     strncat (str1, str2, 6);
     printf("%s\n", str1);
     return 0;
}

我们可以测试看一看strncpy时会不会把\0也复制过来,经过下面的测试我们发现确实如我们所想,\0也会跟着被复制过来。并且如果我们选择复制的源头的复制个数超过本来的字符串长度,那么将会把多出来的用\0来填补。

我们再来刨析一下strncat的不同使用情况:

strncat在插入字符串之后,如若源字符串长度比要插入的长度大,则会在插入后多补一个\0,若源字符串长度比要插入的长度小,则只会在插入后补充一个\0,多余的长度则不做计较。

九、strncmp函数的使用 

较str1和str2的前num个字符,如果相等就继续往后较,最多较num个字母,如果提前发现不⼀样,就提前结束,大的字符所在的字符串⼤于另外⼀个。如果num个字符都相等,就是相等返回0。

十、strstr的使用和模拟实现 

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

Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.
(函数返回字符串str2在字符串str1中第⼀次出现的位置)。
The matching process does not include the terminating null-characters, but it stops there.(字符
串的比较匹配不包含 \0 字符,以 \0 作为结束标志)。
/* strstr example */
#include <stdio.h>
#include <string.h>
int main ()
{
     char str[] ="This is a simple string";
     char * pch;
     pch = strstr (str,"simple");
     strncpy (pch,"sample",6);
     printf("%s\n", str);
     return 0;
}

 strstr的模拟实现:

//暴力算法
char* my_strstr(const char* str1, const char* str2)
{
	const char* cur = str1;
	const char* s1 = NULL;
	const char* s2 = NULL;

	assert(str1 && str2);
	if (*str2 == '\0')
		return (char*)str1;
	while (*cur)
	{
		s1 = cur;
		s2 = str2;
		while (*s1 && *s2 && *s1 == *s2)
		//1.s1找到了\0,*s2 == '\0' -> 找到了
		//2.s2找到了\0 -> 找到了
		//3.*s1 != *s2
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return (char*)cur;
		cur++;
	}
	return NULL;
}

int main()
{
	char arr1[] = "abbbcdef";
	char arr2[] = "bbc";
	char* ret = my_strstr(arr1, arr2);
	if (ret != NULL)
		printf("%s\n", ret);
	else
		printf("找不到!\n");
	return 0;
}

十一、strtok函数的使用 

sep参数指向⼀个字符串,定义了用作分隔符的字符集合
第⼀个参数指定⼀个字符串,它包含了0个或者多个由sep字符串中⼀个或者多个分隔符分割的标记。
strtok函数找到str中的下⼀个标记,并将其用 \0 结尾,返回⼀个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串⼀般都是临时拷贝的内容并且可修改。)
strtok函数的第⼀个参数不为NULL ,函数将找到str中第⼀个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第⼀个参数为 NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针。
int main()
{
	char arr[] = "zhangsan@163.com";
	char arr2[20] = { 0 };//zhangsan@163.com -> zhangsan\0163\0com
	strcpy(arr2, arr);
	const char* p = "@.";
	char* s = NULL;
	//char* s = strtok(arr2, p);//zhangsan\0
	//printf("%s\n", s);
	//s = strtok(NULL, p);//163\0
	//printf("%s\n", s);
	//s = strtok(NULL, p);//com\0
	//printf("%s\n", s);

	//初始化部分只执行一次
	for (s = strtok(arr2, p); s != NULL; s = strtok(NULL, p))
		printf("%s\n", s);

	return 0;
}

strtok0)用来将字符串分割成一个个片段。参数str指向欲分割的字符串,参数sep则为分割字符串中包含的所有字符。当strtok()在参数s的字符串中发现参数sep中包含的分割字符时,则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数str字符串,往后的调用则将参数str设置成NULL。每次调用成功则返回指向被分割出片段的指针。

从str开头开始的一个个被分割的串。当str中的字符查找到未尾时,返回NULL。

如果查找不到sep中的字符时,返回当前strtok的字符串的指针。

所有sep包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点。

十二、strerror函数的使用 

char * strerror ( int errnum );

strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。

在不同的系统和C语言标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头文件中说明的,C语⾔程序启动的时候就会使用⼀个全局的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会讲对应的错误码,存放在errno中,而⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。
#include <errno.h>
#include <string.h>
#include <stdio.h>
//我们打印⼀下0~10这些错误码对应的信息
int main()
{
    int i = 0;
    for (i = 0; i <= 10; i++) 
    {
        printf("%s\n", strerror(i));
    }
    return 0;
}

 在Windows11+VS2022环境下输出的结果如下:

No error
Operation not permitted
No such file or directory
No such process
Interrupted function call
Input/output error
No such device or address
Arg list too long
Exec format error
Bad file descriptor
No child processes

举例: 

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
     FILE * pFile;
     pFile = fopen ("unexist.ent","r");
     if (pFile == NULL)
         printf ("Error opening file unexist.ent: %s\n", strerror(errno));
     return 0;
}

 输出:

也可以了解⼀下perror函数,perror函数相当于⼀次将上述代码中的第9行完成了,直接将错误信息打印出来。perror函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
    FILE * pFile;
    pFile = fopen ("unexist.ent","r");
    if (pFile == NULL)
        perror("Error opening file unexist.ent");
    return 0;
}

输出:Error opening file unexist.ent: No such file or directory.

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

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

相关文章

鸿蒙4.0开发 - DevEco Studio如何使用Previewer窗口预览器报错

DevEco Studio预览器概况在HarmonyOS应用开发过程中&#xff0c;通过使用预览器&#xff0c;可以查看应用的UI效果&#xff0c;方便开发者实时查看应用的运行效果&#xff0c;随时调整代码。 1.正常启动 打开预览器的位置在DevEco Studio编辑界面的右上角部分&#xff0c;竖排…

MySQL低版本中:字符串中的数字、英文字符、汉字提取

我们如何提醒一个字段中的汉字和数字呢 高版本指mysql8.0以上 使用sql语句 SELECT REGEXP_REPLACE(column_name, [^\\p{Han}], ) AS chinese_characters FROM table_name;其中 column_name指名称列&#xff0c;table_name是表名 2.低版本使用 需要新建函数 DELIMITER $$DR…

ChatGPT4 Excel 高级复杂函数案例实践

案例需求: 需求中需要判断多个条件进行操作。 可以让ChatGPT来实现这样的操作。 Prompt:有一个表格B2单元格为入职日期,C2单元格为员工等级(A,B,C),D2单元格为满意度分数(1,2,3,4,5)请给入职一年以上,员工等级为A级并且满意度在3分以上的人发4000元奖金,给入…

《打造第二大脑》—如何构建高效的笔记系统

最近看了一本书&#xff0c;因为我也用Obsidian来记笔记&#xff0c;&#xff08;Obsidian之前有介绍过Obsidian使用教程&#xff08;如何构建你的个人知识库&#xff0c;第二大脑&#xff09;&#xff09;看完这本书后发现里面给的方法跟Obsidian很契合&#xff0c;所以就整理…

Vue3报错: ‘defineProps‘ is not defined,解决方法

问题出现: 今天在使用 <script setup>组合式 API 的语法糖的时候&#xff0c;定义defineProps时候报错&#xff1a; ‘defineProps’ is not defined 查了一下资料&#xff0c;这是因为eslint的语法校验导致的问题。 解决方法1&#xff1a; 在项目根目录的文件.eslin…

基于Springboot的任务发布平台设计与实现(源码齐全+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。你想解决的问题&#xff0c;今天给大家介绍…

QT作业3

完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密码不匹配&#xf…

鸿蒙小车之多任务调度实验

说到鸿蒙我们都会想到华为mate60&#xff1a;遥遥领先&#xff01;我们一直领先&#xff01; 我们这个小车也是采用的是鸿蒙操作系统&#xff0c;学习鸿蒙小车&#xff0c;让你遥遥领先于你的同学。 文章目录 前言一、什么是任务&#xff1f;为什么要有任务二、任务的状态三、任…

​报名参加openGauss训练营,开启数据库之旅!

一直以来,数据库被誉为基础软件“皇冠上的明珠”、技术的“大动脉”。也许我们对它的名字略感陌生,但我们生活的方方面面却都无法离不开它,无论是抢票、网购还是线上点餐等,几乎都得益于数据库的支持,它是支撑各类应用软件运行的基础。 openGauss是一款开源关系型数据库管理系…

Duplicate keys detected: This may cause an update error.【Vue遍历渲染报错的解决】

今天在写项目时&#xff0c;写到一个嵌套评论的遍历时&#xff0c;控制台出现了一个报错信息&#xff0c;但是并不影响页面的渲染&#xff0c;然后一看这个错的原因是 key值重复&#xff0c;那么问题的解决方式就很简单了。&#xff08;vue for循环读取key值时&#xff0c; key…

Java基础面试题小结

基础面试题 Java语言简介 Java是1995年由sun公司推出的一门高级语言&#xff0c;该语言具备如下特点: 简单易学&#xff0c;相较于C语言和C&#xff0c;没有指针的概念&#xff0c;所以操作和使用是会相对容易一些。平台无关性&#xff0c;即Java程序可以通过Java虚拟机在不…

使用Vue3+Typescript手写一个日历签到组件

设计理念 昨天写了个简单美观的日历签到组件&#xff0c;使用的是Vue3TypeScript&#xff0c;大概逻辑是先找到本月份第一天是周几&#xff0c;然后开始填充月份日期&#xff1a;weeksArray:[[]]:之后渲染到表格中&#xff0c;对于签到事件触发则先判断是否是今天且还未没有签…

【Pytorch】学习记录分享2——Tensor基础,数据类型,及其多种创建方式

pytorch 官方文档 Tensor基础&#xff0c;数据类型&#xff0c;及其多种创建方式 1. 创建 Creating Tensor&#xff1a; 标量、向量、矩阵、tensor2. 三种方法可以创建张量&#xff0c;一是通过列表(list)&#xff0c;二是通过元组(tuple)&#xff0c;三是通过Numpy的数组(arra…

Python将列表中的数据写入csv并正确解析出来

用Python做数据处理常常会将数据写到文件中进行保存&#xff0c;又或将保存在文件中的数据读出来进行使用。通过Python将列表中的数据写入到csv文件中很多人都会&#xff0c;可以通过Python直接写文件或借助pandas很方便的实现将列表中的数据写入到csv文件中&#xff0c;但是写…

苹果计划将全球1/4的IPhone产能转移至印度

KlipC报道&#xff1a;据相关人士报道&#xff0c;苹果希望在未来2到3年内每年在印度生产超过5000万部iphone&#xff0c;要是该计划得以实现&#xff0c;印度将占领全球iPhone产量的四分之一。 KlipC的分析师Alex Su表示&#xff1a;“此次iPhone15推出是苹果印度制造计划的一…

Initial用法-FPGA入门3

Initial是什么 FPGA Initial是一种在FPGA中进行初始化的方法。在FPGA设备上&#xff0c;初始值决定了逻辑门的状态和寄存器的初始值。FPGA Initial可以通过设置初始值来控制电路在上电后的初始状态。 Initial的作用 2.1&#xff0c;控制电路启动时的初始状态 通过设置FPGA Ini…

XXE利用的工作原理,利用方法及防御的案例讲解

XXE&#xff08;XML外部实体注入&#xff09;利用是一种网络安全攻击手段&#xff0c;其中攻击者利用XML解析器处理外部实体的方式中的漏洞。这种攻击主要针对的是那些使用XML来处理数据的应用程序&#xff0c;尤其是当这些应用程序没有正确限制外部实体的处理时。通过XXE利用&…

小程序接口OK,桌面调试接口不行

手机小程序OK,桌面版出现问题&#xff1b; 环境&#xff1a;iis反向url的tomcat服务&#xff0c;提供接口。 该接口post了一个很大的数组&#xff0c;处理时间比较久。 1&#xff09;桌面调试出现错误,提示 用apipost调用接口同样出错, 502 - Web 服务器在作为网关或代理服…

VS2022配置C++ 20解决import std报错

C 20新特征支持用import std来导入std模块&#xff0c;如下&#xff1a; 配置时主要有两个步骤&#xff1a; &#xff08;1&#xff09;项目--属性--常规--C语言标准--预览 - 最新 C 工作草案中的功能 (/std:clatest) 注意选择ISO C20 标准 (/std:c20)也不能正常使用&#xf…

一个程序,实现随机随机数据生成自由

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 发现又是好久没有和大家见面了&#xff0c;先给大家分享一下最近的研究方向和成果&#xff1a; 最近接到的…