C语言-基础语法学习-4 字符串

news2024/11/25 2:32:44

目录

      • 字符串
      • C语言字符串及相关函数
        • 定义
        • 字符数组和字符串的区别
        • sizeof()和strlen()的区别
        • 动态开辟字符串
        • 野指针
        • 常用字符串函数

字符串

C语言字符串及相关函数

在C语言中,字符串是由字符数组表示的一系列字符序列。C语言提供了一些函数来处理字符串,使我们能够对字符串进行操作和处理。以下是一些常用的C语言字符串函数的介绍:

  1. strlen():用于计算字符串的长度,即字符串中字符的个数。

  2. strcpy():用于将一个字符串复制到另一个字符串中。

  3. strcat():用于将一个字符串连接到另一个字符串的末尾。

  4. strcmp():用于比较两个字符串是否相等。返回值为0表示相等,小于0表示第一个字符串小于第二个字符串,大于0表示第一个字符串大于第二个字符串。

  5. strchr():用于在字符串中查找指定字符的第一次出现位置,并返回该位置的指针。

  6. strstr():用于在字符串中查找指定子串的第一次出现位置,并返回该位置的指针。

  7. sprintf():用于将格式化的数据写入字符串中,类似于printf()函数。

  8. strtok():用于将字符串分割为多个子字符串,可以指定分隔符进行分割。

这些函数提供了基本的字符串操作功能,可以帮助我们在C语言中进行字符串的处理和操作。使用这些函数时需要注意字符串的长度,避免数组越界和内存溢出的问题。

除了这些基本的字符串函数,C语言还提供了更多的字符串处理函数,如字符串转换函数(atoi、atof、itoa等)、字符串格式化函数(printf、scanf等)以及字符串查找和替换函数(strspn、strcspn、strpbrk等)。熟练掌握这些字符串函数的使用可以提高字符串处理的效率和准确性。

总结而言,C语言的字符串函数提供了丰富的功能,使我们能够对字符串进行各种操作和处理。通过合理运用这些函数,我们可以方便地处理字符串的拷贝、连接、比较、查找等操作,从而实现更加复杂的字符串处理需求。

定义

C语言并不存在字符串这个数据类型,而是用字符数组来保存字符串,但字符数组和字符串是完全不同的两个概念。

/*字符数组赋初值*/
char cArr[] = {'I''L''O''V''E''C'};
/*字符串赋初值*/
char sArr[] = "ILOVEC";

也可以写成如下等价形式:

/*字符数组赋初值*/
char cArr[6] = {'I''L''O''V''E''C'};
/*字符串赋初值*/
char sArr[7] = "ILOVEC";

对于字符串 sArr,可以直接使用 printf 的 %s 打印其内容;而对字符数组,很显然使用 printf 的 %s 打印其内容是不合适的。

//输出字符串方式
printf("%s", sArr);
puts(sArr);

字符数组和字符串的区别

  1. 字符串指针变量本身是一个变量,用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以 \0 作为串的结束。

    char str[] = "hello";   //字符串数组,可以修改数组内容
    char *pchar = "hello";  //字符串指针变量,此时的"hello"为字符串常量,不能再通过指针来修改其内容
    
  2. 字符数组是由若干个数组元素组成,它可用来存放整个字符串。

  3. 字符串指针变量只是一个指向字符串首地址的指针变量,我们可以对指针变量进行赋值,确定其指向的地址空间==(指针指向的字符串为字符串常量,不能再通过指针来修改其内容)==;
    而字符串数组在定义时便在内存中为其分配了空间,也就是说,我们不能随意的改变这个数组的地址。

    对字符串指针方式 char *ps="C Language"; 定义时可以写为:
    char *ps;
    ps="C Language";
    -------------------------------------
    而对数组方式: static char st[]={"C Language"}; 只能对字符数组的各元素逐个赋值,不能写为:
    char st[20];
    st={"C Language"};  //错误
    
  4. 差别体现在sizeof的值。用字符串数组定义的"helloword"占11个字节,是因为"helloword"加上结尾的"\0"一共十一个char型字符,每个char型字符占1个字节;而用字符串指针变量定义时,sizeof的值仅为4个字节,这是因为s2是一个指针,在32位系统中,地址占4个字节。

    我们通过一个小程序来认识这个区别。
    
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char c1[] ="helloworld";
        char *c2 = "helloworld";
    
        printf("sizeof(s1) :  %d %d\n", sizeof(c1), sizeof(c2));
        printf("strlen(s2) :  %d %d\n", strlen(c1), strlen(c2));
    
        return 0;
    }
    这段程序运行的结果是:
        sizeof(s1):  11  4
        strlen(s2):  10  10
    
    "helloword"一共10个字符,所以strlen的值都为10

