C语言基础16:二维数组、字符数组

二维数组

定义

二维数组本质上是一个行列式的组合,也就是说二维数组由行和列两部分组成。属于多维数组,二维数组数据是通过行列进行解读。

二维数组可被视为一个特殊的一维数组,相当于二维数组又是一个一维数组,只不过它的元素是一维数组。(也就是说数组的元素的类型可以是数组类型)

语法
数据类型 数组名 [行数][列数];//二维数组外层表示行数,内层表示列数

举例:

int arr[3][3] = {{11,22,33},{21,22,23},{31,32,33}};//正确,等价于下面写法
int arr[][3] = {{11,22,33},{21,22,23},{31,32,33}}; //正确广义上称之为柔性数组int arr[3][3] = {{11,12},{21,22,23},{31}};  //正确,等价于下面写法
int arr[3][3] = {{11,12,0},{21,22,23},{31,0,0}};//正确int arr[3][3] = {};//正确,全部为0
int arr[3][3] = {{11}};//正确,未初始化的元素使用0填充int arr[][] = {{11,22,33},{21,22,23},{31,32,33}};//这种写法会编译错误,不能省略
int arr[3][] = {{11,22,33},{21,22,23},{31,32,33}};//这种写法会编译错误,不能省略

注意:在C语言中,二维数组在计算机的存储顺序是按行进行的,即第一维的下标变化慢,第二维的下标变化快。

应用场合

主要应用于数据有行列要求的情况。比如说我们现在要存储班级的学生的成绩。

特殊写法
  • 下标可以是整型表达式,如:a[2-1][2*2-1]
  • 下标可以是已经有值的变量或数组元素,如:a[2*x-1]
  • 数据元素可以出现在表达式中,如:b[1][2] = a[2][3]/2
  • 注意:使用数组元素的下标应在已定义数组的大小范围内:应注意区别定义数组大小和引用数组元素的区别。
初始化
  • 分行给二维数组赋初值

    int arr[3][4] = {{11,12,13,14},{21,22,23,24},{31,32,33,34}};
    
  • 可将所有数据写在一个花括号内,按照排列顺序对元素赋值

    int arr[3][4] = {11,12,13,14,21,22,23,24,31,32,33,34};
    
  • 可对部分元素赋初值,其余未赋值部分自动填充 整型默认值-0 | 字符型默认值-\0 | 浮点型默认值-0.0..

    int arr[3][4] = {{11},{21,22},{31}};
    
  • 若对全部元素赋初值,自定义数组时可以省略第1维数组的长度,第2维数组的长度必须指明。

    int a[][4] = {11,12,13,14,21,22,23,24,31,32,33,34};
    
  • 在分行赋初值时,也可以省略第1维的长度。

    int arr[][4] = {{11,12,13},{0},{0,10}};
    
案例

案例1:

  • 需求:二维数组的遍历

  • 代码:

    /*************************************************************************> File Name:    demo01.c> Author:       ZK> Description:二维数组的遍历  > Created Time: 2025年02月17日 星期一 09时15分14秒************************************************************************/#include <stdio.h>int main(int argc,char *argv[])
    {//创建一个二维数组,必须指定列int arr[][3] = {{11},{21,22},{31,32,33}};//获取二维数组的大小int r_len = sizeof(arr) / sizeof(arr[0]);//遍历二维数组//外层循环,遍历行元素(行元素是数组类型)for(int row = 0;row < r_len; row++){//内层循环,遍历列元素(列元素是单一类型)int c_len = sizeof(arr[row]) / sizeof(int);//内层循环,遍历列元素(列元素时是单一类型)for(int col = 0; col < c_len; col++){//获取元素printf("%-3d",arr[row][col]);}}printf("\n");return 0;
    }
  • 运行结果:

    在这里插入图片描述

