1 00:00:00,000 --> 00:00:11,200 2 00:00:11,200 --> 00:00:12,580 >> DAVID马兰:好的,欢迎回来。 3 00:00:12,580 --> 00:00:13,290 这是CS50。 4 00:00:13,290 --> 00:00:15,130 这是七周的开始。 5 00:00:15,130 --> 00:00:18,890 因此,它已经有一段时间,所以我想我们最好 在哪里,我们需要旋风之旅 6 00:00:18,890 --> 00:00:20,760 离开的,我们现在要。 7 00:00:20,760 --> 00:00:23,310 >> 所以这个东西在这里可能有 造成了一定的焦虑在第一。 8 00:00:23,310 --> 00:00:27,680 但我希望,你开始 适应新环境,这表示在这里 - 9 00:00:27,680 --> 00:00:32,670 星级代表一个指针,它是 究竟是什么,更通俗地说? 10 00:00:32,670 --> 00:00:33,400 因此,它是一个地址。 11 00:00:33,400 --> 00:00:35,490 >> 因此,它的地址是 在内存中的东西。 12 00:00:35,490 --> 00:00:38,260 我们开始剥开层层 几个星期前,事情喜欢 13 00:00:38,260 --> 00:00:41,800 GetString的和其他类似的功能 这一切的时候已经返回 14 00:00:41,800 --> 00:00:46,010 地址在内存中的东西,像 地址中的第一个字符 15 00:00:46,010 --> 00:00:46,990 一些序列。 16 00:00:46,990 --> 00:00:50,360 >> 因此,我们也介绍了valgrind的, 你会开始使用这个问题 17 00:00:50,360 --> 00:00:53,380 设置,尤其是为下一个 问题设置。 18 00:00:53,380 --> 00:00:54,980 valgrind的为我们做什么? 19 00:00:54,980 --> 00:00:57,520 20 00:00:57,520 --> 00:01:01,020 检查内存泄漏, 检查滥用记忆。 21 00:01:01,020 --> 00:01:05,890 >> 以一定的概率,它可以检测,如果 你的代码将触摸内存 22 00:01:05,890 --> 00:01:07,100 那根本不应该。 23 00:01:07,100 --> 00:01:10,410 所以不一定泄漏,但如果你 一些超越的界限 24 00:01:10,410 --> 00:01:14,730 数组,并在实际运行Valgrind的 并诱发这种行为,而 25 00:01:14,730 --> 00:01:17,870 Valgrind是运行在你的程序是 它内部的运行,你会得到 26 00:01:17,870 --> 00:01:21,460 这样的消息 - “无效写 尺寸4,“记得一对夫妇 27 00:01:21,460 --> 00:01:25,880 两周前意味着我不得不意外 喜欢上一个int太远 28 00:01:25,880 --> 00:01:27,250 边界之外的一个数组。 29 00:01:27,250 --> 00:01:30,790 等大小4表示这里的大小 该特定的诠释。 30 00:01:30,790 --> 00:01:35,260 >> 因此,需要安慰的事实, Valgrind的输出,它的格式, 31 00:01:35,260 --> 00:01:36,170 仅仅是残暴的。 32 00:01:36,170 --> 00:01:40,180 这真的很难识破的一塌糊涂 有趣的信息。 33 00:01:40,180 --> 00:01:42,910 所以我们在这里所做的只是摘录 一些对情侣更 34 00:01:42,910 --> 00:01:43,850 有趣的线。 35 00:01:43,850 --> 00:01:46,760 但要意识到80%的valgrind 输出将是一个有点 36 00:01:46,760 --> 00:01:47,650 分心。 37 00:01:47,650 --> 00:01:52,820 >> 只要看看这些模式,如 - 无效的,正确的,无效的阅读,40个字节 38 00:01:52,820 --> 00:01:56,690 和一些的块数是绝对 丢失,这样的关键字。 39 00:01:56,690 --> 00:02:01,920 什么,你会希望看到的是一些 那种一丝什么功能 40 00:02:01,920 --> 00:02:03,340 错误是实际上英寸的 41 00:02:03,340 --> 00:02:07,195 在这种情况下,在这里,在哪一行 我的代码,显然是错误的吗? 42 00:02:07,195 --> 00:02:09,729 43 00:02:09,729 --> 00:02:14,130 >> 在一个名为memory.c,这是26 例如,我们都在玩 44 00:02:14,130 --> 00:02:14,890 的时间。 45 00:02:14,890 --> 00:02:16,460 所以它可能不是malloc的。 46 00:02:16,460 --> 00:02:18,630 这可能是在我的代码代替。 47 00:02:18,630 --> 00:02:20,910 因此,我们将再次看到这 前再次长。 48 00:02:20,910 --> 00:02:24,080 >> 因此,scanf函数,这是在一个 夫妇迄今形式。 49 00:02:24,080 --> 00:02:26,410 我们看到sscanf的简要介绍。 50 00:02:26,410 --> 00:02:28,330 而东西 你在你跳入 51 00:02:28,330 --> 00:02:29,535 准备测验。 52 00:02:29,535 --> 00:02:33,130 和scanf实际上是什么CS50 图书馆一直使用下面的 53 00:02:33,130 --> 00:02:36,560 相当长的一段时间,以便罩 得到来自用户的输入。 54 00:02:36,560 --> 00:02:40,420 >> 举例来说,如果我移动到CS50 家电在这里,让我开了 55 00:02:40,420 --> 00:02:45,315 比如今天这就是所谓的scanf函数0.C 它的超简单。 56 00:02:45,315 --> 00:02:46,590 这只是一个几行代码。 57 00:02:46,590 --> 00:02:50,880 但它真的演示如何调用getInt 已经工作的这段时间。 58 00:02:50,880 --> 00:02:54,710 >> 在这个程序中在这里,在第16行 请注意我声明一个int。 59 00:02:54,710 --> 00:02:57,270 因此,没有指针,没有什么神奇 在那里,只是一个int。 60 00:02:57,270 --> 00:03:00,330 然后在第17行,我提示 用户输入一个数字,请。 61 00:03:00,330 --> 00:03:02,930 然后在18年底,我这里使用的scanf。 62 00:03:02,930 --> 00:03:06,910 我和规定,一种如printf, 我期待报价 63 00:03:06,910 --> 00:03:08,110 引文结束%。 64 00:03:08,110 --> 00:03:10,920 >> 所以我%,当然, 表示一个int。 65 00:03:10,920 --> 00:03:14,580 但是要注意什么第二 是scanf函数参数。 66 00:03:14,580 --> 00:03:17,350 你会如何​​形容第二 逗号后的参数? 67 00:03:17,350 --> 00:03:19,450 那是什么? 68 00:03:19,450 --> 00:03:20,670 >> 这是x的地址。 69 00:03:20,670 --> 00:03:25,490 因此,这是非常有用的,因为通过提供 scanf函数x的地址,什么 70 00:03:25,490 --> 00:03:29,560 授权功能怎么办? 71 00:03:29,560 --> 00:03:33,010 不只是去那里,而且还做什么呢? 72 00:03:33,010 --> 00:03:34,060 >> 它的变化。 73 00:03:34,060 --> 00:03:38,080 因为你可以去那里,它的排序 就像一张地图在内存中的位置。 74 00:03:38,080 --> 00:03:41,900 所以只要你提供scanf函数,或 任何这样的地图,即功能 75 00:03:41,900 --> 00:03:45,840 功能可以去那里,不仅 看一看的价值,但它也可以 76 00:03:45,840 --> 00:03:49,670 更改该值,这是有用的,如果 scanf函数在生活中是 77 00:03:49,670 --> 00:03:53,060 扫描来自用户的输入,具体 从键盘输入。 78 00:03:53,060 --> 00:03:57,830 和F表示格式化,就像 printf的一个格式化的,f表示 79 00:03:57,830 --> 00:03:58,930 要打印的串。 80 00:03:58,930 --> 00:04:04,430 >> 因此,在短期,简单地说,此行18, 从用户的尝试读取一个int 81 00:04:04,430 --> 00:04:10,420 键盘和它里面存储的x, 无论地址x恰巧住在。 82 00:04:10,420 --> 00:04:14,860 然后最后,19号线刚说, 感谢为int的,在这种情况下。 83 00:04:14,860 --> 00:04:15,940 >> 所以,让我继续前进,使这个。 84 00:04:15,940 --> 00:04:18,570 所以使:scanf的0。 85 00:04:18,570 --> 00:04:20,130 让我继续放大。 86 00:04:20,130 --> 00:04:22,960 我会去,并运行此 点斜线:scanf的0。 87 00:04:22,960 --> 00:04:24,020 号码好吗? 88 00:04:24,020 --> 00:04:24,720 50。 89 00:04:24,720 --> 00:04:25,730 感谢为50。 90 00:04:25,730 --> 00:04:27,270 因此,它是相当简单的。 91 00:04:27,270 --> 00:04:28,160 >> 现在是什么是不是在做什么? 92 00:04:28,160 --> 00:04:29,940 这不是做了一大堆 错误检查。 93 00:04:29,940 --> 00:04:33,000 举例来说,如果我不配合, 我不键入一个数字,但 94 00:04:33,000 --> 00:04:37,860 而不是我写的东西,如“你好”, 这只是一种奇怪的。 95 00:04:37,860 --> 00:04:41,130 因此CS50的事情之一 库已经为我们做了一些 96 00:04:41,130 --> 00:04:43,440 时间是再次提示 并再次提示。 97 00:04:43,440 --> 00:04:49,320 >> 重试短语召回在cs50.c, 的原因,调用getInt 98 00:04:49,320 --> 00:04:51,670 CS50库实际上是一个整体 一堆线长,因为我们 99 00:04:51,670 --> 00:04:53,190 检查这样的愚蠢的东西。 100 00:04:53,190 --> 00:04:55,730 用户不要给 我们,其实,一个int? 101 00:04:55,730 --> 00:04:57,910 他或她给我们的东西 像一个字母? 102 00:04:57,910 --> 00:05:01,410 如果是这样,我们要检测 ,并大声喝斥。 103 00:05:01,410 --> 00:05:03,915 >> 但是,事情变得更加有趣 在下一个例子。 104 00:05:03,915 --> 00:05:09,840 如果我去scanf函数1.C,什么是一个 事情是从根本上改变 105 00:05:09,840 --> 00:05:11,135 在下一个例子吗? 106 00:05:11,135 --> 00:05:13,690 107 00:05:13,690 --> 00:05:16,010 我使用char *,当然, 而不是int。 108 00:05:16,010 --> 00:05:19,210 >> 因此,这是有趣的,因为char *, 回想一下,其实只是 109 00:05:19,210 --> 00:05:20,190 同样的事情串。 110 00:05:20,190 --> 00:05:23,840 所以感觉一样,也许这是一个超级 GetString的简单实现。 111 00:05:23,840 --> 00:05:26,010 但我已经去皮层 CS50库,所以我 112 00:05:26,010 --> 00:05:27,550 现在调用这个char *的。 113 00:05:27,550 --> 00:05:30,070 让我们看看,如果在任何地方, 我们去错了。 114 00:05:30,070 --> 00:05:30,840 >> 第17行 - 115 00:05:30,840 --> 00:05:33,950 我再次说,请你给我的东西, 在这种情况下,一个字符串。 116 00:05:33,950 --> 00:05:37,940 然后在下一行,我调用scanf函数, 再次,给它一个格式码, 117 00:05:37,940 --> 00:05:39,310 但这次%秒。 118 00:05:39,310 --> 00:05:41,900 那么这个时候,我 给它的缓冲区。 119 00:05:41,900 --> 00:05:43,550 >> 现在请注意,我没有使用 符号。 120 00:05:43,550 --> 00:05:47,120 但是,这是为什么这里大概OK? 121 00:05:47,120 --> 00:05:49,760 原因是什么缓冲了吗? 122 00:05:49,760 --> 00:05:50,770 这已经是一个指针。 123 00:05:50,770 --> 00:05:51,650 它已经一个地址。 124 00:05:51,650 --> 00:05:54,510 >> ,让我们这个“混淆视听”,让我 只是把它,例如, 125 00:05:54,510 --> 00:05:55,050 简约。 126 00:05:55,050 --> 00:05:58,250 不过,我已经把它称为缓冲,因为在 一般情况下,在编程中,如果你有一个 127 00:05:58,250 --> 00:06:02,130 大块的内存,这一个字符串真的 只是,你可以称之为一个缓冲区。 128 00:06:02,130 --> 00:06:04,460 这是一个地方来存储信息。 129 00:06:04,460 --> 00:06:07,400 >> 类似的事情,如YouTube,当 他们正在缓冲,可以这么说, 130 00:06:07,400 --> 00:06:10,270 只是意味着它的下载位 将它们保存在互联网和 131 00:06:10,270 --> 00:06:14,160 本地阵列,一个地方的内存块,所以 ,你可以看它,以后不 132 00:06:14,160 --> 00:06:16,830 跳跃或挂在 你一边玩。 133 00:06:16,830 --> 00:06:20,930 >> 所以这是一个问题,但在这里, 因为我告诉scanf函数,期望 134 00:06:20,930 --> 00:06:22,320 来自用户的字符串。 135 00:06:22,320 --> 00:06:24,410 这里的地址是 一块内存。 136 00:06:24,410 --> 00:06:26,180 把该字符串。 137 00:06:26,180 --> 00:06:31,230 这是为什么绑定给 给我们带来麻烦,但? 138 00:06:31,230 --> 00:06:33,490 >> 那是什么? 139 00:06:33,490 --> 00:06:35,510 我允许访问 内存的那部分? 140 00:06:35,510 --> 00:06:36,250 你知道,我不知道。 141 00:06:36,250 --> 00:06:39,210 由于缓冲区被初始化 什么吗? 142 00:06:39,210 --> 00:06:39,820 真的没有。 143 00:06:39,820 --> 00:06:43,090 因此,这是我们一直呼吁 垃圾值,这 144 00:06:43,090 --> 00:06:44,040 是不是一个正式的词。 145 00:06:44,040 --> 00:06:49,200 它只是意味着,我们不知道什么位 内的四个字节, 146 00:06:49,200 --> 00:06:51,240 我已经分配缓冲区。 147 00:06:51,240 --> 00:06:52,450 >> 我还没有叫的malloc。 148 00:06:52,450 --> 00:06:53,940 我肯定不叫GetString的。 149 00:06:53,940 --> 00:06:56,380 那么,谁知道什么是真正的 缓冲液内? 150 00:06:56,380 --> 00:07:00,550 还告诉scanf的盲目,去那里 并把任何用户输入。 151 00:07:00,550 --> 00:07:04,460 >> 那么,什么是可能造成 在我们的代码中,如果我们运行呢? 152 00:07:04,460 --> 00:07:05,700 大概一个segfault。 153 00:07:05,700 --> 00:07:07,970 也许不是,但可能是一个段错误。 154 00:07:07,970 --> 00:07:10,620 和我说,也许不是因为有时 你这样做,有时 155 00:07:10,620 --> 00:07:11,380 你没有得到一个段错误。 156 00:07:11,380 --> 00:07:14,280 有时候你就是幸运的,但 但是这将是 157 00:07:14,280 --> 00:07:15,340 在我们的程序中的一个bug。 158 00:07:15,340 --> 00:07:17,060 >> 所以,让我继续前进,编译这个。 159 00:07:17,060 --> 00:07:18,280 我要做到这一点老派的方式。 160 00:07:18,280 --> 00:07:23,825 所以铛破折号scanf函数-1,0, scanf函数1.C,回车。 161 00:07:23,825 --> 00:07:24,720 哎呀,太旧的学校。 162 00:07:24,720 --> 00:07:26,550 让我们来看看。 163 00:07:26,550 --> 00:07:28,440 我应该在哪里? 164 00:07:28,440 --> 00:07:29,700 哦,字符*缓冲区。 165 00:07:29,700 --> 00:07:33,595 166 00:07:33,595 --> 00:07:35,130 哦,谢谢你 - 167 00:07:35,130 --> 00:07:36,930 保存,OK - 168 00:07:36,930 --> 00:07:37,690 很老的学校。 169 00:07:37,690 --> 00:07:38,900 好吧,它已经有一段时间。 170 00:07:38,900 --> 00:07:41,720 >> 所以,我刚刚保存后的文件 使该临时 171 00:07:41,720 --> 00:07:42,700 前改变了一会儿。 172 00:07:42,700 --> 00:07:46,090 现在我已经编译 手动锵。 173 00:07:46,090 --> 00:07:49,500 现在我要继续前进 并运行scanf函数-1,回车。 174 00:07:49,500 --> 00:07:50,290 字符串。 175 00:07:50,290 --> 00:07:51,600 我会键入“你好。” 176 00:07:51,600 --> 00:07:54,070 >> 而现在,这里的地方,坦率地说,PRINTF 可以是有点恼人。 177 00:07:54,070 --> 00:07:56,020 它实际上并不是要 在这种情况下,段错误。 178 00:07:56,020 --> 00:07:59,860 printf是有点特殊的,因为 它是如此的超级常用 179 00:07:59,860 --> 00:08:03,570 基本上printf是做 我们赞成和实现, 180 00:08:03,570 --> 00:08:04,830 这不是一个有效的指针。 181 00:08:04,830 --> 00:08:09,080 让我把它后,我自己只是打印 在括号空,甚至 182 00:08:09,080 --> 00:08:13,340 虽然它不一定是 我们自己的预期。 183 00:08:13,340 --> 00:08:16,940 >> 因此,我们不能真的很容易诱发 段错误这一点,但显然这 184 00:08:16,940 --> 00:08:18,600 是不是我想要的行为。 185 00:08:18,600 --> 00:08:19,800 那么,有什么简单的解决方案? 186 00:08:19,800 --> 00:08:25,650 那么,在scanf-2,让我提出, 而不是实际只是分配 187 00:08:25,650 --> 00:08:30,100 的char *,让我有点小聪明有关 这一点,让我分配缓冲区 188 00:08:30,100 --> 00:08:32,940 为16个字符的序列。 189 00:08:32,940 --> 00:08:34,200 >> 所以,我可以做到这一点的方式在一对夫妇。 190 00:08:34,200 --> 00:08:35,610 我完全可以使用malloc。 191 00:08:35,610 --> 00:08:38,980 但我可以回去两个星期时 我只是需要一大堆 192 00:08:38,980 --> 00:08:39,620 字符。 193 00:08:39,620 --> 00:08:40,860 这只是一个数组。 194 00:08:40,860 --> 00:08:44,870 因此,让我,而不是重新定义缓冲区 是一个数组为16个字符。 195 00:08:44,870 --> 00:08:47,340 >> 而现在,当我通过缓冲区 - 196 00:08:47,340 --> 00:08:49,940 这是我们没有的东西 谈谈在本周二 - 197 00:08:49,940 --> 00:08:53,730 但你可以把一个数组作为 虽然它是一个地址。 198 00:08:53,730 --> 00:08:56,390 技术上,正如我们已经看到的那样,他们是 有一点点不同。 199 00:08:56,390 --> 00:09:01,290 但scanf函数不会介意,如果你传递给它 数组名,原因是什么 200 00:09:01,290 --> 00:09:05,030 铛会为我们做本质上是 作为治疗该数组的名称 201 00:09:05,030 --> 00:09:08,280 16个字节的数据块的地址。 202 00:09:08,280 --> 00:09:09,550 >> 因此,这是更好的。 203 00:09:09,550 --> 00:09:12,110 这意味着,现在我希望能 做到以下几点。 204 00:09:12,110 --> 00:09:16,800 让我缩小了一会儿, 做scanf的-2,编译OK。 205 00:09:16,800 --> 00:09:19,390 现在让我做了斜线scanf函数2。 206 00:09:19,390 --> 00:09:22,430 字符串。 “你好。”并且它 似乎工作时间。 207 00:09:22,430 --> 00:09:26,020 >> 但有人提出了一个方案 它仍然可能不工作? 208 00:09:26,020 --> 00:09:28,550 是吗? 209 00:09:28,550 --> 00:09:30,640 东西超过16个字符。 210 00:09:30,640 --> 00:09:32,020 而实际上,我们可以 更确切的一点。 211 00:09:32,020 --> 00:09:36,540 东西不再那么15个字符, 因为我们真的需要牢记 212 00:09:36,540 --> 00:09:39,920 我们需要反斜杠零 上面的字符串末尾的隐式 213 00:09:39,920 --> 00:09:42,950 这是一个抛开scanf函数通常会 照顾我们。 214 00:09:42,950 --> 00:09:46,210 >> 因此,让我做这样的事情 - 215 00:09:46,210 --> 00:09:48,040 有时我们就可以 离开它这样。 216 00:09:48,040 --> 00:09:50,630 好了,我们现在已经引起 我们的分割故障。 217 00:09:50,630 --> 00:09:51,000 为什么呢? 218 00:09:51,000 --> 00:09:54,940 因为我打字不超过15个 字符,所以我们实际上已经 219 00:09:54,940 --> 00:09:58,280 其实我感动内存 不应该有。 220 00:09:58,280 --> 00:10:00,180 >> 那么,什么是真正的解决方案在这里? 221 00:10:00,180 --> 00:10:02,210 那么,如果我们需要一个更长的字符串? 222 00:10:02,210 --> 00:10:03,960 好吧,我们也许做32个字节。 223 00:10:03,960 --> 00:10:05,160 那么,如果不够长吗? 224 00:10:05,160 --> 00:10:06,040 大约64个字节? 225 00:10:06,040 --> 00:10:07,080 如果不够长? 226 00:10:07,080 --> 00:10:09,640 约128或200字节? 227 00:10:09,640 --> 00:10:12,660 什么是真正的解决方案,在这里 一般情况下,如果我们不知道在 228 00:10:12,660 --> 00:10:14,460 推进用户要输入什么? 229 00:10:14,460 --> 00:10:20,000 230 00:10:20,000 --> 00:10:23,050 >> 这是一个很大的痛苦的屁股只是一种, 说实话,这是为什么 231 00:10:23,050 --> 00:10:29,050 CS50库有几十行 共同实施的代码 232 00:10:29,050 --> 00:10:32,390 字符串的方式,我们不这样做,则由GetString引发 提前知道什么 233 00:10:32,390 --> 00:10:33,430 用户将要输入。 234 00:10:33,430 --> 00:10:37,370 特别是,如果你回头看看 cs50.c从两个星期前,你会看到 235 00:10:37,370 --> 00:10:40,480 确实,GetString的 以这种方式不使用的scanf。 236 00:10:40,480 --> 00:10:43,720 相反,它读取一个字符 的时间。 237 00:10:43,720 --> 00:10:46,010 >> 因为一个美好的事情 我们可以读取一个字符 238 00:10:46,010 --> 00:10:48,490 保证自己总是 至少有一个字符。 239 00:10:48,490 --> 00:10:51,740 我可以声明一个char,然后采取 只是这些真正的婴儿的步骤 240 00:10:51,740 --> 00:10:54,380 在读取一个字符 从键盘输入的时间。 241 00:10:54,380 --> 00:10:58,240 然后,你会看到的GetString 确实是每次用完, 242 00:10:58,240 --> 00:11:02,280 说,16字节的内存,它使用 malloc的,或一个表弟物, 243 00:11:02,280 --> 00:11:06,810 分配更多的内存,复制旧 内存成新的,然后爬 244 00:11:06,810 --> 00:11:09,900 一直以来,得到一个字符的时间, 当它用完 245 00:11:09,900 --> 00:11:13,370 的内存块,它扔了出去,待价而沽 更大的内存块复制旧 246 00:11:13,370 --> 00:11:14,750 进入新的和重复。 247 00:11:14,750 --> 00:11:18,480 ,它是一个真正的痛苦其实 实现的东西一样简单 248 00:11:18,480 --> 00:11:19,710 得到来自用户的输入。 249 00:11:19,710 --> 00:11:21,090 >> 所以,你可以使用scanf函数。 250 00:11:21,090 --> 00:11:22,430 您可以使用其他类似功能。 251 00:11:22,430 --> 00:11:25,420 而很多课本和在线 例子,但他们都 252 00:11:25,420 --> 00:11:27,210 脆弱到这样的问题。 253 00:11:27,210 --> 00:11:29,550 最终,得到一个segfault 是有点恼人。 254 00:11:29,550 --> 00:11:30,680 这不是为用户好。 255 00:11:30,680 --> 00:11:33,560 >> 但是,在最坏情况下,这是什么 它从根本上把你的 256 00:11:33,560 --> 00:11:37,160 代码的风险吗? 257 00:11:37,160 --> 00:11:39,250 某种攻击,有可能。 258 00:11:39,250 --> 00:11:41,680 我们谈到了一个这样的攻击 - 堆栈溢出。 259 00:11:41,680 --> 00:11:44,660 但在一般情况下,如果你允许 缓冲区溢出,像我们做了一个 260 00:11:44,660 --> 00:11:48,070 几个星期前,只是写 以上的“你好”,你在堆栈上 261 00:11:48,070 --> 00:11:52,330 的确可以考虑,潜在的, 计算机上,或者至少在数据 262 00:11:52,330 --> 00:11:53,510 不属于你。 263 00:11:53,510 --> 00:11:55,970 >> 因此,在短期,这就是为什么我们有 这些培训轮子。 264 00:11:55,970 --> 00:11:59,090 但是现在,我们开始把他们赶走, 因为我们的课程不再需要, 265 00:11:59,090 --> 00:12:00,610 必须的,来自用户的输入。 266 00:12:00,610 --> 00:12:03,960 但在问题的情况下,设置6个, 您的输入将来自一个巨大的 267 00:12:03,960 --> 00:12:07,520 一些字典文件150 奇千言万语。 268 00:12:07,520 --> 00:12:10,330 >> 所以,你将不必担心 用户任意输入。 269 00:12:10,330 --> 00:12:13,720 我们会给你一些假设 关于该文件。 270 00:12:13,720 --> 00:12:20,340 指针上有任何疑问或scanf 或用户输入一般? 271 00:12:20,340 --> 00:12:24,450 >> 所有的权利,所以在一个快速浏览一下,然后 尾随从两个星期前的话题。 272 00:12:24,450 --> 00:12:28,590 这是一个struct这个概念。 273 00:12:28,590 --> 00:12:34,180 不 - 这个概念, 结构,这是什么? 274 00:12:34,180 --> 00:12:35,430 什么结构为我们做什么? 275 00:12:35,430 --> 00:12:39,280 276 00:12:39,280 --> 00:12:39,860 >> 定义 - 277 00:12:39,860 --> 00:12:41,710 对不起? 278 00:12:41,710 --> 00:12:42,820 定义一个变量的类型。 279 00:12:42,820 --> 00:12:44,410 因此,排序。 280 00:12:44,410 --> 00:12:46,180 其实我们两个主题结合。 281 00:12:46,180 --> 00:12:49,510 因此,用typedef,回想一下,我们可以 声明一个类型,像我们自己的 282 00:12:49,510 --> 00:12:51,500 的代名词,就像字符串的char *。 283 00:12:51,500 --> 00:12:56,200 但是,我们可以使用typedef和结构 真正创造我们自己的数据结构。 284 00:12:56,200 --> 00:12:59,600 >> 举例来说,如果我回去到gedit中 这里只是一个瞬间,我先走 285 00:12:59,600 --> 00:13:08,230 做这样的事情,让我节省 本作,让我们说,structs.c 286 00:13:08,230 --> 00:13:10,840 暂时我只是 继续前进,包括 287 00:13:10,840 --> 00:13:14,360 standardio.h,INT主要无效。 288 00:13:14,360 --> 00:13:18,960 然后在这里,假设,我想 写一个程序,存储 289 00:13:18,960 --> 00:13:21,840 多个学生从多个 房屋,例如。 290 00:13:21,840 --> 00:13:24,430 因此,它是像一个registrarial的 某种数据库。 291 00:13:24,430 --> 00:13:29,550 >> 所以,如果我需要一个学生的名字,我 可能会做一些像char *的名称, 292 00:13:29,550 --> 00:13:31,570 我会做这样的事情 - 293 00:13:31,570 --> 00:13:34,410 其实,让我们使用CS50库 只是一瞬间,使这个 294 00:13:34,410 --> 00:13:38,380 简单一点的,所以我们可以借用 那些几十行代码。 295 00:13:38,380 --> 00:13:39,340 只是,让我们保持它的简单。 296 00:13:39,340 --> 00:13:42,610 我们会保持它的字符串, 现在则由GetString引发。 297 00:13:42,610 --> 00:13:47,420 >> 因此,我要求现在,我已经存储的名称 一些学生,房子 298 00:13:47,420 --> 00:13:50,240 一些学生,只需使用变量 像我们一样,在第一个星期。 299 00:13:50,240 --> 00:13:52,370 但是,假设我现在要支持 多个学生。 300 00:13:52,370 --> 00:13:58,460 好吧,让我的直觉是做 字符串名称2,得到的GetString,串 301 00:13:58,460 --> 00:14:01,370 house2得到的GetString。 302 00:14:01,370 --> 00:14:05,850 然后我们的第三个学生, 让我们做NAME3 GetString的。 303 00:14:05,850 --> 00:14:09,170 >> 所有的权利,所以这是希望引人注目 作为一种愚蠢的, 304 00:14:09,170 --> 00:14:11,580 因为这个过程是真的从来没有 将要结束,它只是要 305 00:14:11,580 --> 00:14:13,130 使我的代码看起来更糟糕 和每况愈下。 306 00:14:13,130 --> 00:14:14,810 但我们解决了这个在本周二也。 307 00:14:14,810 --> 00:14:19,450 我们比较干净的解决方案是什么 当我们有多个变量, 308 00:14:19,450 --> 00:14:23,580 相同的数据类型都有关,但 我们不希望这种残暴的混乱 309 00:14:23,580 --> 00:14:26,870 同样命名的变量? 310 00:14:26,870 --> 00:14:30,060 我们做了什么呢? 311 00:14:30,060 --> 00:14:31,260 >> 所以我想我听到了几个地方。 312 00:14:31,260 --> 00:14:32,590 我们有一个数组。 313 00:14:32,590 --> 00:14:37,110 如果你想的多个实例 的东西,为什么不要我们清理这一切 314 00:14:37,110 --> 00:14:39,540 ,只是说,给我 数组的名字呢? 315 00:14:39,540 --> 00:14:41,640 >> 现在,让我们的硬编码3。 316 00:14:41,640 --> 00:14:44,450 然后给我另一个数组 称为房子,让我 317 00:14:44,450 --> 00:14:45,800 现在硬编码3。 318 00:14:45,800 --> 00:14:49,220 而且我已经大规模清理 乱,我只是创建。 319 00:14:49,220 --> 00:14:52,400 现在,我还是硬编码3,但即使 3可以动态来自 320 00:14:52,400 --> 00:14:54,350 用户,或者argv的或类似。 321 00:14:54,350 --> 00:14:55,720 所以这已经是清洁。 322 00:14:55,720 --> 00:15:00,100 >> 但恼人的是, 现在,即使名字是某种 323 00:15:00,100 --> 00:15:02,280 根本联系 学生的家 - 324 00:15:02,280 --> 00:15:04,720 这是一个学生,我真的 要代表 - 325 00:15:04,720 --> 00:15:08,080 我现在有两个平行的阵列 在这个意义上,他们是 326 00:15:08,080 --> 00:15:13,930 相同的大小,名称托架0 想必映射到房子支架0, 327 00:15:13,930 --> 00:15:16,600 和名称支架1地图 房屋支架1。 328 00:15:16,600 --> 00:15:19,280 换句话说,该学生生活在 那房子,房子和其他学生 329 00:15:19,280 --> 00:15:20,530 生活在其他的房子。 330 00:15:20,530 --> 00:15:23,720 但可以肯定,这可能是 做得更干净。 331 00:15:23,720 --> 00:15:24,990 >> 好吧,它可以,其实。 332 00:15:24,990 --> 00:15:28,730 并让我继续前进,打开 了structs.h,你会 333 00:15:28,730 --> 00:15:31,130 在这里看到这个想法。 334 00:15:31,130 --> 00:15:34,905 请注意,我用的typedef,因为你 刚才提到申报我们 335 00:15:34,905 --> 00:15:35,570 自己的数据类型。 336 00:15:35,570 --> 00:15:39,660 但是,我也使用此关键字 称为struct这给了我一个新的 337 00:15:39,660 --> 00:15:40,790 的数据结构。 338 00:15:40,790 --> 00:15:43,980 >> 而这一数据结构,我要求是怎么回事 有两件事情里面 339 00:15:43,980 --> 00:15:47,060 - 一个字符串名为name, 一个字符串,称为房子。 340 00:15:47,060 --> 00:15:49,820 和名字我要去给 将这样的数据结构 341 00:15:49,820 --> 00:15:51,005 被称为学生。 342 00:15:51,005 --> 00:15:54,030 我可以打电话给我想要的任何东西, 但这种语义 343 00:15:54,030 --> 00:15:55,810 我感觉到,在我的脑海里。 344 00:15:55,810 --> 00:15:59,160 >> 所以,现在,如果我打开了一个更好的版本 的节目,我开始写 345 00:15:59,160 --> 00:16:00,390 那里,让我滚动到顶部。 346 00:16:00,390 --> 00:16:03,190 还有一些更多的代码行 在这里,但让我专注 347 00:16:03,190 --> 00:16:04,160 一个时刻。 348 00:16:04,160 --> 00:16:07,790 我宣布一个恒定的所谓学生 硬编码的现在。 349 00:16:07,790 --> 00:16:11,110 但现在,注意到何洁 我的代码开始就搞定了。 350 00:16:11,110 --> 00:16:15,030 >> 在22行,我宣布 阵列的学生。 351 00:16:15,030 --> 00:16:18,760 并注意学生显然是 现在的数据类型。 352 00:16:18,760 --> 00:16:23,360 因为在顶部的文件,通知 我已经包含了该头文件 353 00:16:23,360 --> 00:16:24,820 我拉起刚才。 354 00:16:24,820 --> 00:16:28,820 该头文件很简单 这个定义一个学生。 355 00:16:28,820 --> 00:16:32,470 >> 所以,现在,我创建了自己的自定义数据 类型,作者的C年 356 00:16:32,470 --> 00:16:33,890 前事先没有想到的。 357 00:16:33,890 --> 00:16:34,570 但没有问题。 358 00:16:34,570 --> 00:16:35,870 我可以做自己。 359 00:16:35,870 --> 00:16:39,050 所以这是一个阵列称为学生, 其每名成员 360 00:16:39,050 --> 00:16:41,100 是学生结构。 361 00:16:41,100 --> 00:16:44,270 我想三个 在数组中。 362 00:16:44,270 --> 00:16:46,030 >> 而现在,没有休息 这个程序怎么办? 363 00:16:46,030 --> 00:16:47,550 我需要的东西有点武断。 364 00:16:47,550 --> 00:16:51,450 因此,从24日起在网上, 我遍历从0到3。 365 00:16:51,450 --> 00:16:54,000 然后我再问用户 学生的名字。 366 00:16:54,000 --> 00:16:56,110 然后我用则由GetString引发如前。 367 00:16:56,110 --> 00:16:59,410 然后,我问学生的房子, 我用则由GetString引发像以前那样。 368 00:16:59,410 --> 00:17:01,780 >> 但通知 - 稍微新 一块语法 - 369 00:17:01,780 --> 00:17:07,010 我仍然可以索引到的第i个学生, 但我怎么得到的具体数据 370 00:17:07,010 --> 00:17:08,354 领域里面的结构吗? 371 00:17:08,354 --> 00:17:11,770 那么,什么是显然 新语法? 372 00:17:11,770 --> 00:17:13,339 这仅仅是点操作符。 373 00:17:13,339 --> 00:17:14,510 >> 这之前,我们还没有真正见过。 374 00:17:14,510 --> 00:17:17,819 你已经看到了它的pset五,如果你 已经跌位图文件。 375 00:17:17,819 --> 00:17:22,372 但点只是意味着在这里面, 结构或多个领域,给点 376 00:17:22,372 --> 00:17:24,510 名称,或者给我点的房子。 377 00:17:24,510 --> 00:17:28,690 这意味着内部结构 得到这些特定的领域。 378 00:17:28,690 --> 00:17:30,200 >> 这个程序的其余部分做什么? 379 00:17:30,200 --> 00:17:31,190 这还不是全部,性感。 380 00:17:31,190 --> 00:17:34,640 请注意,我再次循环从0到3, 我只是创造英语 381 00:17:34,640 --> 00:17:40,500 短语,比如某某等 这样的房子,通过在点名称 382 00:17:40,500 --> 00:17:43,320 的第i个学生和他们的 房子,以及。 383 00:17:43,320 --> 00:17:47,560 >> 最后,现在我们将开始得到 肛门,现在我们 384 00:17:47,560 --> 00:17:49,580 熟悉什么malloc和 其他功能已经 385 00:17:49,580 --> 00:17:50,570 做这一切的时候。 386 00:17:50,570 --> 00:17:54,220 为什么我一定要释放这两个名字 和房子,即使我 387 00:17:54,220 --> 00:17:56,960 没有调用malloc? 388 00:17:56,960 --> 00:17:58,020 >> GetString的了。 389 00:17:58,020 --> 00:18:00,930 那是肮脏的小秘密 几个星期,但GetString的 390 00:18:00,930 --> 00:18:03,530 遍布泄漏内存 把所有学期迄今为止。 391 00:18:03,530 --> 00:18:05,990 valgrand终于将 揭示给我们。 392 00:18:05,990 --> 00:18:10,730 >> 但是,它不是一个大不了的,因为我知道, 我可以简单地释放名称 393 00:18:10,730 --> 00:18:15,750 和房子,虽然在技术上, 超强,安全,应该是我 394 00:18:15,750 --> 00:18:17,890 做一些错误检查。 395 00:18:17,890 --> 00:18:19,040 什么是你的直觉告诉你吗? 396 00:18:19,040 --> 00:18:22,480 我应该怎么检查 之前,我释放什么是 397 00:18:22,480 --> 00:18:25,470 字符串,又名一个char *? 398 00:18:25,470 --> 00:18:33,460 >> 我真的应该进行检查,如果学生 支架I点名称不 399 00:18:33,460 --> 00:18:34,840 等于空。 400 00:18:34,840 --> 00:18:40,400 然后,它会确定先走,并免费 该指针,相同或其他 401 00:18:40,400 --> 00:18:41,160 别人。 402 00:18:41,160 --> 00:18:46,860 如果学生支架I点的房子是不是 等于为null,这将保护 403 00:18:46,860 --> 00:18:52,520 对角落的情况 的形式返回类似空。 404 00:18:52,520 --> 00:18:57,310 而且我们刚才也看到了,printf的 保护我们在这里只是说 405 00:18:57,310 --> 00:18:58,990 null,这是怎么回事,看起来很怪异。 406 00:18:58,990 --> 00:19:02,340 但至少它不会出现段错误, 正如我们所看到。 407 00:19:02,340 --> 00:19:05,990 >> 好吧,让我在这里做另一件事。 结构-0是一个愚蠢的计划 408 00:19:05,990 --> 00:19:09,700 因为我输入所有数据,然后 它失去了,一旦程序结束。 409 00:19:09,700 --> 00:19:10,940 但是,让我继续前进,做到这一点。 410 00:19:10,940 --> 00:19:12,830 让我做终端 窗口有点大了。 411 00:19:12,830 --> 00:19:17,000 让我结构-1, 这是一个新版本。 412 00:19:17,000 --> 00:19:18,520 >> 我会在一点点放大。 413 00:19:18,520 --> 00:19:21,620 现在让我跑点 削减结构1。 414 00:19:21,620 --> 00:19:22,590 学生的名字 - 415 00:19:22,590 --> 00:19:31,500 大卫·马瑟,让我们做罗布·柯克兰, 让劳伦利维瑞特。 416 00:19:31,500 --> 00:19:33,650 现在是什么有趣的通知 - 417 00:19:33,650 --> 00:19:35,540 我只知道这是因为 我写的程序 - 418 00:19:35,540 --> 00:19:38,930 现在我目前有一个文件 目录students.csv。 419 00:19:38,930 --> 00:19:40,420 你们当中有些人可能已经看到 这些在现实世界中。 420 00:19:40,420 --> 00:19:42,980 >> 什么是CSV文件? 421 00:19:42,980 --> 00:19:44,170 逗号分隔值。 422 00:19:44,170 --> 00:19:46,670 它有点像一个穷人的 版本的Excel文件。 423 00:19:46,670 --> 00:19:50,580 这是一个表的行和列, 你可以打开一个程序如Excel, 424 00:19:50,580 --> 00:19:51,800 或在Mac上的数字。 425 00:19:51,800 --> 00:19:55,180 >> 如果我在这里打开此文件gedit中, 通知 - 数字是不存在的。 426 00:19:55,180 --> 00:19:57,360 这只是gedit的告诉 我行号。 427 00:19:57,360 --> 00:19:59,740 的第一行通知 文件是大卫和马瑟。 428 00:19:59,740 --> 00:20:01,450 下一行是罗布逗号柯克兰。 429 00:20:01,450 --> 00:20:04,170 第三行是劳伦 逗号利维瑞特。 430 00:20:04,170 --> 00:20:05,480 >> 所以我创建了什么? 431 00:20:05,480 --> 00:20:09,580 我现在写的C程序 可以有效地生成电子表格 432 00:20:09,580 --> 00:20:11,840 可以打开在 如Excel程序。 433 00:20:11,840 --> 00:20:15,520 并非所有引人注目的一个数据集,但 如果你有更大的大块 434 00:20:15,520 --> 00:20:18,440 数据,你其实是要 操纵,使图表和 435 00:20:18,440 --> 00:20:21,260 喜欢,这也许是一个 的方式来创建数据。 436 00:20:21,260 --> 00:20:25,370 此外,特装车点实际上超共同 只是简单的数据存储 - 437 00:20:25,370 --> 00:20:28,940 雅虎财经,举例来说,如果你得到 通过他们所谓的股票行情 438 00:20:28,940 --> 00:20:33,180 API的免费服务,让您 获取当前到最新的库存 439 00:20:33,180 --> 00:20:35,650 公司的报价,他们 在给数据 440 00:20:35,650 --> 00:20:37,800 超简单的CSV格式。 441 00:20:37,800 --> 00:20:39,380 >> 所以,我们是怎么做到的呢? 442 00:20:39,380 --> 00:20:42,530 注意到,这一计划的最 几乎是相同的。 443 00:20:42,530 --> 00:20:46,870 但是请注意,在这里,而不是打印 学生,上线35 444 00:20:46,870 --> 00:20:51,040 开始,我要求我保存 学生到磁盘,保存文件。 445 00:20:51,040 --> 00:20:53,630 >> 因此,注意到我声明一个FILE * - 446 00:20:53,630 --> 00:20:57,260 现在,这是一种异常C. 无论出于何种原因,文件是全部大写, 447 00:20:57,260 --> 00:21:00,690 这是不是像大多数其他数据类型 但是这是一个内置的 448 00:21:00,690 --> 00:21:02,320 数据类型,文件*。 449 00:21:02,320 --> 00:21:05,900 我声明一个指针到一个文件, 你怎么能想到的。 450 00:21:05,900 --> 00:21:08,070 >> FOPEN意味着打开的文件。 451 00:21:08,070 --> 00:21:09,470 你想打开什么文件? 452 00:21:09,470 --> 00:21:12,620 我想打开一个文件,我将 任意调用students.csv。 453 00:21:12,620 --> 00:21:14,480 我可以打电话,我想要的任何东西。 454 00:21:14,480 --> 00:21:15,200 >> 再取一个猜测。 455 00:21:15,200 --> 00:21:18,960 第二个参数做什么 FOPEN大概是这个意思吗? 456 00:21:18,960 --> 00:21:21,480 右,w代表写, 是读r为。 457 00:21:21,480 --> 00:21:24,120 还有一个附加的,如果你 要添加行,而不是 458 00:21:24,120 --> 00:21:25,200 覆盖整个事情。 459 00:21:25,200 --> 00:21:28,005 >> 但我只是想创建这个文件 一次,所以我会使用报价引文结束瓦特。 460 00:21:28,005 --> 00:21:31,880 而且我知道,只有在读取 文档或手册页。 461 00:21:31,880 --> 00:21:35,100 如果文件不为空 - 换句话说, 如果没事就去那里错了 - 462 00:21:35,100 --> 00:21:37,820 让我遍历 从0到3的学生。 463 00:21:37,820 --> 00:21:40,410 >> 现在注意到有什么东西 曾经如此略有不同 464 00:21:40,410 --> 00:21:42,110 行约41。 465 00:21:42,110 --> 00:21:42,960 这不是printf的。 466 00:21:42,960 --> 00:21:46,530 fprintf printf的文件。 467 00:21:46,530 --> 00:21:47,790 因此,它会写入文件。 468 00:21:47,790 --> 00:21:48,860 哪个文件? 469 00:21:48,860 --> 00:21:53,630 您指定的指针 作为第一个参数。 470 00:21:53,630 --> 00:21:55,940 >> 然后,我们指定格式字符串。 471 00:21:55,940 --> 00:21:59,660 然后,我们指定我们想要什么字符串 插头的第一%S和 472 00:21:59,660 --> 00:22:04,320 然后另一个变量或 第二个%秒。 473 00:22:04,320 --> 00:22:06,760 然后关闭文件FCLOSE。 474 00:22:06,760 --> 00:22:09,380 比我释放内存之前,虽然 我应该回去,并添加 475 00:22:09,380 --> 00:22:10,540 一些检查为空。 476 00:22:10,540 --> 00:22:12,090 >> 就是这样。 477 00:22:12,090 --> 00:22:16,960 FOPEN,fprintf等FCLOSE给我 创建文本文件的能力。 478 00:22:16,960 --> 00:22:19,640 现在,你会看到问题集五, 涉及图像,您将使用 479 00:22:19,640 --> 00:22:20,990 二进制文件来代替。 480 00:22:20,990 --> 00:22:24,200 但是从根本上说,这个想法是一样的, 即使功能,你会 481 00:22:24,200 --> 00:22:28,710 看到的是有一点点不同。 482 00:22:28,710 --> 00:22:32,580 >> 所以旋风之旅,但你会得到 太熟悉文件I/O-- 483 00:22:32,580 --> 00:22:34,960 输入和输出 - pset中五。 484 00:22:34,960 --> 00:22:38,607 而任何疑问 初始的基础在这里? 485 00:22:38,607 --> 00:22:39,857 是吗? 486 00:22:39,857 --> 00:22:41,880 487 00:22:41,880 --> 00:22:43,710 >> 如果你试图释放一个空值? 488 00:22:43,710 --> 00:22:48,880 我相信,除非已经得到了自由 对用户来说更加友好,你可以 489 00:22:48,880 --> 00:22:49,890 潜在的段错误。 490 00:22:49,890 --> 00:22:54,160 它传递空是不好的,因为我不 相信自由困扰为你检查, 491 00:22:54,160 --> 00:22:57,330 因为它可能会是浪费 为它做自己的时间 492 00:22:57,330 --> 00:22:59,022 在世界上的每个人。 493 00:22:59,022 --> 00:23:00,590 好问题,虽然。 494 00:23:00,590 --> 00:23:04,300 >> 好,那么这种得到 我们一个有趣的话题。 495 00:23:04,300 --> 00:23:07,010 习题集的主题 五是取证。 496 00:23:07,010 --> 00:23:08,420 至少这是一个部分 问题集。 497 00:23:08,420 --> 00:23:12,030 取证一般是指在 恢复的信息,可能或 498 00:23:12,030 --> 00:23:14,110 可能没有被删除 故意的。 499 00:23:14,110 --> 00:23:18,680 所以我想,我想给你一个快速 什么味道真的 500 00:23:18,680 --> 00:23:21,230 下面这段时间 引擎盖您的计算机。 501 00:23:21,230 --> 00:23:23,960 >> 举例来说,如果你里面有你 笔记本电脑或桌面电脑一 502 00:23:23,960 --> 00:23:28,040 硬盘驱动器,它可以通过机械 设备实际旋转 - 503 00:23:28,040 --> 00:23:31,650 有圆形的东西称为盘片 看起来很喜欢我 504 00:23:31,650 --> 00:23:34,540 刚刚在这里,虽然在屏幕上 这是越来越多的老同学。 505 00:23:34,540 --> 00:23:37,370 这是三个和一个半英寸 硬盘驱动器。 506 00:23:37,370 --> 00:23:40,070 三个半英寸指 的东西,当你安装它 507 00:23:40,070 --> 00:23:40,890 在一台计算机。 508 00:23:40,890 --> 00:23:44,890 >> 你们中许多人的家伙现在在您的笔记本电脑 有固态硬盘或SSD, 509 00:23:44,890 --> 00:23:46,260 没有移动部件。 510 00:23:46,260 --> 00:23:49,170 他们更像RAM不像 这些机械设备。 511 00:23:49,170 --> 00:23:51,450 但这些想法仍然是相同的, 当然,因为它们涉及 512 00:23:51,450 --> 00:23:52,790 问题五。 513 00:23:52,790 --> 00:23:57,400 >> 如果你想想现在的硬盘驱动器 代表了一圈,这 514 00:23:57,400 --> 00:23:58,930 在这里,我会得出这样的。 515 00:23:58,930 --> 00:24:02,290 当您在您的计算机上创建一个文件, 无论它是一个SSD,或在 516 00:24:02,290 --> 00:24:06,610 这种情况下,硬盘驱动器是较旧的学校, 该文件包括多个位。 517 00:24:06,610 --> 00:24:10,510 比方说,它的0和1, 一大堆的0和1。 518 00:24:10,510 --> 00:24:11,660 所以这是我的整个硬盘驱动器。 519 00:24:11,660 --> 00:24:13,225 这显然​​是一个相当大的文件。 520 00:24:13,225 --> 00:24:18,080 并且被使用在该0s和1s 部分的物理盘片。 521 00:24:18,080 --> 00:24:19,750 >> 那么,什么是物理部分? 522 00:24:19,750 --> 00:24:25,310 嗯,事实证明,在硬盘上, 至少在此类型中,有 523 00:24:25,310 --> 00:24:27,340 这些微小的磁性粒子。 524 00:24:27,340 --> 00:24:32,630 他们基本上有北部和 南极,因此,如果您 525 00:24:32,630 --> 00:24:35,710 打开其中一个,这些磁性颗粒 通过这种方式,你可能会说,这是 526 00:24:35,710 --> 00:24:36,720 较1。 527 00:24:36,720 --> 00:24:39,340 如果它是倒挂南下 北,你可能会说,这是 528 00:24:39,340 --> 00:24:40,390 代表一个0。 529 00:24:40,390 --> 00:24:43,660 >> 因此,在真实的物理世界,这是 你如何能代表的东西 530 00:24:43,660 --> 00:24:45,670 二进位的0状态和1。 531 00:24:45,670 --> 00:24:46,720 所以这是一个文件。 532 00:24:46,720 --> 00:24:49,300 有一大堆磁 是他们这样或颗粒 533 00:24:49,300 --> 00:24:51,920 通过这种方式,创建模式 0和1。 534 00:24:51,920 --> 00:24:56,760 >> 但事实证明,当你保存文件, 一些信息分开保存。 535 00:24:56,760 --> 00:25:00,000 所以这是一个小桌子, 一个目录,可以这么说。 536 00:25:00,000 --> 00:25:05,810 我会打电话给这列名, 我会打电话给这个列位置。 537 00:25:05,810 --> 00:25:08,850 >> 我要去说,假设 这是我的简历。 538 00:25:08,850 --> 00:25:14,050 我的resume.doc被存储在 位置,比方说123。 539 00:25:14,050 --> 00:25:15,390 我总是去该号码。 540 00:25:15,390 --> 00:25:18,810 但我只想说,就像 在RAM中,你可以把一个硬盘驱动器 541 00:25:18,810 --> 00:25:22,350 这是一个千兆字节或200千兆字节 TB级,你可以 542 00:25:22,350 --> 00:25:23,750 所有的字节数。 543 00:25:23,750 --> 00:25:26,480 你可以列出所有的8位块。 544 00:25:26,480 --> 00:25:29,030 >> 因此,我们会说,这 是123的位置。 545 00:25:29,030 --> 00:25:32,070 因此,这个目录里面,我的作业 系统会记住我 546 00:25:32,070 --> 00:25:34,250 简历是在位置123。 547 00:25:34,250 --> 00:25:36,850 但它变得有趣,当 你删除一个文件。 548 00:25:36,850 --> 00:25:37,820 >> 因此,例如 - 549 00:25:37,820 --> 00:25:40,790 令人欣慰的是,世界上大多数国家都有 捕捉到这 - 时会发生什么 550 00:25:40,790 --> 00:25:45,040 拖动文件到您的Mac OS垃圾桶 或Windows回收站? 551 00:25:45,040 --> 00:25:48,290 552 00:25:48,290 --> 00:25:50,510 这样做的目的是什么? 553 00:25:50,510 --> 00:25:53,860 这显然​​是要摆脱的文件, 但到底是什么行为拖动 554 00:25:53,860 --> 00:25:57,550 下降到废纸篓或 回收站在电脑上做的吗? 555 00:25:57,550 --> 00:25:59,230 >> 绝对没有,真的。 556 00:25:59,230 --> 00:26:00,320 这就像一个文件夹。 557 00:26:00,320 --> 00:26:01,800 这是一个特殊的文件夹,可以肯定的。 558 00:26:01,800 --> 00:26:04,460 但它实际上删除的文件? 559 00:26:04,460 --> 00:26:06,780 >> 哦,不,因为一些你可能 一直喜欢,哦,该死的,你没有 560 00:26:06,780 --> 00:26:07,420 意味着这样做。 561 00:26:07,420 --> 00:26:09,130 所以,你双击 垃圾桶或回收站。 562 00:26:09,130 --> 00:26:11,630 你周围戳,你已经恢复 只需拖动文件 563 00:26:11,630 --> 00:26:12,110 离开那里。 564 00:26:12,110 --> 00:26:14,420 所以很明显,它不一定 删除。 565 00:26:14,420 --> 00:26:15,990 >> OK,你聪明得多。 566 00:26:15,990 --> 00:26:18,860 你知道,只是拖动它到 垃圾桶或回收站并不意味着 567 00:26:18,860 --> 00:26:19,930 你清空垃圾桶。 568 00:26:19,930 --> 00:26:24,110 所以,你上去的菜单,和你说 清空废纸篓或清空回收站。 569 00:26:24,110 --> 00:26:25,360 然后会发生什么? 570 00:26:25,360 --> 00:26:29,070 571 00:26:29,070 --> 00:26:32,530 >> 是啊,所以它被删除,更是这样。 572 00:26:32,530 --> 00:26:37,660 但所发生的一切是这样的。 573 00:26:37,660 --> 00:26:45,350 电脑忘记 是resume.doc。 574 00:26:45,350 --> 00:26:47,400 >> 但什么也没有明显变化 在画面? 575 00:26:47,400 --> 00:26:51,390 576 00:26:51,390 --> 00:26:55,570 位,0和1,我要求的是 在现场的一些物理方面的 577 00:26:55,570 --> 00:26:56,280 硬件。 578 00:26:56,280 --> 00:26:57,110 他们还在那里。 579 00:26:57,110 --> 00:26:58,930 这只是电脑有 遗忘它们是什么。 580 00:26:58,930 --> 00:27:03,160 >> 因此,它本质上释放文件的 位的,所以它们可以被重复使用。 581 00:27:03,160 --> 00:27:06,940 但直到你创建更多的文件, 多个文件,多个文件 582 00:27:06,940 --> 00:27:12,150 概率,这些0和1, 这些磁性粒子,得到重用, 583 00:27:12,150 --> 00:27:16,220 上攻或右侧, 其他文件,0和1。 584 00:27:16,220 --> 00:27:17,980 >> 所以,你有这样的时间窗口。 585 00:27:17,980 --> 00:27:19,860 它不是可预测 长度,真的。 586 00:27:19,860 --> 00:27:22,240 这取决于你的硬盘的大小 驱动器和你有多少个文件 587 00:27:22,240 --> 00:27:23,490 你如何迅速做出新的。 588 00:27:23,490 --> 00:27:27,050 但是这期间的时间窗口 该文件仍然是完美的 589 00:27:27,050 --> 00:27:27,770 收回。 590 00:27:27,770 --> 00:27:31,050 >> 所以,如果你使用的程序如McAfee 或Norton尝试恢复 591 00:27:31,050 --> 00:27:35,680 数据,他们正在做的是试图 恢复这个所谓的目录 592 00:27:35,680 --> 00:27:37,340 弄清楚你的文件在哪里。 593 00:27:37,340 --> 00:27:40,605 有时诺顿和会说, 文件是可收回93%。 594 00:27:40,605 --> 00:27:42,020 那么,是什么意思呢? 595 00:27:42,020 --> 00:27:45,690 这只是意味着,其他一些文件 巧合的结束使用,也就是说, 596 00:27:45,690 --> 00:27:48,920 那些位出你的原始文件。 597 00:27:48,920 --> 00:27:51,950 >> 那么,什么是真正参与 在恢复数据? 598 00:27:51,950 --> 00:27:55,720 好吧,如果你不会有这样的事情 诺顿预先安装在电脑上, 599 00:27:55,720 --> 00:27:59,510 有时你可以做的是最好的看 在整个硬盘寻找 600 00:27:59,510 --> 00:28:00,510 的位模式。 601 00:28:00,510 --> 00:28:05,350 和问题集的主题之一 五是,你会搜索 602 00:28:05,350 --> 00:28:09,570 相当于一个硬盘驱动器,一个法医 形象从一个紧凑的闪存卡 603 00:28:09,570 --> 00:28:13,660 数码相机,搜索为0 和1,通常,具有较高的 604 00:28:13,660 --> 00:28:16,720 概率,代表 开始的JPEG图像。 605 00:28:16,720 --> 00:28:21,120 >> 你们可以收回这些图像 假设,如果我看到这个图案 606 00:28:21,120 --> 00:28:24,380 位法医形象, 的概率很高,这标志着 607 00:28:24,380 --> 00:28:25,650 开始的JPEG。 608 00:28:25,650 --> 00:28:29,520 如果我再次看到同样的模式, 可能标志着开始 609 00:28:29,520 --> 00:28:32,440 另一个JPEG格式,和其他 JPEG格式,和其他的JPEG。 610 00:28:32,440 --> 00:28:34,970 这通常是如何 数据恢复工作。 611 00:28:34,970 --> 00:28:37,870 关于JPEG文件有什么高兴的是,即使 的文件格式本身是有点 612 00:28:37,870 --> 00:28:44,400 复杂,每一个这样的开头 文件其实是相当可识别 613 00:28:44,400 --> 00:28:47,370 和简单,因为你会看到, 如果你还没有准备好。 614 00:28:47,370 --> 00:28:50,270 >> 因此,让我们来仔细看看下面 正是一直罩 615 00:28:50,270 --> 00:28:53,360 回事,这些0和1 ,给你多一点的 616 00:28:53,360 --> 00:28:55,330 上下文这个特殊的挑战。 617 00:28:55,330 --> 00:28:55,510 >> [视频回放] 618 00:28:55,510 --> 00:28:58,700 >> ,如果您的电脑存储最 其永久性的数据。 619 00:28:58,700 --> 00:29:03,390 要做到这一点,数据从RAM 随着软件信号,告诉 620 00:29:03,390 --> 00:29:06,110 硬盘驱动器如何将这些数据存储。 621 00:29:06,110 --> 00:29:09,410 硬盘驱动器电路翻译 这些信号转换成电压 622 00:29:09,410 --> 00:29:10,870 波动的影响。 623 00:29:10,870 --> 00:29:14,970 这些,反过来,控制硬盘驱动器的 移动部件,一些数 624 00:29:14,970 --> 00:29:17,910 留在移动部件 现代计算机。 625 00:29:17,910 --> 00:29:22,130 >> 部分的信号控制电机 其中旋转金属涂层盘片。 626 00:29:22,130 --> 00:29:25,470 您的数据实际上是存储 这些盘片上。 627 00:29:25,470 --> 00:29:28,610 其他信号将读/写 头读取或 628 00:29:28,610 --> 00:29:30,710 写在盘片上的数据。 629 00:29:30,710 --> 00:29:35,450 这个机器,一个人如此精确 头发甚至不能之间传递 630 00:29:35,450 --> 00:29:37,280 磁头和旋转盘片。 631 00:29:37,280 --> 00:29:40,316 然而,这一切都以惊人的速度。 632 00:29:40,316 --> 00:29:40,660 >> [END视频播放] 633 00:29:40,660 --> 00:29:42,190 >> 国宝马兰:在一个小放大 更深现在什么 634 00:29:42,190 --> 00:29:44,360 实际上这些盘片上。 635 00:29:44,360 --> 00:29:44,720 >> [视频回放] 636 00:29:44,720 --> 00:29:47,660 >> - 让我们来看看,在我们刚才 看到慢动作。 637 00:29:47,660 --> 00:29:51,710 当一个简短的电脉冲 发送到读/写头,如果翻转 638 00:29:51,710 --> 00:29:54,650 一个微小的电磁 的一小部分的第二个。 639 00:29:54,650 --> 00:29:58,970 磁铁创建一个字段,该字段 一个微小的,微小的改变极性 640 00:29:58,970 --> 00:30:02,850 部的金属颗粒 大衣每个盘片表面。 641 00:30:02,850 --> 00:30:05,940 >> 这些微小的一个模式系列, 充电区,在磁盘上的 642 00:30:05,940 --> 00:30:08,470 表示的一个位 二进制数中的数据 643 00:30:08,470 --> 00:30:10,530 由电脑系统使用。 644 00:30:10,530 --> 00:30:13,775 现在,如果当前发送的一种方法 通过读/写头,该地区 645 00:30:13,775 --> 00:30:15,970 是在一个方向上极化。 646 00:30:15,970 --> 00:30:17,950 如果当前的发送,在 相反方向上, 647 00:30:17,950 --> 00:30:19,930 极化反转。 648 00:30:19,930 --> 00:30:22,370 >> 您是怎样从硬盘的数据? 649 00:30:22,370 --> 00:30:24,090 只要相反的过程。 650 00:30:24,090 --> 00:30:26,550 因此,它是在磁盘上的颗粒 获取中的电流 651 00:30:26,550 --> 00:30:27,960 读/写头移动。 652 00:30:27,960 --> 00:30:30,700 这些放在一起百万 磁化段, 653 00:30:30,700 --> 00:30:32,160 你已经得到了一个文件。 654 00:30:32,160 --> 00:30:36,060 >> 现在,一个单一的文件件 遍布驱动器的 655 00:30:36,060 --> 00:30:39,970 盘片的一塌糊涂,有点像 你的办公桌上的文件。 656 00:30:39,970 --> 00:30:43,500 因此,一个特殊的额外的文件跟踪 这里的一切是。 657 00:30:43,500 --> 00:30:45,985 难道你不希望你有 类似的东西? 658 00:30:45,985 --> 00:30:46,470 >> [END视频播放] 659 00:30:46,470 --> 00:30:47,820 >> 国宝MALAN:OK,大概不会。 660 00:30:47,820 --> 00:30:52,070 所以,你们的许多球员 从小一起长大的这些吗? 661 00:30:52,070 --> 00:30:53,970 OK,所以越来越少 表决时,每一年。 662 00:30:53,970 --> 00:30:56,550 不过,我很高兴你至少熟悉 与他们,因为这和我们自己的 663 00:30:56,550 --> 00:31:00,520 可悲的是,书的演示,死一个非常 熟悉拖死。 664 00:31:00,520 --> 00:31:04,010 >> 但是,这是我,至少,早在 高中,用于备份。 665 00:31:04,010 --> 00:31:08,110 它是令人惊异的,因为你 可以存储140兆字节 666 00:31:08,110 --> 00:31:08,930 这个特定的磁盘。 667 00:31:08,930 --> 00:31:12,260 这是高密度版本, 所指示的HD,其中有 668 00:31:12,260 --> 00:31:14,240 这意味着之前今天的高清视频。 669 00:31:14,240 --> 00:31:16,400 >> 标准密度为800千字节。 670 00:31:16,400 --> 00:31:18,640 而在这之前,有 400千字节的磁盘。 671 00:31:18,640 --> 00:31:23,120 而在这之前,共有5和1/4 英寸磁盘,这是真正的软盘, 672 00:31:23,120 --> 00:31:25,680 和一点点更宽,更高 比这里这些事。 673 00:31:25,680 --> 00:31:29,150 但实际上你可以看到所谓的 这些磁盘的软盘方面。 674 00:31:29,150 --> 00:31:32,630 >> 和功能,它们实际上是 非常相似,在硬盘驱动器 675 00:31:32,630 --> 00:31:33,570 至少这种类型。 676 00:31:33,570 --> 00:31:37,270 同样,固态硬盘在新电脑 工作方式略有不同。 677 00:31:37,270 --> 00:31:41,530 但是,如果你移动,小金属卡, 实际上,你可以看到一个小的cookie, 678 00:31:41,530 --> 00:31:42,560 或拼盘。 679 00:31:42,560 --> 00:31:43,830 >> 它不是像这样的金属。 680 00:31:43,830 --> 00:31:46,000 其实这其中的一些便宜 塑料材料制成。 681 00:31:46,000 --> 00:31:46,750 你可以摆动它的那种。 682 00:31:46,750 --> 00:31:50,310 你trully只是抹去一些 位或磁性颗粒的数量 683 00:31:50,310 --> 00:31:51,220 从该磁盘。 684 00:31:51,220 --> 00:31:52,710 >> 令人欣慰的是,它没有什么。 685 00:31:52,710 --> 00:31:55,790 如果这件事情的方式 - 并覆盖 你的眼睛和你的邻居 - 686 00:31:55,790 --> 00:31:58,865 你可以只是一种拉 整个鞘关闭这样的。 687 00:31:58,865 --> 00:32:01,900 但是,有一个小弹簧,所以 知道你的眼睛。 688 00:32:01,900 --> 00:32:03,620 所以,现在你有一个真正的软盘。 689 00:32:03,620 --> 00:32:07,090 >> 什么显着 在尽可能多的是,因为这是一个 690 00:32:07,090 --> 00:32:10,830 一个更大的小规模的代表性 硬盘驱动器,这些东西都是超, 691 00:32:10,830 --> 00:32:11,590 超级简单的。 692 00:32:11,590 --> 00:32:15,170 如果你捏它的底部,现在 该金属的东西,和剥离 693 00:32:15,170 --> 00:32:20,990 他们打开,有两件 感到,并且所谓的软盘 694 00:32:20,990 --> 00:32:22,930 一块金属在里面。 695 00:32:22,930 --> 00:32:25,990 >> 并有去一半 我的磁盘的内容。 696 00:32:25,990 --> 00:32:27,540 去他们的另一半。 697 00:32:27,540 --> 00:32:31,375 但是这一切,里面纺纱 您的计算机在昔日。 698 00:32:31,375 --> 00:32:35,220 699 00:32:35,220 --> 00:32:38,310 >> 再次,把这种成角度, 有多大你的大部分 700 00:32:38,310 --> 00:32:39,560 硬盘驱动器,这些天? 701 00:32:39,560 --> 00:32:41,960 702 00:32:41,960 --> 00:32:46,230 500千兆字节,TB级,也许在 一台台式电脑,3,2 TB的 703 00:32:46,230 --> 00:32:47,630 TB级,4 TB的,对不对? 704 00:32:47,630 --> 00:32:52,480 这是一个兆字节,或采取 甚至不能符合一个典型的MP3 705 00:32:52,480 --> 00:32:55,310 这些天了,还是有些 类似的音乐文件。 706 00:32:55,310 --> 00:32:59,500 >> 有那么一点点的纪念品今天为你, 也能帮助处境是什么 707 00:32:59,500 --> 00:33:03,570 我们将采取理所当然的 现在的问题设置5个。 708 00:33:03,570 --> 00:33:04,820 所以,那些是你的保持。 709 00:33:04,820 --> 00:33:07,340 710 00:33:07,340 --> 00:33:13,370 因此,让我这里将成为过渡 花下的pset。 711 00:33:13,370 --> 00:33:18,470 所以我们现在已经设置这个页面 - 哦, 一对夫妇很快公布。 712 00:33:18,470 --> 00:33:21,730 >> 本星期五,如果您想加入CS50 吃午饭,去平常的地方, 713 00:33:21,730 --> 00:33:23,610 cs50.net/rsvp。 714 00:33:23,610 --> 00:33:25,100 最终项目 - 715 00:33:25,100 --> 00:33:28,520 所以每教学大纲,我们已经发布了 项目最终规范已经。 716 00:33:28,520 --> 00:33:31,410 要认识到,这并不意味着 这是由于特别快。 717 00:33:31,410 --> 00:33:33,990 它的贴吧,真的,只是为了得到 你们想着它。 718 00:33:33,990 --> 00:33:37,620 果然,有一个超级显著 将解决你的百分比 719 00:33:37,620 --> 00:33:40,780 最终项目的材料,我们 甚至还没有得到在课堂上, 720 00:33:40,780 --> 00:33:42,730 但下周初。 721 00:33:42,730 --> 00:33:45,530 >> 但请注意,该规范要求 几个不同的组件的 722 00:33:45,530 --> 00:33:46,190 最终的项目。 723 00:33:46,190 --> 00:33:49,590 第一,在几个星期内,是一种 建议前期,很随意的电子邮件 724 00:33:49,590 --> 00:33:52,760 你的TF告诉他,或者你在做什么 想为您的项目, 725 00:33:52,760 --> 00:33:53,650 没有承诺。 726 00:33:53,650 --> 00:33:56,710 建议将您的特定 的承诺,他说,在这里,这是什么 727 00:33:56,710 --> 00:33:57,770 我想为我的项目做。 728 00:33:57,770 --> 00:33:58,250 你觉得呢? 729 00:33:58,250 --> 00:33:58,650 太大? 730 00:33:58,650 --> 00:33:59,145 太小? 731 00:33:59,145 --> 00:34:00,330 是管理? 732 00:34:00,330 --> 00:34:02,230 你可以看到更多的细节。规范 733 00:34:02,230 --> 00:34:05,060 >> 几个星期后,状态 报告,这是一个类似的 734 00:34:05,060 --> 00:34:08,260 休闲电子邮件到TF说多么 不甘落后,你在你的最终 735 00:34:08,260 --> 00:34:12,360 项目的实施,其次是 CS50 Hackathon大家 736 00:34:12,360 --> 00:34:17,520 被邀请,这将是一个事件 下午8:00至7:00一个晚上 737 00:34:17,520 --> 00:34:19,150 AM第二天早晨。 738 00:34:19,150 --> 00:34:22,560 比萨,因为我可能会提到周 为零,将担任下午9:00, 739 00:34:22,560 --> 00:34:24,120 中国食品在凌晨1:00。 740 00:34:24,120 --> 00:34:27,929 而如果你还醒着上午5:00, 我们带你去IHOP早餐。 741 00:34:27,929 --> 00:34:31,310 >> 因此,黑客马拉松是其中一个比较 类中的难忘的经历。 742 00:34:31,310 --> 00:34:35,290 然后执行由于 然后高潮CS50展。 743 00:34:35,290 --> 00:34:38,070 在所有这些的更多细节 在今后几个星期。 744 00:34:38,070 --> 00:34:40,739 >> 但是,让我们回去的东西 旧学校 - 745 00:34:40,739 --> 00:34:41,920 再次,一个数组。 746 00:34:41,920 --> 00:34:45,040 所以数组是不错的,因为它解决 的问题,像我们看到的只是一个 747 00:34:45,040 --> 00:34:49,290 刚才学生结构 开始有点失控,如果我们 748 00:34:49,290 --> 00:34:52,405 希望有学生,学生, 学生点点点三,学生, 749 00:34:52,405 --> 00:34:54,400 一些任意数量的学生。 750 00:34:54,400 --> 00:34:58,850 >> 所以阵列,几个星期前,猛扑 并解决我们的问题不 751 00:34:58,850 --> 00:35:03,340 事先知道有多少东西 某种类型的,我们想要的。 752 00:35:03,340 --> 00:35:07,390 我们已经看到,结构可以帮助我们 进一步组织我们的代码,并保持 753 00:35:07,390 --> 00:35:11,660 概念类似的变量,就像一个 名称和房子一起,使我们 754 00:35:11,660 --> 00:35:15,570 可以把它们当作一个实体,里面 其中有小块。 755 00:35:15,570 --> 00:35:17,810 >> 但是,阵列具有一些缺点。 756 00:35:17,810 --> 00:35:19,780 的一些缺点是什么 我们遇到 757 00:35:19,780 --> 00:35:22,320 阵列,从而有多远? 758 00:35:22,320 --> 00:35:23,450 那是什么? 759 00:35:23,450 --> 00:35:28,130 固定大小 - 所以即使你可能 能够分配内存的 760 00:35:28,130 --> 00:35:32,310 阵列,一旦你知道有多少学生 你有,你有多少个字符 761 00:35:32,310 --> 00:35:35,460 从用户,一旦你分配 数组,你样的画 762 00:35:35,460 --> 00:35:36,740 自己陷入了困境。 763 00:35:36,740 --> 00:35:40,600 >> 因为你不能插入新元素 到一个数组中。 764 00:35:40,600 --> 00:35:43,660 您不能插入更多的元素 在结束一个数组。 765 00:35:43,660 --> 00:35:47,750 真的,你不得不求助于创造一个 全新的数组,如我们已经讨论了, 766 00:35:47,750 --> 00:35:49,320 复制旧到新。 767 00:35:49,320 --> 00:35:52,610 再次,这是头痛 则由GetString引发为您处理。 768 00:35:52,610 --> 00:35:56,170 >> 不过,你不能甚至插入 成的中间的数组的东西 769 00:35:56,170 --> 00:35:58,200 如果利率没有被完全填充。 770 00:35:58,200 --> 00:36:03,010 例如,如果该数组的大小 六只有五件事情, 771 00:36:03,010 --> 00:36:06,080 好了,你可能只是粘 到年底的东西。 772 00:36:06,080 --> 00:36:08,200 但是,如果你要插入的东西 到中间的 773 00:36:08,200 --> 00:36:11,280 阵列,即使它可能有 五六个的东西在里面? 774 00:36:11,280 --> 00:36:14,250 >> 哦,那我们做的时候,我们都 我们人类志愿者在舞台上 775 00:36:14,250 --> 00:36:15,110 周过去? 776 00:36:15,110 --> 00:36:18,710 如果我们希望把这里有人,无论是 这些人该如何移动 777 00:36:18,710 --> 00:36:22,540 的方式,还是这些人该如何移动 方式,并且变得昂贵了。 778 00:36:22,540 --> 00:36:26,950 里面的人转移 阵列加起来和成本 779 00:36:26,950 --> 00:36:31,240 我们的时间,因此我们很多ñ平方 运行时间,如插入排序, 780 00:36:31,240 --> 00:36:32,550 例如,在最坏的情况下。 781 00:36:32,550 --> 00:36:36,520 所以数组是伟大的,但你必须 提前知道你希望他们有多大。 782 00:36:36,520 --> 00:36:38,030 >> 这样就OK了,这里是一个解决方案。 783 00:36:38,030 --> 00:36:43,860 如果我事先不知道多少 我可能有学生,而且我知道,一旦 784 00:36:43,860 --> 00:36:47,870 不过,我决定,我坚持与 许多学生,为什么不我只是一直 785 00:36:47,870 --> 00:36:51,740 分配两倍的空间 因为我可能认为我需要什么? 786 00:36:51,740 --> 00:36:54,450 那是不是一个合理的解决方案吗? 787 00:36:54,450 --> 00:36:58,240 >> 实际上,我不认为我们 将需要超过50个插槽 788 00:36:58,240 --> 00:37:02,190 阵列中的一个中等大小的类, 因此让刚刚围捕。 789 00:37:02,190 --> 00:37:07,040 我会让我的数组,只需100插槽 这样我们就可以肯定得到 790 00:37:07,040 --> 00:37:10,330 我期望的学生数 在一些中等大小的类。 791 00:37:10,330 --> 00:37:14,320 那么为什么不围捕和分配 更多的记忆体,典型地,一个数组 792 00:37:14,320 --> 00:37:16,290 比你想象的,你甚至可能需要? 793 00:37:16,290 --> 00:37:20,190 这是什么简单的推托 这个想法? 794 00:37:20,190 --> 00:37:21,440 >> 你只是浪费内存。 795 00:37:21,440 --> 00:37:25,350 从字面上看你写的每一个程序,然后 也许使用两倍的内存 796 00:37:25,350 --> 00:37:26,680 你的实际需要。 797 00:37:26,680 --> 00:37:28,990 而这只是不觉得自己像一个 特别是优雅的解决方案。 798 00:37:28,990 --> 00:37:31,990 此外,它只是降低了 出问题的概率。 799 00:37:31,990 --> 00:37:35,300 如果你碰巧有一个流行的课程 一个学期,你有101 800 00:37:35,300 --> 00:37:39,610 学生,你的程序仍然是 从根本上面临着同样的问题。 801 00:37:39,610 --> 00:37:44,280 >> 令人欣慰的是,有一个解决方案, 这个广告的形式我们所有的问题 802 00:37:44,280 --> 00:37:46,790 的数据结构的 之外的更复杂的 803 00:37:46,790 --> 00:37:47,970 到目前为止,我们已经看到了。 804 00:37:47,970 --> 00:37:50,530 ,我要求,这是一个链表。 805 00:37:50,530 --> 00:37:51,920 这是一个数字列表 - 806 00:37:51,920 --> 00:37:54,970 9,17,22,26,34 - 807 00:37:54,970 --> 00:38:00,120 已连在一起的方式 什么,我画箭头。 808 00:38:00,120 --> 00:38:03,580 >> 换句话说,如果我想代表 我可以做一个数组, 809 00:38:03,580 --> 00:38:04,910 这样的事情。 810 00:38:04,910 --> 00:38:07,310 我就把这个开销 在短短的时刻。 811 00:38:07,310 --> 00:38:09,970 我可以做的 - 812 00:38:09,970 --> 00:38:12,520 你好,所有的权利。 813 00:38:12,520 --> 00:38:14,470 待机。 814 00:38:14,470 --> 00:38:17,360 在这里,新的计算机明确 - 815 00:38:17,360 --> 00:38:18,090 所有权利。 816 00:38:18,090 --> 00:38:21,730 >> 所以,如果我有这些数字阵列 - 817 00:38:21,730 --> 00:38:28,880 9,17,22,26,24 - 818 00:38:28,880 --> 00:38:30,530 未必按比例绘制。 819 00:38:30,530 --> 00:38:33,730 所有的权利,所以这里是我的数组 - 820 00:38:33,730 --> 00:38:34,980 噢,我的上帝。 821 00:38:34,980 --> 00:38:38,700 822 00:38:38,700 --> 00:38:40,395 所有的权利,所以这里是我的数组。 823 00:38:40,395 --> 00:38:44,110 824 00:38:44,110 --> 00:38:45,050 哦,我的上帝。 825 00:38:45,050 --> 00:38:48,820 >> [笑] 826 00:38:48,820 --> 00:38:49,440 >> 国宝马兰:假装。 827 00:38:49,440 --> 00:38:52,330 这是太多精力回去 解决这个问题,所以有 - 828 00:38:52,330 --> 00:38:54,290 26。 829 00:38:54,290 --> 00:38:57,650 因此,我们有这阵 9,17,22,26,和34。 830 00:38:57,650 --> 00:39:00,260 对于那些你可以看到 令人尴尬的错误,我只是做了 831 00:39:00,260 --> 00:39:00,830 它是。 832 00:39:00,830 --> 00:39:04,490 >> 因此,我要求这是一个 非常有效的解决方案。 833 00:39:04,490 --> 00:39:07,310 我分配尽可能多的int类型, 我需要 - 一,二,三, 834 00:39:07,310 --> 00:39:09,100 四,五,六 - 835 00:39:09,100 --> 00:39:11,660 然后我存储的数字 这个数组里面。 836 00:39:11,660 --> 00:39:15,220 但是,假设,然后,我要插入 8号这样的值? 837 00:39:15,220 --> 00:39:16,100 那么,它在哪里去了? 838 00:39:16,100 --> 00:39:18,530 假设我想插入 20这样的数字。 839 00:39:18,530 --> 00:39:19,790 那么,它在哪里去了? 840 00:39:19,790 --> 00:39:23,160 某处有在中间, 或数字35去 841 00:39:23,160 --> 00:39:24,010 某处在年底。 842 00:39:24,010 --> 00:39:25,320 但我所有的空间。 843 00:39:25,320 --> 00:39:29,120 >> 所以这是一个根本性的挑战 的阵列,它的解决方案。 844 00:39:29,120 --> 00:39:32,280 刚才我声称是,GetString 解决了这个问题。 845 00:39:32,280 --> 00:39:37,380 如果你想插入第六号 进入此阵列,什么是至少一种 846 00:39:37,380 --> 00:39:40,090 解决方案,您可以依傍的肯定, 就像我们做的GetString? 847 00:39:40,090 --> 00:39:44,340 848 00:39:44,340 --> 00:39:46,030 那是什么? 849 00:39:46,030 --> 00:39:48,190 >> 嗯,使其更大 说起来容易做起来难。 850 00:39:48,190 --> 00:39:52,810 我们不一定可以使数组 大,但我们能做些什么呢? 851 00:39:52,810 --> 00:39:56,570 创建一个新的更大的数组,大小 6,或者大小为10,如果我们想要 852 00:39:56,570 --> 00:40:00,490 出人头地的东西,然后复制 旧到新的数组,然后 853 00:40:00,490 --> 00:40:01,680 释放旧的阵列。 854 00:40:01,680 --> 00:40:05,770 >> 但是,什么是运行时间 现在这一进程? 855 00:40:05,770 --> 00:40:09,870 大O n的,因为复制 要花费你一些单位 856 00:40:09,870 --> 00:40:13,480 时间,所以不是那么理想,如果我们有 分配一个新的数组,这是怎么回事 857 00:40:13,480 --> 00:40:15,610 消耗的两倍多 暂时记忆。 858 00:40:15,610 --> 00:40:16,660 复制旧到新的 - 859 00:40:16,660 --> 00:40:18,800 我的意思是,它只是头痛, 再次,我们为什么写 860 00:40:18,800 --> 00:40:19,920 则由GetString引发你。 861 00:40:19,920 --> 00:40:21,380 >> 所以我们可能会做什么呢? 862 00:40:21,380 --> 00:40:25,000 那么,如果我们的数据结构 实际上有差距? 863 00:40:25,000 --> 00:40:30,790 假设我的目标是让我放松 连续的内存块,其中9 864 00:40:30,790 --> 00:40:34,500 至17日,这是旁边 旁边22,依此类推。 865 00:40:34,500 --> 00:40:39,570 >> 假设9可以在这里 RAM,17能在RAM中,在这里 866 00:40:39,570 --> 00:40:40,990 22可以在这里,在RAM中。 867 00:40:40,990 --> 00:40:43,610 换句话说,我并不需要他们 甚至背靠背了。 868 00:40:43,610 --> 00:40:47,850 我只是必须以某种方式穿针 通过每个这些数字,或每个 869 00:40:47,850 --> 00:40:51,010 这些节点,我们称之为 我画的矩形, 870 00:40:51,010 --> 00:40:55,670 记得怎么到最后 从第一个这样的节点。 871 00:40:55,670 --> 00:40:59,940 >> 那么,什么是编程构造 我们最近见过不少与我 872 00:40:59,940 --> 00:41:03,030 可以实现,线程,或者 吸引到这里,我可以 873 00:41:03,030 --> 00:41:05,430 实现这些箭头? 874 00:41:05,430 --> 00:41:06,500 所以指针,对不对? 875 00:41:06,500 --> 00:41:09,560 如果我不只是一个分配 int,但是一个节点 - 和 876 00:41:09,560 --> 00:41:10,810 节点,我的意思只是容器。 877 00:41:10,810 --> 00:41:12,900 和视觉,我的意思是一个矩形。 878 00:41:12,900 --> 00:41:16,420 所以一个节点显然需要 包含两个值 - 879 00:41:16,420 --> 00:41:21,490 的int本身,然后,如所暗示的 矩形的下半部分, 880 00:41:21,490 --> 00:41:23,010 类型为int的足够的空间。 881 00:41:23,010 --> 00:41:26,130 >> 所以只是想提前在这里, 有多大,这是节点,这 882 00:41:26,130 --> 00:41:27,170 容器中的问题? 883 00:41:27,170 --> 00:41:29,250 多少字节的整数? 884 00:41:29,250 --> 00:41:31,310 大概4,如果是 一样平常。 885 00:41:31,310 --> 00:41:33,270 那么有多少字节 指针? 886 00:41:33,270 --> 00:41:33,650 4。 887 00:41:33,650 --> 00:41:37,940 所以这个容器中,或此节点 将是一个8字节的结构。 888 00:41:37,940 --> 00:41:41,760 哦,这是一个令人高兴的巧合, 我们刚刚推出这个概念 889 00:41:41,760 --> 00:41:44,400 一个结构或C结构。 890 00:41:44,400 --> 00:41:48,890 >> 所以我要求,我要采取的一个步骤 朝着这个更复杂 891 00:41:48,890 --> 00:41:52,560 实施数字的列表, 链表的数字,我需要做一个 892 00:41:52,560 --> 00:41:56,920 多思考一点前面 声明不只是一个int,但结构 893 00:41:56,920 --> 00:41:58,620 我会打电话的,传统 在这里,节点。 894 00:41:58,620 --> 00:42:01,630 我们可以把它称为我们想要的东西,但 节点将是在一个特定的主题 895 00:42:01,630 --> 00:42:03,560 的事情,我们现在开始寻找。 896 00:42:03,560 --> 00:42:06,480 >> 该节点的内部是一个INT N。 897 00:42:06,480 --> 00:42:09,350 那么这个语法,一点点 怪异的第一眼 - 898 00:42:09,350 --> 00:42:12,960 结构节点*。 899 00:42:12,960 --> 00:42:16,900 形象好了,那是什么? 900 00:42:16,900 --> 00:42:21,000 这是下半部分的 我们看到的矩形 901 00:42:21,000 --> 00:42:22,730 刚才。 902 00:42:22,730 --> 00:42:27,600 >> 但是为什么我说结构节点* 而不是只是节点*? 903 00:42:27,600 --> 00:42:31,370 因为如果指针指向 在另一个节点时,它只是 904 00:42:31,370 --> 00:42:32,760 一个节点的地址。 905 00:42:32,760 --> 00:42:35,630 这是符合我们什么 关于指针讨论迄今。 906 00:42:35,630 --> 00:42:39,690 但是,为什么,如果我要求这个结构 称为节点,我不得不说结构 907 00:42:39,690 --> 00:42:42,660 内部节点这里? 908 00:42:42,660 --> 00:42:43,190 >> 没错。 909 00:42:43,190 --> 00:42:46,490 这是一个愚蠢的现实C. typedef的,可以这么说,有没有 910 00:42:46,490 --> 00:42:47,220 尚未发生。 911 00:42:47,220 --> 00:42:48,510 C的超级字面。 912 00:42:48,510 --> 00:42:51,050 它读取你的代码顶级 底部,从左到右。 913 00:42:51,050 --> 00:42:54,930 直到它击中,分号 底线,你猜怎么着不 914 00:42:54,930 --> 00:42:57,590 作为数据类型存在? 915 00:42:57,590 --> 00:42:59,060 节点,报价引文结束节点的。 916 00:42:59,060 --> 00:43:03,050 >> 但由于更详细 声明,我做的第一行 - 917 00:43:03,050 --> 00:43:05,340 的typedef struct节点的 - 918 00:43:05,340 --> 00:43:08,790 因为来之前,首先 大括号,有点像 919 00:43:08,790 --> 00:43:11,800 前教育锵,你 知道吗,给我一个struct 920 00:43:11,800 --> 00:43:13,570 所谓结构节点。 921 00:43:13,570 --> 00:43:16,270 坦率地说,我不喜欢调用的东西 结构节点,结构节点 922 00:43:16,270 --> 00:43:17,090 在我的代码。 923 00:43:17,090 --> 00:43:20,660 但我会只使用一次,只是里面, 让我能有效地 924 00:43:20,660 --> 00:43:25,010 创建一个循环引用,而不是 一个指针,指向自己本身,而是一种 925 00:43:25,010 --> 00:43:29,400 另一个指针 属于同一类型。 926 00:43:29,400 --> 00:43:32,330 >> 所以,事实证明,一个数据结构 这样,有几 927 00:43:32,330 --> 00:43:34,470 操作,可能会对 我们感兴趣的。 928 00:43:34,470 --> 00:43:37,460 我们可能要插入 进入这样的名单。 929 00:43:37,460 --> 00:43:39,850 我们可能想要删除 从这样的名单。 930 00:43:39,850 --> 00:43:43,490 我们可能要搜索一个列表 值,或者更普遍的是,遍历。 931 00:43:43,490 --> 00:43:46,410 和横向只是一个奇特的方式 说你应该开始在左侧和移动全部 932 00:43:46,410 --> 00:43:47,650 的方式的权利。 933 00:43:47,650 --> 00:43:52,640 >> 通知,即使有这样的稍多 复杂的数据结构,让 934 00:43:52,640 --> 00:43:56,510 我建议,我们可以借用一些 在过去两个星期的思想和 935 00:43:56,510 --> 00:43:58,410 执行一个函数调用 搜索这个样子。 936 00:43:58,410 --> 00:44:01,360 这将返回true或 false,表示yes或 937 00:44:01,360 --> 00:44:03,390 不中,n为在列表中。 938 00:44:03,390 --> 00:44:05,960 它的第二个参数是一个指针 列表本身,所以 939 00:44:05,960 --> 00:44:07,920 到一个节点的指针。 940 00:44:07,920 --> 00:44:10,350 >> 我要那么做是申报 一个临时变量。 941 00:44:10,350 --> 00:44:12,730 我们叫它PTR按照惯例, 指针。 942 00:44:12,730 --> 00:44:15,220 我给它等于 开始的名单。 943 00:44:15,220 --> 00:44:16,680 >> 现在注意到while循环。 944 00:44:16,680 --> 00:44:20,640 只要指针不等于 空,我要来检查。 945 00:44:20,640 --> 00:44:24,520 指针箭头n等于 中传递的n? 946 00:44:24,520 --> 00:44:26,410 并等待一分钟 - 新 一块语法。 947 00:44:26,410 --> 00:44:29,324 什么是箭头一下子? 948 00:44:29,324 --> 00:44:30,574 是吗? 949 00:44:30,574 --> 00:44:34,200 950 00:44:34,200 --> 00:44:34,810 >> 没错。 951 00:44:34,810 --> 00:44:38,860 因此,而在几分钟前,我们使用 点符号访问一些东西 952 00:44:38,860 --> 00:44:43,080 内部的一个结构中,如果变量 你是不是该结构 953 00:44:43,080 --> 00:44:47,420 本身,而是指向结构的指针, 令人欣慰的是,一块语法 954 00:44:47,420 --> 00:44:48,620 终于使得直观的感觉。 955 00:44:48,620 --> 00:44:52,360 箭头指按照指针, 像我们的箭通常意味着 956 00:44:52,360 --> 00:44:56,570 形象,并去 数据字段内。 957 00:44:56,570 --> 00:44:59,700 所以箭头是点,但同样的事情 你使用它的时候,你有一个指针。 958 00:44:59,700 --> 00:45:05,270 >> 因此,只要回顾一下,然后,如果n场 里面的结构称为指针 959 00:45:05,270 --> 00:45:07,760 等于等于N,则返回true。 960 00:45:07,760 --> 00:45:11,970 否则,这条线的位置 - 指针 等于指针。 961 00:45:11,970 --> 00:45:17,540 所以,这是什么做的,通知,如果我 我目前指向的结构 962 00:45:17,540 --> 00:45:21,430 含有9,和9的不数 我要找的 - 假设我要找 963 00:45:21,430 --> 00:45:22,830 n等于50 - 964 00:45:22,830 --> 00:45:25,930 我要更新我的临时指针 在这个节点不指向 965 00:45:25,930 --> 00:45:31,190 了,但指针旁边的箭头, 正打算把我在这里。 966 00:45:31,190 --> 00:45:34,270 >> 现在,我意识到是旋风 的介绍。 967 00:45:34,270 --> 00:45:37,380 上周三,我们将真正做到这一点 用一些人类和一些较 968 00:45:37,380 --> 00:45:38,900 代码以较慢的速度。 969 00:45:38,900 --> 00:45:42,990 但要意识到,我们现在正在做我们的数据 更复杂的结构,使我们的 970 00:45:42,990 --> 00:45:45,780 算法可以得到更高效, 将是必要条件 971 00:45:45,780 --> 00:45:50,500 pset中六,当我们加载,再次,那些 15万字,但需要这样做 972 00:45:50,500 --> 00:45:55,650 高效,理想的情况下,创建一个 我们的用户不是在运行的程序 973 00:45:55,650 --> 00:46:00,460 线性的,而不是在n的平方,但在 恒定的时间,在理想。 974 00:46:00,460 --> 00:46:02,300 >> 上周三,我们会看到你。 975 00:46:02,300 --> 00:46:07,240 >> 演讲嘉宾:在未来CS50大卫 忘记了他的基本情况。 976 00:46:07,240 --> 00:46:12,770 >> 国宝马兰:这就是你如何发送 短信与C - 977 00:46:12,770 --> 00:46:14,020 >> [各种短信 通知的声音] 978 00:46:14,020 --> 00:46:19,734