sizeof()和strlen()的区别

char str[] = "hello";  //结尾有'\0'
sizeof(str);  //6,计算的是整个空间的长度
strlen(str);  //5,只计算有效字符,会忽略结尾的'\0'

char *p = "hello";
sizeof(p);  //8,p是一个char *
strlen(p);  //5

动态开辟字符串

常用函数,需要包含头文件#include <stdlib.h>

在这里插入图片描述

举例

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

int main()
{
    char *p; //未赋初值,为野指针
    p = (char *)malloc(1); //p有了具体的内存指向
    *p = 'c';
    free(p);  //释放空间,防止内存泄漏
    
    p = (char *)malloc(12);  //开辟新空间
    strcpy(p, "yanghaoqing");  //为新空间赋值
    
    int len = strlen("112123123adfadfasdf");
    realloc(p, len - 12 + 1);  //扩容,调整之前分配的空间,起始地址并未变化
    strcpy(p, "112123123adfadfasdf");
    
    puts(p); 
    free(p);  //释放空间
    p = NULL;  //防止为悬挂指针,防止野指针
    return 0;
}

野指针

**悬挂指针:**指针的指向内存被删除导致

  1. 例子1:

    • 退出if的范围之后,c变量不再存在,p指向的地址被操作系统回收了。

    • 指针被悬挂了,后续如果再被使用就会有问题。

    • int *p = nullptr;if (p == nullptr){undefined int c = 100;p = &c;}

  2. 例子2:变量p指向被释放了,指针被悬挂了,后续如果再被使用就会有问题。

    • int *p = nullptr;{undefined int *q = new intp = q;delete q;}

**野指针:**指针变量未初始化

指向不可用内存区域的指针(非法内存,垃圾内存)。野指针不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为if语句能够判断。但是野指针是很危险的,if不能判断一个指针是正常指针还是野指针。

野指针的成因主要有3种:

  1. 指针变量没有被初始化。 任何指针(全局指针变量除外,全局指针变量为NULL)变量在刚被创建的时候不会自动成为NULL指针,它的缺省值是随机的。所以指针变量在创建的时候,要么设置为NULL,要么指向合法的内存。
  2. 指针p被free/delete之后,没有置为NULL(最好加一句p = NULL;),经常性的我们会以为p是个合法的指针。他们只是把指针指向的内存给释放掉,并没有把指针本身干掉,此时指针指向的就是“垃圾”内存。所以我们应该在释放完之后,立即将指针置为NULL,防止出现乱指的情况
  3. 指针操作超越了变量的作用范围。不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。也就是说指向的对象的声明周期已经结束了,然而我们还使用该指针访问该对象。

常用字符串函数

可能需要包含头文件#include <string.h>

输出字符串

char *p = "yanghaoqing";
puts("请输入一个字符串:");  //输出字符串后,会自动输出一个回车符
puts(p);
printf("%s\n", p);

获取字符串

gets() 函数原型

include <stdio.h>
char *gets(char *str);   

