1 00:00:07,360 --> 00:00:09,360 [Powered by Google Translate] 让我们谈论阵列。 2 00:00:09,360 --> 00:00:12,780 那么,为什么我们要使用阵列吗? 3 00:00:12,780 --> 00:00:17,210 那么让我们说你有一个程序,需要存储5个学生证。 4 00:00:17,210 --> 00:00:21,270 这可能似乎是合理的,有5个独立的变量。 5 00:00:21,270 --> 00:00:24,240 我们会看到在一个位的原因,我们会从0开始计数。 6 00:00:24,240 --> 00:00:30,700 的变量,我们就必须将int ID0,诠释ID1,等等。 7 00:00:30,700 --> 00:00:34,870 我们想要执行的任何逻辑上学生证需要进行复制和粘贴 8 00:00:34,870 --> 00:00:36,870 这些学生的ID。 9 00:00:36,870 --> 00:00:39,710 如果我们要检查学生发生在CS50, 10 00:00:39,710 --> 00:00:43,910 我们首先需要检查,如果ID0代表学生的过程中。 11 00:00:43,910 --> 00:00:48,070 然后做同样的学生,我们需要的代码复制并粘贴ID0 12 00:00:48,070 --> 00:00:54,430 替换所有出现ID0 ID1等ID2,3和4。 13 00:00:54,430 --> 00:00:57,560 >> 只要你听到了,我们需要复制和粘贴, 14 00:00:57,560 --> 00:01:00,440 你应该开始想有一个更好的解决方案。 15 00:01:00,440 --> 00:01:05,360 现在,如果你知道你不需要5个学生证,而是7? 16 00:01:05,360 --> 00:01:09,570 您需要返回到源代码中添加一个ID5,ID6, 17 00:01:09,570 --> 00:01:14,260 复制并粘贴的逻辑检查,如果属于这2个新的ID类的ID。 18 00:01:14,260 --> 00:01:19,600 有没有所有这些ID连接在一起,所以是没有办法的要求 19 00:01:19,600 --> 00:01:22,040 程序做到这一点的ID 0到6。 20 00:01:22,040 --> 00:01:26,120 现在好了,你知道你有100个学生证。 21 00:01:26,120 --> 00:01:30,770 它开始似乎不太理想,需要单独声明这些ID, 22 00:01:30,770 --> 00:01:33,760 复制并粘贴这些新的ID任何逻辑。 23 00:01:33,760 --> 00:01:38,380 但是也许我们有决心,我们做的所有100名学生。 24 00:01:38,380 --> 00:01:42,240 但是,如果你不知道有多少学生实际上是什么? 25 00:01:42,240 --> 00:01:47,320 只是一些有n个学生,你的程序有问什么,n是用户。 26 00:01:47,320 --> 00:01:50,250 嗯哦。这是行不通的,非常好。 27 00:01:50,250 --> 00:01:53,820 你的程序只适用于一些固定数量的学生。 28 00:01:53,820 --> 00:01:57,520 >> 解决所有这些问题,是美丽的数组。 29 00:01:57,520 --> 00:01:59,930 那么,什么是数组? 30 00:01:59,930 --> 00:02:04,480 在一些编程语言中数组类型可能是能多做一点, 31 00:02:04,480 --> 00:02:09,960 但在这里,我们将重点放在数组的基本数据结构,就像你会看到它在C. 32 00:02:09,960 --> 00:02:14,030 数组是一个大的内存块。就是这样。 33 00:02:14,030 --> 00:02:17,770 当我们说我们有10个整数的数组,这只是意味着我们有一些块 34 00:02:17,770 --> 00:02:20,740 的内存是大到足以容纳10个独立的整数。 35 00:02:29,930 --> 00:02:33,410 假设一个整数是4个字节,这意味着有10个整数的数组 36 00:02:33,410 --> 00:02:37,180 是一个连续的块的40个字节在内存中。 37 00:02:42,660 --> 00:02:46,280 即使当您使用多维数组,我们不会在这里, 38 00:02:46,280 --> 00:02:49,200 它仍然只是一个大的内存块。 39 00:02:49,200 --> 00:02:51,840 多维符号只是为了方便。 40 00:02:51,840 --> 00:02:55,640 如果你有一个3×3的多维数组的整数, 41 00:02:55,640 --> 00:03:00,650 那么你的程序会真的只是把这个作为一个大的块36个字节。 42 00:03:00,650 --> 00:03:05,460 整数的总数是3次3,和每个整数占用4个字节。 43 00:03:05,460 --> 00:03:07,750 >> 让我们来看看一个基本的例子。 44 00:03:07,750 --> 00:03:10,660 在这里我们可以看到两种不同的方式声明数组。 45 00:03:15,660 --> 00:03:18,580 我们不得不评论1编译的程序 46 00:03:18,580 --> 00:03:20,900 因为我们声明x的两倍。 47 00:03:20,900 --> 00:03:25,140 我们就来看看一些之间的差异,这2种类型的声明中位。 48 00:03:25,140 --> 00:03:28,560 这些线路都声明一个数组的大小为N, 49 00:03:28,560 --> 00:03:30,740 在这里我们定义N为10。 50 00:03:30,740 --> 00:03:34,460 我们可以要求用户为一正整数 51 00:03:34,460 --> 00:03:37,250 及使用上,作为我们的数组中的元素数目的整数。 52 00:03:37,250 --> 00:03:41,960 像我们的学生ID的例子之前,这是一种像宣布10完全独立的 53 00:03:41,960 --> 00:03:49,000 虚变量; X0,X1,x2和等xN的-1。 54 00:03:57,270 --> 00:04:00,840 忽略我们声明数组的行,注意方括号不变 55 00:04:00,840 --> 00:04:02,090 在fo​​r循环内。 56 00:04:02,090 --> 00:04:09,660 当我们写的东西,比如x [3],我只是读为x支架3, 57 00:04:09,660 --> 00:04:13,090 你能想到它是这样要求的虚X3。 58 00:04:13,090 --> 00:04:17,519 比与大小为N的括号内的数目,这意味着,一个数组的通知 59 00:04:17,519 --> 00:04:22,630 我们称之为索引,可以是任何东西,从0到N-1, 60 00:04:22,630 --> 00:04:25,660 这是一个总的N个索引。 61 00:04:25,660 --> 00:04:28,260 >> 要想想如何实际工作 62 00:04:28,260 --> 00:04:31,260 请记住,数组是一个大的内存块。 63 00:04:31,260 --> 00:04:37,460 假设一个整数是4个字节,整个数组x是一个40字节的内存块。 64 00:04:37,460 --> 00:04:41,360 所以,X0是指非常的块的第一个4字节。 65 00:04:45,810 --> 00:04:49,230 X [1]是指在接下来的4个字节,等等。 66 00:04:49,230 --> 00:04:53,760 这就是说,开始的x是所有的程序都需要来跟踪。 67 00:04:55,660 --> 00:04:59,840 如果你想使用x [400],然后程序就知道,这相当于 68 00:04:59,840 --> 00:05:03,460 后仅1600字节x的开始。 69 00:05:03,460 --> 00:05:08,780 在哪里,我们得到1600个字节?这是只有400次4个字节的整数。 70 00:05:08,780 --> 00:05:13,170 >> 在继续之前,它是非常重要的实现,在C 71 00:05:13,170 --> 00:05:17,080 在阵列中使用的索引,我们没有强制执行。 72 00:05:17,080 --> 00:05:23,180 我们的大的块是只有10个整数长,但绝对不会骂我们,如果我们写X [20] 73 00:05:23,180 --> 00:05:26,060 甚至是X [-5]。 74 00:05:26,060 --> 00:05:28,240 该指数甚至不必须是一个数字。 75 00:05:28,240 --> 00:05:30,630 它可以是任意表达式。 76 00:05:30,630 --> 00:05:34,800 在该方案中,我们使用变量i的循环索引数组。 77 00:05:34,800 --> 00:05:40,340 这是一个非常常见的模式,循环从i = 0到该阵列的长度, 78 00:05:40,340 --> 00:05:43,350 然后使用i作为指数为阵列。 79 00:05:43,350 --> 00:05:46,160 这样你整个阵列的有效循环, 80 00:05:46,160 --> 00:05:50,600 ,你可以指定数组中的每一个点,或者用它来进行一些计算。 81 00:05:50,600 --> 00:05:53,920 >> 在第一个for循环中,我从0开始, 82 00:05:53,920 --> 00:05:58,680 所以它会分配到0点的数组中的值0次2。 83 00:05:58,680 --> 00:06:04,370 然后,我的增量,和我们指定的第一点在数组中的值1倍,2。 84 00:06:04,370 --> 00:06:10,170 然后,我的增量再等等,直到我们就到了指定的位置N-1阵列中的 85 00:06:10,170 --> 00:06:13,370 值N-1倍,2。 86 00:06:13,370 --> 00:06:17,810 因此,我们创建了一个数组的第一个10个偶数。 87 00:06:17,810 --> 00:06:21,970 也许埃文斯会是一个更好的变量名比x, 88 00:06:21,970 --> 00:06:24,760 但这样做东西拿走。 89 00:06:24,760 --> 00:06:30,210 第二个for循环,只打印出的价值,我们已经存放在里面的数组。 90 00:06:30,210 --> 00:06:33,600 >> 让我们尝试运行的程序与这两种类型的数组声明 91 00:06:33,600 --> 00:06:36,330 看看该程序的输出。 92 00:06:51,450 --> 00:06:57,020 据我们可以看到,程序的行为同样的方式为两种类型的声明。 93 00:06:57,020 --> 00:07:02,230 让我们也来看看会发生什么,如果我们改变了第一循环不停止在N 94 00:07:02,230 --> 00:07:05,040 而是说10,000元。 95 00:07:05,040 --> 00:07:07,430 超出了数组末尾的途径。 96 00:07:14,700 --> 00:07:17,210 哎呀。也许你已经看到了这一点。 97 00:07:17,210 --> 00:07:20,440 一个分割错误意味着你的程序崩溃。 98 00:07:20,440 --> 00:07:24,430 你会开始看到这些,当你触摸你不应该接触的内存区域。 99 00:07:24,430 --> 00:07:27,870 在这里,我们都在触摸开始的X超过一万个名额, 100 00:07:27,870 --> 00:07:31,920 这显然​​是在内存中,我们不应该接触的地方。 101 00:07:31,920 --> 00:07:37,690 所以,我们大多数人可能会不小心把10,000,而不是N, 102 00:07:37,690 --> 00:07:42,930 但如果我们做一些更微妙的像说写小于或等于N 103 00:07:42,930 --> 00:07:46,830 在fo​​r循环中的条件,而不是小于N。 104 00:07:46,830 --> 00:07:50,100 请记住,一个数组只具有从0到N-1的索引, 105 00:07:50,100 --> 00:07:54,510 这意味着,索引N超出阵列的结尾。 106 00:07:54,510 --> 00:07:58,050 在这种情况下,该程序可能不会崩溃,但它仍然是一个错误。 107 00:07:58,050 --> 00:08:01,950 其实,这个错误是很常见的,它有它的自己的名字, 108 00:08:01,950 --> 00:08:03,970 关闭1个错误。 109 00:08:03,970 --> 00:08:05,970 >> 这是它的基本知识。 110 00:08:05,970 --> 00:08:09,960 那么,什么是2种类型的数组声明的主要区别? 111 00:08:09,960 --> 00:08:13,960 一个区别是大的内存块。 112 00:08:13,960 --> 00:08:17,660 在第一个声​​明,我会打电话给支架数组类型, 113 00:08:17,660 --> 00:08:20,300 虽然这绝不是以往的名称, 114 00:08:20,300 --> 00:08:22,480 它会在栈上。 115 00:08:22,480 --> 00:08:27,450 而在第二,我会打电话给指针数组类型,它会在堆上。 116 00:08:27,450 --> 00:08:32,480 这意味着,当函数返回时,支架阵列会自动被释放, 117 00:08:32,480 --> 00:08:36,419 而你必须explicitily拨打免费的指针数组 118 00:08:36,419 --> 00:08:38,010 否则,你有内存泄漏。 119 00:08:38,010 --> 00:08:42,750 此外,在托架阵列实际上是不是一个变量。 120 00:08:42,750 --> 00:08:45,490 这是很重要的。这只是一个符号。 121 00:08:45,490 --> 00:08:49,160 你可以认为它是一个常量,编译器供您选择。 122 00:08:49,160 --> 00:08:52,970 这意味着,我们不能做什么,比如x + +的支架类型, 123 00:08:52,970 --> 00:08:56,240 虽然这是完全合法的指针类型。 124 00:08:56,240 --> 00:08:58,270 >> 指针类型是一个变量。 125 00:08:58,270 --> 00:09:01,510 对于指针类型,我们有2个独立的内存块。 126 00:09:01,510 --> 00:09:06,060 该变量x自身被存储在堆栈中,并只是一个单一的指针, 127 00:09:06,060 --> 00:09:08,620 但大的内存块存储在堆中。 128 00:09:08,620 --> 00:09:11,010 只是存储在堆栈中的变量x的地址 129 00:09:11,010 --> 00:09:14,010 大的堆内存块。 130 00:09:14,010 --> 00:09:17,370 这方面的一个含义是与运营商的规模。 131 00:09:17,370 --> 00:09:22,480 如果你问的支架数组的大小,它会给你的大内存块的大小, 132 00:09:22,480 --> 00:09:24,620 像40字节, 133 00:09:24,620 --> 00:09:26,920 但如果你问的指针类型的数组的大小, 134 00:09:26,920 --> 00:09:32,740 它会给你变量x本身,而在设备上可能只有4个字节的大小。 135 00:09:32,740 --> 00:09:36,530 使用指针数组类型,它是不​​可能直接要求 136 00:09:36,530 --> 00:09:38,530 大的内存块的大小。 137 00:09:38,530 --> 00:09:42,530 这是没多大的限制,因为我们很少想的大小 138 00:09:42,530 --> 00:09:46,980 大的内存块,如果我们需要的话,我们通常可以计算出它。 139 00:09:46,980 --> 00:09:51,490 >> 最后,支架阵列恰好为我们提供的快捷方式初始化数组。 140 00:09:51,490 --> 00:09:56,130 让我们看看我们如何可以写第一个使用快捷键在实例10个偶数。 141 00:10:11,220 --> 00:10:14,470 指针数组,有没有一种方法可以做到这样的快捷方式。 142 00:10:14,470 --> 00:10:18,120 这仅仅是你可以做什么与阵列的介绍。 143 00:10:18,120 --> 00:10:20,990 他们出现在几乎每一个程序,你写的。 144 00:10:20,990 --> 00:10:24,390 希望你现在可以看到一个更好的方式做学生证的例子 145 00:10:24,390 --> 00:10:26,710 从一开始的视频。 146 00:10:26,710 --> 00:10:29,960 >> 我的名字是罗布·波顿,这是CS50。