案例2:

  • 需求:矩阵的转置(将一个2行3列的数组转换为3行2列的数组)

  • 代码:

    /*************************************************************************> File Name:    demo02.c> Author:       ZK> Description:二维数组的转置> Created Time: 2025年02月17日 星期一 09时39分39秒************************************************************************/#include <stdio.h>//定义行和列
    #define ROW 2
    #define COL 3int main(int argc,char *argv[])
    {//准备2个数组用来存放转置前后的数列int arr_before[ROW][COL] = {{11,12,13},{14,15,16}};int arr_after[COL][ROW] = {0};//计算arr_before的大小int r_len = sizeof(arr_before) / sizeof(arr_before[0]);//遍历for(int i = 0; i < r_len; i++){//计算arr_before中的列数int c_len = sizeof(arr_before[i]) / sizeof(int);for (int j = 0; j < c_len; j++ ){printf("%-4d",arr_before[i][j]);//转置arr_after[j][i] = arr_before[i][j];}printf("\n");}printf("\n");//换行//循环输出arr_afterfor(int i = 0;i < sizeof(arr_after)/sizeof(arr_after[0]); i++){for(int j = 0;j < sizeof(arr_after[i])/sizeof(int);j++){printf("%-4d",arr_after[i][j]);}printf("\n");}return 0;
    }
  • 运行结果:

在这里插入图片描述

字符数组

概念

元素类型为char字符型的数组,字符数组往往是用来存储字符串数据的。需要注意的一点是,我们C语言中的字符是字节字符。

字节字符:也就是一个字符占1个字节,在C语言中,我们使用char表示字节。

举例:

char a = 'A';	//正确
char b = '1';	//正确
char c = 65;	//正确。char支持两种赋值形式,一种是字符,一种是赋值,如果是数值表示ASCII码
char d = "A";	//错误,char字符不能使用双引号
char e = '卜';	//错误,中文一个字符超过了一个char

C语言支持字符串常量,不支持字符串变量

语法
char 数组名[容量];
char 数组名[行容量][列容量];

字符数组的语法就是我们前面所学的一维数组和二维数组的语法,只不过数组的数据类型是char而已。

注意:

​ 如果我们的char数组初始化的时候,没有完全初始化值的时候,空出来的地方使用\0进行填充。大家要注意,这里的\0只起到占位的作用,我们是无法通过printf进行输出的。

比如:

char c[8] = {'h','e','l','l','o'};//等价于
char c[8] = {'h','e','l','l','o','\0','\0','\0'};
案例

案例1:

  • 需求:输出一个字符序列(I LOVE YOU!)

  • 代码:

    /*************************************************************************> File Name:    demo03.c> Author:       ZK> Description:字符数组案例 > Created Time: 2025年02月17日 星期一 10时43分10秒************************************************************************/#include <stdio.h>int main(int argc,char *argv[])
    {//创建一个数组用来存储I LOVE YOU ASCII中32对应空格char arr[10] = {'I',' ','L','O','V','E',' ','Y','O','U'};//使用for遍历数组for(int i = 0;i < sizeof(arr) / sizeof(char);i++){printf("%c",arr[i]);}printf("\n");return 0;
    }
  • 运行结果:

在这里插入图片描述

案例2:

  • 需求:输出一个用字符组成的菱形图案

  • 代码:

    /*************************************************************************
    > File Name:demo04.c
    > Author:ZK
    > Description:
    > Created Time: 2025年02月17日 星期一 10时50分33秒
    ************************************************************************/#include <stdio.h>int main(int argc,char *argv[])
    {// 准备数据char arr[5][5] = {{' ',' ','*',' ',' '},{' ','*','*','*',' '},{'*','*','*','*','*'},{' ','*','*','*',' '},{' ',' ','*',' ',' '}};// 遍历数组for (int i = 0;i < sizeof(arr)/sizeof(arr[0]); i++){for (int j = 0; j < sizeof(arr[i])/sizeof(char); j++){printf("%c",arr[i][j]);}printf("\n");}printf("\n");return 0;
    }

注意:

①如果定义时,不初始化,元素值不确定

char arr1[2];	//此时属于未初始化,元素的值不确定(随机值),大概率是\0.也有可能是其值。
char arr2[5] = {'a','b','c'};//此时属于不完全初始化,未初始化的元素使用\0进行填充

②如果提供的字符个数大于数组长度,则按照语法错误处理;如果字符个数小于数组长度,后面的元素自动为空字符(\0)

③如果提供的字符个数与数组长度相同,可以省略数组长度,系统会自动确定元素个数,适合字符较多时。