gets() 函数注意事项

  1. 可以直接输入带空格的字符串

  2. gets() 函数的功能是从输入缓冲区中读取一个字符串存储到字符指针变量 str 所指向的内存空间。缓冲区(Buffer)又称为缓存(Cache),是内存空间的一部分。有时候,从键盘输入的内容,或者将要输出到显示器上的内容,会暂时进入缓冲区,待时机成熟,再一股脑将缓冲区中的所有内容“倒出”,我们才能看到变量的值被刷新,或者屏幕产生变化。

  3. 因为本函数可以无限读取,易发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值。

  4. 关于使用 gets() 函数需要注意:使用 gets() 时,系统会将最后“敲”的换行符从缓冲区中取出来,然后丢弃,所以缓冲区中不会遗留换行符。这就意味着,如果前面使用过 gets(),而后面又要从键盘给字符变量赋值的话就不需要吸收回车清空缓冲区了,因为缓冲区的回车已经被 gets() 取出来扔掉了。

    # include <stdio.h>
    int main(void)
    {
        char str[30];
        char ch;
        printf("请输入字符串:");
        gets(str);
        printf("%s\n", str);
        scanf("%c", &ch);
        printf("ch = %c\n", ch);
        return 0;
    }
    

    输出结果是:
    请输入字符串:i love you
    i love you
    Y
    ch = Y

    我们看到,没有清空缓冲区照样可以输入’Y’,因为 gets() 已经将缓冲区中的回车取出来丢掉了。如果前面使用的不是 gets() 而是 scanf,那么通过键盘给 ch 赋值前就必须先使用 getchar() 清空缓冲区。

gets() 函数使用例程

char *p = "yanghaoqing";  //不能更改指向的字符串
char str[128] = "\0";   //字符数组初始化\0
scanf("%s", str);
gets(str); 

对字符指针变量所指向的内存单元进行初始化也可以用 gets()

char str[30];
char *string = str;  //一定要先将指针变量初始化
gets(string);  //也可以写成gets(str);
printf("%s\n", string);  //输出参数是已经定义好的“指针变量名”

strncpy()函数

表示把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回被赋值后的dest。

char *strncpy(char *dest, const char *src, int n)

strcpy()函数

自己实现字符串拷贝函数 strcpy() 和 strncpy()函数

#include <stdio.h>

char *myStrcpy(char *des, char *src)
{
    if (des == NULL || src == NULL)
        return NULL;
    char *bak = des;
    while (*src != '\0')
        *des++ = *src++;
    *des = '\0';
    return bak;
}

char *myStrncpy(char *des, char *src, int count)
{
    if (des == NULL || src == NULL)
        return NULL;
    char *bak = des;
    while (*src != '\0' && count-- > 0)
        *des++ = *src++;
    if (count > 0)
        while (count-- > 0) 
            *des = '\0';
    else
	    *des = '\0';
    return bak;
}

int main()
{
    char str[128] = "\0";
    char *p = "1231asdfas";
    myStrcpy(str, p);
    puts(str);
    myStrncpy(str, p, 5);
    puts(str);
    return 0;
}

strcat()函数 字符串拼接函数

把src所指向的字符串(包括“\0”)复制到dest所指向的字符串后面(删除*dest原来末尾的“\0”)。要保证*dest足够长,以容纳被复制进来的*src*src中原有的字符不变。返回指向dest的指针。

char *strcat(char *dest, const char *src);

#include <stdio.h>
#include <string.h>
#include <assert.h>
//自己实现
char *myStrcat(char *des, char *src)  //写法1
{
    assert(des != NULL && src != NULL);  //断言,主动报错
    char *bak = des;
    while (*des != '\0')  //定位到结尾
        des++;
    while (*src != '\0')  //开始拼接
        *des++ = *src++;
    *des = '\0';
    return bak;
}

char *myStrcat2(char *des, char *src)  //写法2
{
    assert(des != NULL && src != NULL);  //断言,主动报错
    char *bak = des;
    strcpy(des + strlen(des), src); //先偏移有效字符个数后再拷贝字符串
    return bak;
}

int main()
{
    char str[128] = "casdfkadkdf";
    char *p = "handsome";
    char *pNew;
    pNew = strcat(str, p);  //有返回值,返回拼接好字符串的地址
    puts(str);
    puts(pNew);
    
    myStrcat(str, p);
    puts(str);
    
    return 0;
}

strcmp()函数

比较相同位置上字符的ASCll码值的大小。

若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数

int strcmp(const char *s1,const char *s2);

#include <stdio.h>
#include <string.h>
#include <assert.h>
//官方实现代码
int myStrcmp(const char *string1, const char *string2)  
{
	int ret = 0;
    assert(string1);
    assert(string2); //判断是否等于NULL
    
    //用unsigned char* 强转因为我们相减的字符ASC码值为正数没有负数,也就是无符号数
    while (!(ret = *(unsigned char *)string1 - *(unsigned char *)string2) && *string2)
    {
        string1++;
        string2++;
    }
    if (ret < 0)
        ret = -1;
    else if (ret > 0)
        ret = 1;
    return ret;
}

int main()
{
    char *p1 = "12akdadf";
    char *p2 = "23sdkfajl";
    int ret = strcmp(p1, p2);
    
    printf("%d\n", ret);
    return 0;
}

strncmp()函数

功能是把 str1 和 str2 进行比较,最多比较前 n 个字节,若str1与str2的前n个字符相同,则返回0;若s1大于s2,则返回大于0的值;若s1 小于s2,则返回小于0的值。

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

memset()函数

包含在头文件 # include <string.h>

  1. memset函数为初始化函数,可以将一段连续的内存初始化为某个值。但它是以字节为单位进行初始化的。
  2. 函数的功能是:将指针变量 s 所指向的前 n 字节的内存单元用一个“整数” c 替换,注意 c 是 int 型。s 是 void* 型的指针变量,所以它可以为任何类型的数据进行初始化。
  3. memset() 的作用是在一段内存块中填充某个给定的值。因为它只能填充一个值,所以该函数的初始化为原始初始化,无法将变量初始化为程序中需要的数据。用memset初始化完后,后面程序中再向该内存空间中存放需要的数据。
  4. memset 一般使用“0”初始化内存单元,而且通常是给数组或结构体进行初始化。一般的变量如 char、int、float、double 等类型的变量直接初始化即可,没有必要用 memset。如果用 memset 的话反而显得麻烦。
  5. 当然,数组也可以直接进行初始化,但 memset 是对较大的数组或结构体进行清零初始化的最快方法,因为它是直接对内存进行操作的。
  6. 虽然参数 c 要求是一个整数,但是整型和字符型是互通的。但是赋值为 ‘\0’ 和 0 是等价的,因为字符 ‘\0’ 在内存中就是 0。所以在 memset 中初始化为 0 也具有结束标志符 ‘\0’ 的作用,所以通常我们就写“0”。
  7. memset 函数的第三个参数 n 的值一般用 sizeof() 获取,这样比较专业。注意,如果是对指针变量所指向的内存单元进行清零初始化,那么一定要先对这个指针变量进行初始化,即一定要先让它指向某个有效的地址。而且用memset给指针变量如p所指向的内存单元进行初始化时,n 千万别写成 sizeof§,这是新手经常会犯的错误。因为 p 是指针变量,不管 p 指向什么类型的变量,sizeof§ 的值都是 4。

函数原型:

#include <string.h>
void *memset(void *s, int c, unsigned long n);
void memset(首地址,, sizeof(地址总大小));

比如对数组a赋值:

memset(a, 0, sizeof(a));

memset以字节为单位进行初始化,这句话是什么意思呢?

就是说它进行初始化时并不关心你要初始化的数组是什么类型的,它均以字节为单位进行初始化。
比如你的数组是int型的。int为4字节。

举例1:

memset(a, 1, sizeof(a));

在a中每个元素占 4字节
比如int型的0为 0x00000000
int 型的最大值为 0x7FFFFFFF
0xF = 0x1111 占四位
1字节为8bit ,所以两位为1字节
使用memset进行初始化后会变为 0x01010101 也就是16843009
所以以下两种初始化效果是一样的

memset(a,-1,sizeof(a));
memset(a,255,sizeof(a));

举例2:

# include <stdio.h>
# include <string.h>
int main(void)
{
    int i;  //循环变量
    char str[10];
    char *p = str;
    memset(str, 0, sizeof(str));  //只能写sizeof(str), 不能写sizeof(p)
    for (i=0; i<10; ++i)
    {
        printf("%d\x20", str[i]);
    }
    printf("\n");
    return 0;
}

根据memset函数的不同,输出结果也不同,分为以下几种情况:
memset(p, 0, sizeof(p)); //地址的大小都是4字节
0 0 0 0 -52 -52 -52 -52 -52 -52