字符串结束标志
说明
  • C语言规定,字符串以字符'\0'作为结束标志。

  • 编译系统对字符串常量自动加一个\0作为结束标志。

  • 程序中往往通过判断\0来检测字符串是否结束。

  • \0的ASCII码是0,不是一个可显示的字符,是“空操作符”,它什么都不做,不会增加有效字符,仅是一个工程判别的标志。

    char c[] = {'h','i'};//字符数组	hi
    char c[] = {'h','i','\0'};//字符串	hi
    char c[] = "hello";//实际等价于 hello\0// \0(空字符),ASCII码是0
    // 0 , ASCII码是48
    // 空格,ASCII码是32
    
字符数组的多样表示

我们的char数组可以以数组的形式一个个输出每个字符;我们的char数组也可以以字符串的方式整体进行输出所有字符。

案例:

/*************************************************************************
> File Name:demo05.c
> Author:ZK
> Description:
> Created Time: 2025年02月17日 星期一 11时24分19秒
************************************************************************/#include <stdio.h>int main(int argc,char *argv[])
{// 字符串的第1种表示:char s1[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0'};// 字符串的第2种表示:char s2[] = {"hello world"};// 字符串常量默认以\0结尾// 字符串的第3种表示:char s3[] = "hello world";// 输出字符串printf("%s\n%s\n%s\n",s1,s2,s3);return 0;
}

注意:

  • 字符串的长度与字符数组的长度不一定相同。
  • 利用字符串常量可以对字符数组进行初始化,但不能用字符串常量对字符数组赋值。
// 正确演示:利用字符串常量给字符数组初始化
char arr1[6] = "hello";// 错误演示:用字符串常量为字符数组赋值
char arr2[6];
arr2 = "hello";
字符串的基础操作

在用格式化说明符%s进行输入输出时,其输入输出项均为数组名、但在输入时,相邻两个字符串之间要用空格分隔,系统将自动在字符串最后加上\0,在输入时,遇到结束符\0作为输出结束标志。

对于字符串操作,我们需要使用到一些系统提供的函数(API操作)。

字符串输入
scanf

语法:

scanf("%s",&数组名);

注意:数组名对应的数组只能是char类型

案例:

/*************************************************************************
> File Name:demo06.c
> Author:ZK
> Description: 字符串输入函数:scanf
> Created Time: 2025年02月17日 星期一 15时26分41秒
************************************************************************/#include <stdio.h>int main(int argc,char *argv[])
{// 创建一个数组,用来存放人的名字char name[20];printf("请输入您的名字:\n");scanf("%s",name);// scanf第二个参数需要传递变量地址,如果是数组,数组名就代表数组的首地址,因为数组本身是没有空间的,其空间就是元素空间printf("您的姓名是%s\n",name);return 0;
}

注意:采用scanf()进行字符串输入,要求字符串中不能存在空格,否则字符串遇到空格就会结束。

fgets

语法:

fgets(数组名,数组容量,stdin);

功能:
从键盘录入一个字符串常量到字符数组,返回字符数组的地址(首地址,默认返回的地址,一般用12位16进制数表示)

说明:

​ 采用fgets进行字符串输入,可获取所有输入的字符串,包含 \n ,在实际的字符串处理时,我们可能需要处理 \n

案例:

/*************************************************************************
> File Name:demo06.c
> Author:ZK
> Description: 字符串输入函数:fgets
> Created Time: 2025年02月17日 星期一 15时26分41秒
************************************************************************/#include <stdio.h>int main(int argc,char *argv[])
{// 创建一个数组,用来存放人的名字char name[20];printf("请输入您的名字:\n");// fgets和scanf只能二选一fgets(name,sizeof(name)/sizeof(name[0]),stdin);printf("您的姓名是%s\n",name);return 0;
}  

注意:
① 如果输入的字符串不包括 空格 或 换行,可以使用scanf |fgets

​ ② 如果输入的字符串需要包含 空格 或 换行,只能使用fgets

​ ③ 经过对比,我们发现,在字符串输入中,fgets和scanf相比,fgets友好一些

gets 危险的

语法:

gets(数组名);

功能:
从键盘录入一个字符串常量到字符数组,返回字符数组的地址(首地址,默认返回的地址,一般用12位16进制数表示)

说明:

​ 采用gets进行字符串输入,可获取所有输入的字符串,包含 \n ,在实际的字符串处理时,我们可能需要处理 \n