memset(p, 0, sizeof(*p)); //*p表示的是一个字符变量, 只有一字节
0 -52 -52 -52 -52 -52 -52 -52 -52 -52

memset(p, 0, sizeof(str));
0 0 0 0 0 0 0 0 0 0

memset(str, 0, sizeof(str));
0 0 0 0 0 0 0 0 0 0

memset(p, 0, 10); //直接写10也行, 但不专业
0 0 0 0 0 0 0 0 0 0

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

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

相关文章

centos磁盘扩容

解释 PE - 物理块&#xff08;Physical Extent&#xff09; 硬盘上有很多实际物理存在的存储块PV - 物理卷 &#xff08;Physical Volume&#xff09; 物理卷处于最底层&#xff0c;它可以是实际物理硬盘上的分区&#xff0c;也可以是整个物理硬盘(相当于单独做一个分区)&…

CommonJS 和 ES6 module

本文主要自己觉得要记录的点记录下来,不耽误大家时间&#xff0c;会持续更新。 Module对象 Module {id: xxx/demo/1.js, //加载文件的绝对路径path: xxx/demo,// 加载文件所在目录的绝对路径exports: [Function (anonymous)],filename: xxx/demo/1.js,加载文件的绝对路径load…

B/S和C/S详解(嵌入式学习)

B/S和C/S详解 1. C/S1.1 概念1.2 C/S架构的特点 2. B/S2.1 概念2.2 B/S架构的特点2.3 相对于传统的C/S架构的优势 3. B/S架构详解4. B/S架构怎么用&#xff08;CGI、Lighttpd&#xff09; 1. C/S 1.1 概念 C/S&#xff08;Client/Server&#xff09;是一种计算机网络架构模式…

【C++】 Qt-页面布局

文章目录 布局组件和布局按钮练习-用户信息页面布局准备工作设置性别设置年龄设置生日设置邮箱后缀 设置头像创建文件写入文件清空表单信息Buddy&#xff08;伙伴&#xff09;关系Tab顺序 布局组件和布局按钮 Qt的UI设计器中提供了丰富的布局管理功能&#xff0c;组件面板里有…

高效简单解决滑动验证码

前言 做爬虫总会遇到各种各样的反爬限制&#xff0c;其中移动验证码是很重要且常见的一环&#xff0c;今天总结下如何高效破解他的方法&#xff0c;例如下图&#xff1a; 解决思路与方法 首先先来分析下&#xff0c;核心问题其实是要怎么样找到目标缺口的位置&#xff0c;一…

Windows服务启动exe无界面终极解决方案

1、前言 我这个方案&#xff08;C#操作&#xff09;是彻底解决【从Windows服务启动程序exe&#xff0c;程序无界面】问题的终极解决方案&#xff0c;终极方案&#xff0c;绝对的终极方案&#xff0c;本来打算收钱的&#xff0c;还是算了&#xff0c;你们也不容易&#xff0c;关…

网络安全(自学笔记)

如果你真的想通过自学的方式入门web安全的话&#xff0c;那建议你看看下面这个学习路线图&#xff0c;具体到每个知识点学多久&#xff0c;怎么学&#xff0c;自学时间共计半年左右&#xff0c;亲测有效&#xff08;文末有惊喜&#xff09;&#xff1a; 1、Web安全相关概念&am…

Redis 性能管理/优化 缓存雪崩/击穿/穿透

---------------------- Redis 性能管理 ---------------------------------------- ----- 查看Redis内存使用 ----- info memoryredis-cli -a abc123 info memory ----- 内存碎片率 ----- used_memory_rss&#xff1a;是Redis向操作系统申请的内存。used_memory&#xff1a;是…

缺失concrt140.dll下载,找不到concrt140.dll的解决方法

我们平时在打开 Adobe 应用程序、Halo、Forza Horizon 5 等时&#xff0c;可能会遇到找不到 concrt140.dll。因此&#xff0c;这不是特定于某个应用程序的问题。如果没有安装正确的 DLL&#xff0c;应用程序将无法正常工作&#xff0c;因为它们的代码依赖于这些库中编写的代码。…

井盖异动监测传感器:井盖的安全守护者

随着城市化进程的不断加速&#xff0c;城市道路、人行道上的井盖扮演着重要的角色。然而&#xff0c;由于各种因素&#xff0c;如车辆冲击、材料老化等&#xff0c;井盖常常会出现异动情况&#xff0c;井盖异动不仅对行车和行人的安全构成威胁&#xff0c;还给城市基础设施的维…

C#扩展——Visual Studio 代码提示/智能提示字体大小更改方法.

声明&#xff1a;本文为个人笔记&#xff0c;用于学习研究使用非商用&#xff0c;内容为个人研究及综合整理所得&#xff0c;若有违规&#xff0c;请联系&#xff0c;违规必改。 C#扩展——Visual Studio 代码提示/智能提示字体大小更改方法. 文章目录 C#扩展——Visual Studio…

【期末总复习】医学影像学(第2版)周翔平

【选择】 1、垂体腺瘤大小范围这么界定的&#xff1f; P66&#xff0c;肿瘤直径<1cm称为垂体微腺瘤&#xff0c;>1cm称为垂体大腺瘤&#xff0c;>4cm成为巨大腺瘤。 2、当一个车祸伤病人&#xff0c;怀疑长骨骨折首选什么检查方法&#xff1f; P387 X线平片 3、…

leetcode957. N 天后的牢房(java-14天周期优化)

N 天后的牢房 leetcode957. N 天后的牢房题目描述解题思路Java 代码演示 算法专题 leetcode957. N 天后的牢房 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/prison-cells-after-n-days 题目描述 监狱中 8 间牢房排成一…

力扣 106. 从中序与后序遍历序列构造二叉树

题目来源&#xff1a;https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/ C题解&#xff1a;中序遍历是左中右&#xff0c;后序遍历是左右中&#xff0c;所以拿到两个遍历数组&#xff0c;我们可以从后序遍历获取中间节点…

信号链噪声分析6

目录 概要 整体架构流程 技术名词解释 技术细节 公用时钟源相位噪声的消除 公用电源噪声的消除 小结 概要 提示&#xff1a;这里可以添加技术概要 放大器输出被发送到均衡混频器&#xff08;相位检测器&#xff09;。相位检测器将两 个信号混合&#xff0c;在其输出处产生和积…

Apollo无人驾驶平台中多传感器标定

传感器标定是无人车最基础也是最核心的模块之一。作为软件层提供的第一项服务,标定质量和准确度极大地影响着感知、定位地图、PNC等模块。在 Apollo 开源自动驾驶平台中,我们提供了丰富的多传感器标定服务,如激光雷达、惯导、摄像头、多普勒雷达等多种传感器之间的标定。算法…

pytorch 中 dim 的-1,0,1,2 的意义 详解

对于3维矩阵&#xff0c;dim为-1时 与 dim为2时 的效果是一样的。dim为0时 从0维度&#xff0c; 下图 是三维实例 图的目的是 可以由一个想象的空间。 下面代码 与上图关系不大 >>> ab torch.tensor([[[0,1,2,3],[1,2,3,4]],[[2,3,4,5],[4,5,6,7]],[[5,6,7,8],…

如何解决failed to load steamui.dll这个问题?

当你在玩steam的时候&#xff0c;电脑突然弹出一个failed to load steamui.dll的时候&#xff0c;相信你内心一定是非常的烦躁的&#xff0c;毕竟你的玩游戏体验直接中断了&#xff0c;今天小编就来给大家详细的讲解一下怎么解决failed to load steamui.dll这个问题。 目录 一…

leetcode消失的数字

题目描述 数组 nums 包含从 0 到 n 的所有整数&#xff0c;但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在 O ( n ) O(n) O(n) 时间内完成吗&#xff1f; 示例 1&#xff1a; 输入&#xff1a;[3,0,1] 输出&#xff1a;2 leetcode链接&#xff1a;消失的数字 ⭕…

举例说明什么是卷积神经网络

卷积神经网络&#xff08;Convolutional Neural Network, CNN&#xff09;是一种深度学习模型&#xff0c;主要应用于计算机视觉任务&#xff0c;如图像分类、物体检测等。它通过卷积层、池化层和全连接层等组件来实现对图像的特征提取和分类。 现在我们以一个简单的图像分类任…