案例:

/*************************************************************************
> File Name:demo06.c
> Author:ZK
> Description: 字符串输入函数:fgets
> Created Time: 2025年02月17日 星期一 15时26分41秒
************************************************************************/#include <stdio.h>int main(int argc,char *argv[])
{// 创建一个数组,用来存放人的名字char name[20];printf("请输入您的名字:\n");// fgets和scanf只能二选一fgets(name,sizeof(name)/sizeof(name[0]),stdin);printf("您的姓名是%s\n",name);return 0;
}
字符串输出
printf

语法:

printf("%s",数组名);

案例:

/*************************************************************************
> File Name:demo06.c
> Author:ZK
> Description: 字符串输入函数:scanf
> Created Time: 2025年02月17日 星期一 15时26分41秒
************************************************************************/#include <stdio.h>int main(int argc,char *argv[])
{// 创建一个数组,用来存放人的名字char name[20];printf("请输入您的名字:\n");scanf("%s",name);// scanf第二个参数需要传递变量地址,如果是数组,数组名就代表数组的首地址,因为数组本身是没有空间的,其空间就是元素空间printf("您的姓名是%s\n",name);return 0;
}
fputs

语法:

fputs(const char *s,FILE *stream);

功能:

​ 输出一个字符串

说明:

​ 字符串可以包含转义字符

案例:

/*************************************************************************
> File Name:demo06.c
> Author:ZK
> Description: 字符串输入函数:fputs()
> Created Time: 2025年02月17日 星期一 15时26分41秒
************************************************************************/#include <stdio.h>int main(int argc,char *argv[])
{// 创建一个数组,用来存放人的名字char name[20];printf("请输入您的名字:\n");// gets、fgets和scanf只能多选一gets(name);// 输出fputs(name,stdout);// 标准的输出return 0;
}
puts

语法:

puts(const char *s);

功能:

​ 输出一个字符串

说明:

​ 字符串可以包含转义字符

案例:

/*************************************************************************
> File Name:demo06.c
> Author:ZK
> Description: 字符串输入函数:fputs()
> Created Time: 2025年02月17日 星期一 15时26分41秒
************************************************************************/#include <stdio.h>int main(int argc,char *argv[])
{// 创建一个数组,用来存放人的名字char name[20];printf("请输入您的名字:\n");// gets、fgets和scanf只能多选一gets(name);// 输出puts(name);// 标准的输出return 0;
}
字符串转数值
  • strtol

    long strtol(const char *str, char **endptr, int base);
    

    将字符串转换为长整型数。

    参数说明:

    • str :指向要转换的字符串的指针。
    • endptr :一个指向字符指针的指针。如果提供了这个参数,并且转换成功, *endptr 将被设置为指向第一个未转换字符的指针。如果 endptr NULL ,则不使用它。
    • base :用于指定转换的基数。它可以是 2 到 36 之间的值,或者是特殊值 0。如果 base是 0,则函数会根据字符串的前缀(如 “0x” 或 “0X” 表示十六进制,“0” 表示八进制,否则默认为十进制)来自动确定基数。
  • strtoul

    unsigned long strtoul(const char *str, char **endptr, int base);
    

    将字符串转换为无符号长整型数。

  • strtod

    double strtod(const char *str, char **endptr);
    

    将字符串转换为双精度浮点数。

  • atoi

    int atoi(const char *str);
    

    将字符串转换为整型数(不推荐使用,建议使用 strtol )。

  • atol

    long atol(const char *str);
    

    将字符串转换为长整型数(不推荐使用,建议使用 strtol )。

  • atof

    double atof(const char *str);
    

    将字符串转换为双精度浮点数(不推荐使用,建议使用 strtod )。

案例:

/*************************************************************************
> File Name:demo09.c
> Author:ZK
> Description: 字符串转换数值
> Created Time: 2025年02月17日 星期一 16时20分34秒
************************************************************************/#include <stdio.h>
#include <stdlib.h>int main(int argc,char *argv[])
{printf("%lo,%ld,%lx\n",strtol("12",NULL,8),strtol("12",NULL,10),strtol("12",NULL,16));printf("%lo,%ld,%lx\n",strtol("012",NULL,0),strtol("12",NULL,10),strtol("0x12",NULL,0));int a = 10;printf("%p,%lx\n",&a,&a);return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小爱音箱连接电脑外放之后,浏览器网页视频暂停播放后,音箱整体没声音问题解决

背景 22年买的小爱音箱增强版play&#xff0c;小爱音箱连接电脑外放之后&#xff0c;浏览器网页视频暂停播放后&#xff0c;音箱整体没声音&#xff08;一边打着游戏&#xff0c;一边听歌&#xff0c;一边放视频&#xff0c;视频一暂停&#xff0c;什么声音都没了&#xff0c;…

【做一个微信小程序】校园地图页面实现

前言 上一个教程我们实现了小程序的一些的功能&#xff0c;有背景渐变色&#xff0c;发布功能有的呢&#xff0c;已支持图片上传功能&#xff0c;表情和投票功能开发中&#xff08;请期待&#xff09;。下面是一个更高级的微信小程序实现&#xff0c;包含以下功能&#xff1a;…

使用Navicat for MySQL工具连接本地虚拟机上的MySQL

昨天在虚拟机上装了MySQL数据库&#xff0c;今天打算用Navicat for MySQL工具连下&#xff0c;结果连接不上。 使用本地Navicat for MySQL工具连接虚拟机上的MySQL数据库&#xff1a; 1.Navicat连接mysql 解决方案 1、首先使用xshell工具连上虚拟机服务器&#xff0c;输入命令&…

算法笔记 02 —— 入门模拟

本系列为胡凡编著的算法笔记当中代码部分的精简版整理&#xff0c;笔者也在同时准备Leetcode刷题和实习面试&#xff0c;希望为有一定编码和数据结构基础的同学提供一份系统型的参考&#xff0c;以方便遗忘时的算法查阅、期末复习总览以及C学习参照。 目录 01 简单模拟 Ⅰ害…

unity学习38:导入角色和动画,实测用脚本控制trigger和动作状态的转换

目录 1 资源准备&#xff1a;先从unity的 Asset store下载一些free的资源 2 在project/Asset里找到角色模型和动画 2.1 在prefab里找到角色资源 2.2 找到动画资源&#xff0c;一般在Animation下的模型文件fbx下层 2.3 准备工作 2.4 拖拽模型文件里的动作到Animator 2.5 …

Weboffice在线Word权限控制:限制编辑,只读、修订、禁止复制等

在现代企业办公中&#xff0c;文档编辑是一项常见且重要的任务。尤其是在线办公环境中&#xff0c;员工需要在网页中打开和编辑文档&#xff0c;但如何确保这些文档只能进行预览而无法被编辑或复制&#xff0c;成为许多企业面临的一个痛点。尤其是在处理涉密文档时&#xff0c;…

Endnote使用笔记——持续更新

&#xff08;1&#xff09;如果样式库里没有想要的期刊格式&#xff0c;可以到这个网址进行下载&#xff0c;并放在本地安装Endnote的文件下边的styles文件里&#xff1a; https://endnote.com/downloads/styles/ &#xff08;2&#xff09;EndNote导入参考文献时&#xff0c;关…

try learning-git-branching

文章目录 mergerebase分离 HEAD相对引用利用父节点branch -f 撤销变更cherry-pick交互式 rebase只取一个提交记录提交的技巧rebase 在上一次提交上amendcherry-pick 在上一次提交上 amend tag多分支 rebase两个parent节点纠缠不清的分支偏离的提交历史锁定的Main推送主分支合并…

Unity使用反射进行Protobuf(CS/SC)协议,json格式

protobuf生成的协议,有挺多协议的.利用反射生成dto进行伪协议的响应 和 发送请求 应用场景: 请求(CS)_后端先写完了(有proto接口了),前端还没搞完时(暂还没接入proto),后端可使用此请求,可自测 响应(SC)_可自行构建一个响应(有些特殊数据后端下发不了的),对数据进行测试 // 请…

Linux探秘坊-------8.进程详解

1.概念详解 1.运行&&阻塞&&挂起 内容基础&#xff1a;方框中的就是调度队列&#xff0c;是一个 双向队列&#xff0c;每一个元素是PCB其对应的代码数据 1.运行 只要进程 在调度队列中&#xff0c;进程的状态就是运行&#xff08;running&#xff09;. 2.阻塞…

VUE 集成高德地图部署到nginx后打开不了,控制台报错

VUE 集成高德地图部署到nginx后打开不了&#xff0c;控制台报错:xxxxxxx,because it violates the following Content Security Policy directive: “script-src ‘self’ https://webapi.amap.com ‘unsafe-inline’ ‘unsafe-eval’ blob: data:”. Note that ‘script-src-e…

解决vue-awesome-swiper 4.x + swiper 5.x 分页pagination配置不生效问题

这次给的需求需要实现几个轮播图&#xff0c;我打算用swiper来做。刚开始我参照同事之前实现的swiper&#xff0c;复制到我的新页面中&#xff0c;是可用的。但是这次的需求需要有底下的分页pagination&#xff0c;而且因为版本比较老&#xff0c;比较难找到配置项。这里说一下…

Linux中线程创建,线程退出,线程接合

线程的简单了解 之前我们了解过 task_struct 是用于描述进程的核心数据结构。它包含了一个进程的所有重要信息&#xff0c;并且在进程的生命周期内保持更新。我们想要获取进程相关信息往往从这里得到。 在Linux中&#xff0c;线程的实现方式与进程类似&#xff0c;每个线程都…

Unity Muse AIGC工具

这篇介绍unity3D的AIGC工具&#xff0c;Unity Muse&#xff0c;实现文本生成材质、动画、聊天等功能。 一、关于Unity Muse Unity Muse Unity Muse&#xff1a;利用 AI 释放您的创造潜力 | Unity 利用编辑器内置的 AI 更快地将你的想法变成现实 使用Unity Muse&#xff0c…

UART(一)——UART基础

一、定义 UART(Universal Asynchronous Receiver/Transmitter)是一种广泛使用的串行通信协议,用于在设备间通过异步方式传输数据。它无需共享时钟信号,而是依赖双方预先约定的参数(如波特率)完成通信。 功能和特点 基本的 UART 系统只需三个信号即可提供稳健的中速全双工…

【MyBatis】预编译SQL与即时SQL

目录 1. 以基本类型参数为例测试#{ }与${ }传递参数的区别 1.1 参数为Integer类型 1.2 参数为String类型 2. 使用#{ }传参存在的问题 2.1 参数为排序方式 2.2 模糊查询 3. 使用${ }传参存在的问题 3.1 SQL注入 3.2 对比#{ } 与 ${ }在SQL注入方面存在的问题 3.3 预编译…

Redis 03章——10大数据类型概述

一、which10 &#xff08;1&#xff09;一图 &#xff08;2&#xff09;提前声明 这里说的数据类型是value的数据类型&#xff0c;key的类型都是字符串 官网&#xff1a;Understand Redis data types | Docs &#xff08;3&#xff09;分别是 1.3.1redis字符串&#xff0…

Linux:线程概念、理解、控制

目录 一、认识线程 1.认识线程V1 2.认识线程V2 3.认识线程V3 4.认识线程V4 5.认识线程V5 二、线程控制 1.前言 2.创建线程 3.线程等待 4.线程终止 5.线程分离 三、线程理解 一、认识线程 1.认识线程V1 借用大多数计算机教材的话&#xff0c;线程是进程的一个执行…

maven使用默认settings.xml配置时,Idea基于pom.xml更新依赖时报错,有些组件下载时连接超时

1、问题背景&#xff1a;maven使用默认settings.xml配置时&#xff0c;Idea基于pom.xml更新依赖时报错&#xff0c;有些组件下载时连接超时&#xff0c; 通过日志发下&#xff0c;去连接maven.org网站下载依赖&#xff0c;有时候肯定会超时。 2、解决办法&#xff1a;使用国外…

【第3章:卷积神经网络(CNN)——3.5 CIFAR-10图像分类】

嘿,小伙伴们,今天咱们来聊聊一个超级酷炫的话题——卷积神经网络(CNN)及其在CIFAR-10图像分类中的应用。这不仅仅是一个技术话题,更是一场探索人工智能奥秘的旅程。准备好了吗?咱们这就发车! 一、CNN:人工智能的“千里眼” 首先,咱们得知道CNN是啥。CNN,全名Convol…