>> DAVID马兰：好的，欢迎回来。
这是CS50。
这是七周的开始。
因此，它已经有一段时间，所以我想我们最好 在哪里，我们需要旋风之旅
离开的，我们现在要。
>> 所以这个东西在这里可能有 造成了一定的焦虑在第一。
但我希望，你开始 适应新环境，这表示在这里 -
星级代表一个指针，它是 究竟是什么，更通俗地说？
因此，它是一个地址。
>> 因此，它的地址是 在内存中的东西。
我们开始剥开层层 几个星期前，事情喜欢
GetString的和其他类似的功能 这一切的时候已经返回
地址在内存中的东西，像 地址中的第一个字符
一些序列。
>> 因此，我们也介绍了valgrind的， 你会开始使用这个问题
设置，尤其是为下一个 问题设置。
valgrind的为我们做什么？
检查内存泄漏， 检查滥用记忆。
>> 以一定的概率，它可以检测，如果 你的代码将触摸内存
那根本不应该。
所以不一定泄漏，但如果你 一些超越的界限
数组，并在实际运行Valgrind的 并诱发这种行为，而
Valgrind是运行在你的程序是 它内部的运行，你会得到
这样的消息 - “无效写 尺寸4，“记得一对夫妇
两周前意味着我不得不意外 喜欢上一个int太远
边界之外的一个数组。
等大小4表示这里的大小 该特定的诠释。
>> 因此，需要安慰的事实， Valgrind的输出，它的格式，
仅仅是残暴的。
这真的很难识破的一塌糊涂 有趣的信息。
所以我们在这里所做的只是摘录 一些对情侣更
有趣的线。
但要意识到80％的valgrind 输出将是一个有点
分心。
>> 只要看看这些模式，如 - 无效的，正确的，无效的阅读，40个字节
和一些的块数是绝对 丢失，这样的关键字。
什么，你会希望看到的是一些 那种一丝什么功能
错误是实际上英寸的
在这种情况下，在这里，在哪一行 我的代码，显然是错误的吗？
>> 在一个名为memory.c，这是26 例如，我们都在玩
的时间。
所以它可能不是malloc的。
这可能是在我的代码代替。
因此，我们将再次看到这 前再次长。
>> 因此，scanf函数，这是在一个 夫妇迄今形式。
我们看到sscanf的简要介绍。
而东西 你在你跳入
准备测验。
和scanf实际上是什么CS50 图书馆一直使用下面的
相当长的一段时间，以便罩 得到来自用户的输入。
>> 举例来说，如果我移动到CS50 家电在这里，让我开了
比如今天这就是所谓的scanf函数0.C 它的超简单。
这只是一个几行代码。
但它真的演示如何调用getInt 已经工作的这段时间。
>> 在这个程序中在这里，在第16行 请注意我声明一个int。
因此，没有指针，没有什么神奇 在那里，只是一个int。
然后在第17行，我提示 用户输入一个数字，请。
然后在18年底，我这里使用的scanf。
我和规定，一种如printf， 我期待报价
引文结束％。
>> 所以我％，当然， 表示一个int。
但是要注意什么第二 是scanf函数参数。
你会如何​​形容第二 逗号后的参数？
那是什么？
>> 这是x的地址。
因此，这是非常有用的，因为通过提供 scanf函数x的地址，什么
授权功能怎么办？
不只是去那里，而且还做什么呢？
>> 它的变化。
因为你可以去那里，它的排序 就像一张地图在内存中的位置。
所以只要你提供scanf函数，或 任何这样的地图，即功能
功能可以去那里，不仅 看一看的价值，但它也可以
更改该值，这是有用的，如果 scanf函数在生活中是
扫描来自用户的输入，具体 从键盘输入。
和F表示格式化，就像 printf的一个格式化的，f表示
要打印的串。
>> 因此，在短期，简单地说，此行18， 从用户的尝试读取一个int
键盘和它里面存储的x， 无论地址x恰巧住在。
然后最后，19号线刚说， 感谢为int的，在这种情况下。
>> 所以，让我继续前进，使这个。
所以使：scanf的0。
让我继续放大。
我会去，并运行此 点斜线：scanf的0。
号码好吗？
50。
感谢为50。
因此，它是相当简单的。
>> 现在是什么是不是在做什么？
这不是做了一大堆 错误检查。
举例来说，如果我不配合， 我不键入一个数字，但
而不是我写的东西，如“你好”， 这只是一种奇怪的。
因此CS50的事情之一 库已经为我们做了一些
时间是再次提示 并再次提示。
>> 重试短语召回在cs50.c， 的原因，调用getInt
CS50库实际上是一个整体 一堆线长，因为我们
检查这样的愚蠢的东西。
用户不要给 我们，其实，一个int？
他或她给我们的东西 像一个字母？
如果是这样，我们要检测 ，并大声喝斥。
>> 但是，事情变得更加有趣 在下一个例子。
如果我去scanf函数1.C，什么是一个 事情是从根本上改变
在下一个例子吗？
我使用char *，当然， 而不是int。
>> 因此，这是有趣的，因为char *， 回想一下，其实只是
同样的事情串。
所以感觉一样，也许这是一个超级 GetString的简单实现。
但我已经去皮层 CS50库，所以我
现在调用这个char *的。
让我们看看，如果在任何地方， 我们去错了。
>> 第17行 -
我再次说，请你给我的东西， 在这种情况下，一个字符串。
然后在下一行，我调用scanf函数， 再次，给它一个格式码，
但这次％秒。
那么这个时候，我 给它的缓冲区。
>> 现在请注意，我没有使用 符号。
但是，这是为什么这里大概OK？
原因是什么缓冲了吗？
这已经是一个指针。
它已经一个地址。
>> ，让我们这个“混淆视听”，让我 只是把它，例如，
简约。
不过，我已经把它称为缓冲，因为在 一般情况下，在编程中，如果你有一个
大块的内存，这一个字符串真的 只是，你可以称之为一个缓冲区。
这是一个地方来存储信息。
>> 类似的事情，如YouTube，当 他们正在缓冲，可以这么说，
只是意味着它的下载位 将它们保存在互联网和
本地阵列，一个地方的内存块，所以 ，你可以看它，以后不
跳跃或挂在 你一边玩。
>> 所以这是一个问题，但在这里， 因为我告诉scanf函数，期望
来自用户的字符串。
这里的地址是 一块内存。
把该字符串。
这是为什么绑定给 给我们带来麻烦，但？
>> 那是什么？
我允许访问 内存的那部分？
你知道，我不知道。
由于缓冲区被初始化 什么吗？
真的没有。
因此，这是我们一直呼吁 垃圾值，这
是不是一个正式的词。
它只是意味着，我们不知道什么位 内的四个字节，
我已经分配缓冲区。
>> 我还没有叫的malloc。
我肯定不叫GetString的。
那么，谁知道什么是真正的 缓冲液内？
还告诉scanf的盲目，去那里 并把任何用户输入。
>> 那么，什么是可能造成 在我们的代码中，如果我们运行呢？
大概一个segfault。
也许不是，但可能是一个段错误。
和我说，也许不是因为有时 你这样做，有时
你没有得到一个段错误。
有时候你就是幸运的，但 但是这将是
在我们的程序中的一个bug。
>> 所以，让我继续前进，编译这个。
我要做到这一点老派的方式。
所以铛破折号scanf函数-1，0， scanf函数1.C，回车。
哎呀，太旧的学校。
让我们来看看。
我应该在哪里？
哦，字符*缓冲区。
哦，谢谢你 -
保存，OK -
很老的学校。
好吧，它已经有一段时间。
>> 所以，我刚刚保存后的文件 使该临时
前改变了一会儿。
现在我已经编译 手动锵。
现在我要继续前进 并运行scanf函数-1，回车。
字符串。
我会键入“你好。”
>> 而现在，这里的地方，坦率地说，PRINTF 可以是有点恼人。
它实际上并不是要 在这种情况下，段错误。
printf是有点特殊的，因为 它是如此的超级常用
基本上printf是做 我们赞成和实现，
这不是一个有效的指针。
让我把它后，我自己只是打印 在括号空，甚至
虽然它不一定是 我们自己的预期。
>> 因此，我们不能真的很容易诱发 段错误这一点，但显然这
是不是我想要的行为。
那么，有什么简单的解决方案？
那么，在scanf-2，让我提出， 而不是实际只是分配
的char *，让我有点小聪明有关 这一点，让我分配缓冲区
为16个字符的序列。
>> 所以，我可以做到这一点的方式在一对夫妇。
我完全可以使用malloc。
但我可以回去两个星期时 我只是需要一大堆
字符。
这只是一个数组。
因此，让我，而不是重新定义缓冲区 是一个数组为16个字符。
>> 而现在，当我通过缓冲区 -
这是我们没有的东西 谈谈在本周二 -
但你可以把一个数组作为 虽然它是一个地址。
技术上，正如我们已经看到的那样，他们是 有一点点不同。
但scanf函数不会介意，如果你传递给它 数组名，原因是什么
铛会为我们做本质上是 作为治疗该数组的名称
16个字节的数据块的地址。
>> 因此，这是更好的。
这意味着，现在我希望能 做到以下几点。
让我缩小了一会儿， 做scanf的-2，编译OK。
现在让我做了斜线scanf函数2。
字符串。 “你好。”并且它 似乎工作时间。
>> 但有人提出了一个方案 它仍然可能不工作？
是吗？
东西超过16个字符。
而实际上，我们可以 更确切的一点。
东西不再那么15个字符， 因为我们真的需要牢记
我们需要反斜杠零 上面的字符串末尾的隐式
这是一个抛开scanf函数通常会 照顾我们。
>> 因此，让我做这样的事情 -
有时我们就可以 离开它这样。
好了，我们现在已经引起 我们的分割故障。
为什么呢？
因为我打字不超过15个 字符，所以我们实际上已经
其实我感动内存 不应该有。
>> 那么，什么是真正的解决方案在这里？
那么，如果我们需要一个更长的字符串？
好吧，我们也许做32个字节。
那么，如果不够长吗？
大约64个字节？
如果不够长？
约128或200字节？
什么是真正的解决方案，在这里 一般情况下，如果我们不知道在
推进用户要输入什么？
>> 这是一个很大的痛苦的屁股只是一种， 说实话，这是为什么
CS50库有几十行 共同实施的代码
字符串的方式，我们不这样做，则由GetString引发 提前知道什么
用户将要输入。
特别是，如果你回头看看 cs50.c从两个星期前，你会看到
确实，GetString的 以这种方式不使用的scanf。
相反，它读取一个字符 的时间。
>> 因为一个美好的事情 我们可以读取一个字符
保证自己总是 至少有一个字符。
我可以声明一个char，然后采取 只是这些真正的婴儿的步骤
在读取一个字符 从键盘输入的时间。
然后，你会看到的GetString 确实是每次用完，
说，16字节的内存，它使用 malloc的，或一个表弟物，
分配更多的内存，复制旧 内存成新的，然后爬
一直以来，得到一个字符的时间， 当它用完
的内存块，它扔了出去，待价而沽 更大的内存块复制旧
进入新的和重复。
，它是一个真正的痛苦其实 实现的东西一样简单
得到来自用户的输入。
>> 所以，你可以使用scanf函数。
您可以使用其他类似功能。
而很多课本和在线 例子，但他们都
脆弱到这样的问题。
最终，得到一个segfault 是有点恼人。
这不是为用户好。
>> 但是，在最坏情况下，这是什么 它从根本上把你的
代码的风险吗？
某种攻击，有可能。
我们谈到了一个这样的攻击 - 堆栈溢出。
但在一般情况下，如果你允许 缓冲区溢出，像我们做了一个
几个星期前，只是写 以上的“你好”，你在堆栈上
的确可以考虑，潜在的， 计算机上，或者至少在数据
不属于你。
>> 因此，在短期，这就是为什么我们有 这些培训轮子。
但是现在，我们开始把他们赶走， 因为我们的课程不再需要，
必须的，来自用户的输入。
但在问题的情况下，设置6个， 您的输入将来自一个巨大的
一些字典文件150 奇千言万语。
>> 所以，你将不必担心 用户任意输入。
我们会给你一些假设 关于该文件。
指针上有任何疑问或scanf 或用户输入一般？
>> 所有的权利，所以在一个快速浏览一下，然后 尾随从两个星期前的话题。
这是一个struct这个概念。
不 - 这个概念， 结构，这是什么？
什么结构为我们做什么？
>> 定义 -
对不起？
定义一个变量的类型。
因此，排序。
其实我们两个主题结合。
因此，用typedef，回想一下，我们可以 声明一个类型，像我们自己的
的代名词，就像字符串的char *。
但是，我们可以使用typedef和结构 真正创造我们自己的数据结构。
>> 举例来说，如果我回去到gedit中 这里只是一个瞬间，我先走
做这样的事情，让我节省 本作，让我们说，structs.c
暂时我只是 继续前进，包括
standardio.h，INT主要无效。
然后在这里，假设，我想 写一个程序，存储
多个学生从多个 房屋，例如。
因此，它是像一个registrarial的 某种数据库。
>> 所以，如果我需要一个学生的名字，我 可能会做一些像char *的名称，
我会做这样的事情 -
其实，让我们使用CS50库 只是一瞬间，使这个
简单一点的，所以我们可以借用 那些几十行代码。
只是，让我们保持它的简单。
我们会保持它的字符串， 现在则由GetString引发。
>> 因此，我要求现在，我已经存储的名称 一些学生，房子
一些学生，只需使用变量 像我们一样，在第一个星期。
但是，假设我现在要支持 多个学生。
好吧，让我的直觉是做 字符串名称2，得到的GetString，串
house2得到的GetString。
然后我们的第三个学生， 让我们做NAME3 GetString的。
>> 所有的权利，所以这是希望引人注目 作为一种愚蠢的，
因为这个过程是真的从来没有 将要结束，它只是要
使我的代码看起来更糟糕 和每况愈下。
但我们解决了这个在本周二也。
我们比较干净的解决方案是什么 当我们有多个变量，
相同的数据类型都有关，但 我们不希望这种残暴的混乱
同样命名的变量？
我们做了什么呢？
>> 所以我想我听到了几个地方。
我们有一个数组。
如果你想的多个实例 的东西，为什么不要我们清理这一切
，只是说，给我 数组的名字呢？
>> 现在，让我们的硬编码3。
然后给我另一个数组 称为房子，让我
现在硬编码3。
而且我已经大规模清理 乱，我只是创建。
现在，我还是硬编码3，但即使 3可以动态来自
用户，或者argv的或类似。
所以这已经是清洁。
>> 但恼人的是， 现在，即使名字是某种
根本联系 学生的家 -
这是一个学生，我真的 要代表 -
我现在有两个平行的阵列 在这个意义上，他们是
相同的大小，名称托架0 想必映射到房子支架0，
和名称支架1地图 房屋支架1。
换句话说，该学生生活在 那房子，房子和其他学生
生活在其他的房子。
但可以肯定，这可能是 做得更干净。
>> 好吧，它可以，其实。
并让我继续前进，打开 了structs.h，你会
在这里看到这个想法。
请注意，我用的typedef，因为你 刚才提到申报我们
自己的数据类型。
但是，我也使用此关键字 称为struct这给了我一个新的
的数据结构。
>> 而这一数据结构，我要求是怎么回事 有两件事情里面
- 一个字符串名为name， 一个字符串，称为房子。
和名字我要去给 将这样的数据结构
被称为学生。
我可以打电话给我想要的任何东西， 但这种语义
我感觉到，在我的脑海里。
>> 所以，现在，如果我打开了一个更好的版本 的节目，我开始写
那里，让我滚动到顶部。
还有一些更多的代码行 在这里，但让我专注
一个时刻。
我宣布一个恒定的所谓学生 硬编码的现在。
但现在，注意到何洁 我的代码开始就搞定了。
>> 在22行，我宣布 阵列的学生。
并注意学生显然是 现在的数据类型。
因为在顶部的文件，通知 我已经包含了该头文件
我拉起刚才。
该头文件很简单 这个定义一个学生。
>> 所以，现在，我创建了自己的自定义数据 类型，作者的C年
前事先没有想到的。
但没有问题。
我可以做自己。
所以这是一个阵列称为学生， 其每名成员
是学生结构。
我想三个 在数组中。
>> 而现在，没有休息 这个程序怎么办？
我需要的东西有点武断。
因此，从24日起在网上， 我遍历从0到3。
然后我再问用户 学生的名字。
然后我用则由GetString引发如前。
然后，我问学生的房子， 我用则由GetString引发像以前那样。
>> 但通知 - 稍微新 一块语法 -
我仍然可以索引到的第i个学生， 但我怎么得到的具体数据
领域里面的结构吗？
那么，什么是显然 新语法？
这仅仅是点操作符。
>> 这之前，我们还没有真正见过。
你已经看到了它的pset五，如果你 已经跌位图文件。
但点只是意味着在这里面， 结构或多个领域，给点
名称，或者给我点的房子。
这意味着内部结构 得到这些特定的领域。
>> 这个程序的其余部分做什么？
这还不是全部，性感。
请注意，我再次循环从0到3， 我只是创造英语
短语，比如某某等 这样的房子，通过在点名称
的第i个学生和他们的 房子，以及。
>> 最后，现在我们将开始得到 肛门，现在我们
熟悉什么malloc和 其他功能已经
做这一切的时候。
为什么我一定要释放这两个名字 和房子，即使我
没有调用malloc？
>> GetString的了。
那是肮脏的小秘密 几个星期，但GetString的
遍布泄漏内存 把所有学期迄今为止。
valgrand终于将 揭示给我们。
>> 但是，它不是一个大不了的，因为我知道， 我可以简单地释放名称
和房子，虽然在技术上， 超强，安全，应该是我
做一些错误检查。
什么是你的直觉告诉你吗？
我应该怎么检查 之前，我释放什么是
字符串，又名一个char *？
>> 我真的应该进行检查，如果学生 支架I点名称不
等于空。
然后，它会确定先走，并免费 该指针，相同或其他
别人。
如果学生支架I点的房子是不是 等于为null，这将保护
对角落的情况 的形式返回类似空。
而且我们刚才也看到了，printf的 保护我们在这里只是说
null，这是怎么回事，看起来很怪异。
但至少它不会出现段错误， 正如我们所看到。
>> 好吧，让我在这里做另一件事。 结构-0是一个愚蠢的计划
因为我输入所有数据，然后 它失去了，一旦程序结束。
但是，让我继续前进，做到这一点。
让我做终端 窗口有点大了。
让我结构-1， 这是一个新版本。
>> 我会在一点点放大。
现在让我跑点 削减结构1。
学生的名字 -
大卫·马瑟，让我们做罗布·柯克兰， 让劳伦利维瑞特。
现在是什么有趣的通知 -
我只知道这是因为 我写的程序 -
现在我目前有一个文件 目录students.csv。
你们当中有些人可能已经看到 这些在现实世界中。
>> 什么是CSV文件？
逗号分隔值。
它有点像一个穷人的 版本的Excel文件。
这是一个表的行和列， 你可以打开一个程序如Excel，
或在Mac上的数字。
>> 如果我在这里打开此文件gedit中， 通知 - 数字是不存在的。
这只是gedit的告诉 我行号。
的第一行通知 文件是大卫和马瑟。
下一行是罗布逗号柯克兰。
第三行是劳伦 逗号利维瑞特。
>> 所以我创建了什么？
我现在写的C程序 可以有效地生成电子表格
可以打开在 如Excel程序。
并非所有引人注目的一个数据集，但 如果你有更大的大块
数据，你其实是要 操纵，使图表和
喜欢，这也许是一个 的方式来创建数据。
此外，特装车点实际上超共同 只是简单的数据存储 -
雅虎财经，举例来说，如果你得到 通过他们所谓的股票行情
API的免费服务，让您 获取当前到最新的库存
公司的报价，他们 在给数据
超简单的CSV格式。
>> 所以，我们是怎么做到的呢？
注意到，这一计划的最 几乎是相同的。
但是请注意，在这里，而不是打印 学生，上线35
开始，我要求我保存 学生到磁盘，保存文件。
>> 因此，注意到我声明一个FILE * -
现在，这是一种异常C. 无论出于何种原因，文件是全部大写，
这是不是像大多数其他数据类型 但是这是一个内置的
数据类型，文件*。
我声明一个指针到一个文件， 你怎么能想到的。
>> FOPEN意味着打开的文件。
你想打开什么文件？
我想打开一个文件，我将 任意调用students.csv。
我可以打电话，我想要的任何东西。
>> 再取一个猜测。
第二个参数做什么 FOPEN大概是这个意思吗？
右，w代表写， 是读r为。
还有一个附加的，如果你 要添加行，而不是
覆盖整个事情。
>> 但我只是想创建这个文件 一次，所以我会使用报价引文结束瓦特。
而且我知道，只有在读取 文档或手册页。
如果文件不为空 - 换句话说， 如果没事就去那里错了 -
让我遍历 从0到3的学生。
>> 现在注意到有什么东西 曾经如此略有不同
行约41。
这不是printf的。
fprintf printf的文件。
因此，它会写入文件。
哪个文件？
您指定的指针 作为第一个参数。
>> 然后，我们指定格式字符串。
然后，我们指定我们想要什么字符串 插头的第一％S和
然后另一个变量或 第二个％秒。
然后关闭文件FCLOSE。
比我释放内存之前，虽然 我应该回去，并添加
一些检查为空。
>> 就是这样。
FOPEN，fprintf等FCLOSE给我 创建文本文件的能力。
现在，你会看到问题集五， 涉及图像，您将使用
二进制文件来代替。
但是从根本上说，这个想法是一样的， 即使功能，你会
看到的是有一点点不同。
>> 所以旋风之旅，但你会得到 太熟悉文件I/O--
输入和输出 - pset中五。
而任何疑问 初始的基础在这里？
是吗？
>> 如果你试图释放一个空值？
我相信，除非已经得到了自由 对用户来说更加友好，你可以
潜在的段错误。
它传递空是不好的，因为我不 相信自由困扰为你检查，
因为它可能会是浪费 为它做自己的时间
在世界上的每个人。
好问题，虽然。
>> 好，那么这种得到 我们一个有趣的话题。
习题集的主题 五是取证。
至少这是一个部分 问题集。
取证一般是指在 恢复的信息，可能或
可能没有被删除 故意的。
所以我想，我想给你一个快速 什么味道真的
下面这段时间 引擎盖您的计算机。
>> 举例来说，如果你里面有你 笔记本电脑或桌面电脑一
硬盘驱动器，它可以通过机械 设备实际旋转 -
有圆形的东西称为盘片 看起来很喜欢我
刚刚在这里，虽然在屏幕上 这是越来越多的老同学。
这是三个和一个半英寸 硬盘驱动器。
三个半英寸指 的东西，当你安装它
在一台计算机。
>> 你们中许多人的家伙现在在您的笔记本电脑 有固态硬盘或SSD，
没有移动部件。
他们更像RAM不像 这些机械设备。
但这些想法仍然是相同的， 当然，因为它们涉及
问题五。
>> 如果你想想现在的硬盘驱动器 代表了一圈，这
在这里，我会得出这样的。
当您在您的计算机上创建一个文件， 无论它是一个SSD，或在
这种情况下，硬盘驱动器是较旧的学校， 该文件包括多个位。
比方说，它的0和1， 一大堆的0和1。
所以这是我的整个硬盘驱动器。
这显然​​是一个相当大的文件。
并且被使用在该0s和1s 部分的物理盘片。
>> 那么，什么是物理部分？
嗯，事实证明，在硬盘上， 至少在此类型中，有
这些微小的磁性粒子。
他们基本上有北部和 南极，因此，如果您
打开其中一个，这些磁性颗粒 通过这种方式，你可能会说，这是
较1。
如果它是倒挂南下 北，你可能会说，这是
代表一个0。
>> 因此，在真实的物理世界，这是 你如何能代表的东西
二进位的0状态和1。
所以这是一个文件。
有一大堆磁 是他们这样或颗粒
通过这种方式，创建模式 0和1。
>> 但事实证明，当你保存文件， 一些信息分开保存。
所以这是一个小桌子， 一个目录，可以这么说。
我会打电话给这列名， 我会打电话给这个列位置。
>> 我要去说，假设 这是我的简历。
我的resume.doc被存储在 位置，比方说123。
我总是去该号码。
但我只想说，就像 在RAM中，你可以把一个硬盘驱动器
这是一个千兆字节或200千兆字节 TB级，你可以
所有的字节数。
你可以列出所有的8位块。
>> 因此，我们会说，这 是123的位置。
因此，这个目录里面，我的作业 系统会记住我
简历是在位置123。
但它变得有趣，当 你删除一个文件。
>> 因此，例如 -
令人欣慰的是，世界上大多数国家都有 捕捉到这 - 时会发生什么
拖动文件到您的Mac OS垃圾桶 或Windows回收站？
这样做的目的是什么？
这显然​​是要摆脱的文件， 但到底是什么行为拖动
下降到废纸篓或 回收站在电脑上做的吗？
>> 绝对没有，真的。
这就像一个文件夹。
这是一个特殊的文件夹，可以肯定的。
但它实际上删除的文件？
>> 哦，不，因为一些你可能 一直喜欢，哦，该死的，你没有
意味着这样做。
所以，你双击 垃圾桶或回收站。
你周围戳，你已经恢复 只需拖动文件
离开那里。
所以很明显，它不一定 删除。
>> OK，你聪明得多。
你知道，只是拖动它到 垃圾桶或回收站并不意味着
你清空垃圾桶。
所以，你上去的菜单，和你说 清空废纸篓或清空回收站。
然后会发生什么？
>> 是啊，所以它被删除，更是这样。
但所发生的一切是这样的。
电脑忘记 是resume.doc。
>> 但什么也没有明显变化 在画面？
位，0和1，我要求的是 在现场的一些物理方面的
硬件。
他们还在那里。
这只是电脑有 遗忘它们是什么。
>> 因此，它本质上释放文件的 位的，所以它们可以被重复使用。
但直到你创建更多的文件， 多个文件，多个文件
概率，这些0和1， 这些磁性粒子，得到重用，
上攻或右侧， 其他文件，0和1。
>> 所以，你有这样的时间窗口。
它不是可预测 长度，真的。
这取决于你的硬盘的大小 驱动器和你有多少个文件
你如何迅速做出新的。
但是这期间的时间窗口 该文件仍然是完美的
收回。
>> 所以，如果你使用的程序如McAfee 或Norton尝试恢复
数据，他们正在做的是试图 恢复这个所谓的目录
弄清楚你的文件在哪里。
有时诺顿和会说， 文件是可收回93％。
那么，是什么意思呢？
这只是意味着，其他一些文件 巧合的结束使用，也就是说，
那些位出你的原始文件。
>> 那么，什么是真正参与 在恢复数据？
好吧，如果你不会有这样的事情 诺顿预先安装在电脑上，
有时你可以做的是最好的看 在整个硬盘寻找
的位模式。
和问题集的主题之一 五是，你会搜索
相当于一个硬盘驱动器，一个法医 形象从一个紧凑的闪存卡
数码相机，搜索为0 和1，通常，具有较高的
概率，代表 开始的JPEG图像。
>> 你们可以收回这些图像 假设，如果我看到这个图案
位法医形象， 的概率很高，这标志着
开始的JPEG。
如果我再次看到同样的模式， 可能标志着开始
另一个JPEG格式，和其他 JPEG格式，和其他的JPEG。
这通常是如何 数据恢复工作。
关于JPEG文件有什么高兴的是，即使 的文件格式本身是有点
复杂，每一个这样的开头 文件其实是相当可识别
和简单，因为你会看到， 如果你还没有准备好。
>> 因此，让我们来仔细看看下面 正是一直罩
回事，这些0和1 ，给你多一点的
上下文这个特殊的挑战。
>> [视频回放]
>> ，如果您的电脑存储最 其永久性的数据。
要做到这一点，数据从RAM 随着软件信号，告诉
硬盘驱动器如何将这些数据存储。
硬盘驱动器电路翻译 这些信号转换成电压
波动的影响。
这些，反过来，控制硬盘驱动器的 移动部件，一些数
留在移动部件 现代计算机。
>> 部分的信号控制电机 其中旋转金属涂层盘片。
您的数据实际上是存储 这些盘片上。
其他信号将读/写 头读取或
写在盘片上的数据。
这个机器，一个人如此精确 头发甚至不能之间传递
磁头和旋转盘片。
然而，这一切都以惊人的速度。
>> [END视频播放]
>> 国宝马兰：在一个小放大 更深现在什么
实际上这些盘片上。
>> [视频回放]
>> - 让我们来看看，在我们刚才 看到慢动作。
当一个简短的电脉冲 发送到读/写头，如果翻转
一个微小的电磁 的一小部分的第二个。
磁铁创建一个字段，该字段 一个微小的，微小的改变极性
部的金属颗粒 大衣每个盘片表面。
>> 这些微小的一个模式系列， 充电区，在磁盘上的
表示的一个位 二进制数中的数据
由电脑系统使用。
现在，如果当前发送的一种方法 通过读/写头，该地区
是在一个方向上极化。
如果当前的发送，在 相反方向上，
极化反转。
>> 您是怎样从硬盘的数据？
只要相反的过程。
因此，它是在磁盘上的颗粒 获取中的电流
读/写头移动。
这些放在一起百万 磁化段，
你已经得到了一个文件。
>> 现在，一个单一的文件件 遍布驱动器的
盘片的一塌糊涂，有点像 你的办公桌上的文件。
因此，一个特殊的额外的文件跟踪 这里的一切是。
难道你不希望你有 类似的东西？
>> [END视频播放]
>> 国宝MALAN：OK，大概不会。
所以，你们的许多球员 从小一起长大的这些吗？
OK，所以越来越少 表决时，每一年。
不过，我很高兴你至少熟悉 与他们，因为这和我们自己的
可悲的是，书的演示，死一个非常 熟悉拖死。
>> 但是，这是我，至少，早在 高中，用于备份。
它是令人惊异的，因为你 可以存储140兆字节
这个特定的磁盘。
这是高密度版本， 所指示的HD，其中有
这意味着之前今天的高清视频。
>> 标准密度为800千字节。
而在这之前，有 400千字节的磁盘。
而在这之前，共有5和1/4 英寸磁盘，这是真正的软盘，
和一点点更宽，更高 比这里这些事。
但实际上你可以看到所谓的 这些磁盘的软盘方面。
>> 和功能，它们实际上是 非常相似，在硬盘驱动器
至少这种类型。
同样，固态硬盘在新电脑 工作方式略有不同。
但是，如果你移动，小金属卡， 实际上，你可以看到一个小的cookie，
或拼盘。
>> 它不是像这样的金属。
其实这其中的一些便宜 塑料材料制成。
你可以摆动它的那种。
你trully只是抹去一些 位或磁性颗粒的数量
从该磁盘。
>> 令人欣慰的是，它没有什么。
如果这件事情的方式 - 并覆盖 你的眼睛和你的邻居 -
你可以只是一种拉 整个鞘关闭这样的。
但是，有一个小弹簧，所以 知道你的眼睛。
所以，现在你有一个真正的软盘。
>> 什么显着 在尽可能多的是，因为这是一个
一个更大的小规模的代表性 硬盘驱动器，这些东西都是超，
超级简单的。
如果你捏它的底部，现在 该金属的东西，和剥离
他们打开，有两件 感到，并且所谓的软盘
一块金属在里面。
>> 并有去一半 我的磁盘的内容。
去他们的另一半。
但是这一切，里面纺纱 您的计算机在昔日。
>> 再次，把这种成角度， 有多大你的大部分
硬盘驱动器，这些天？
500千兆字节，TB级，也许在 一台台式电脑，3，2 TB的
TB级，4 TB的，对不对？
这是一个兆字节，或采取 甚至不能符合一个典型的MP3
这些天了，还是有些 类似的音乐文件。
>> 有那么一点点的纪念品今天为你， 也能帮助处境是什么
我们将采取理所当然的 现在的问题设置5个。
所以，那些是你的保持。
因此，让我这里将成为过渡 花下的pset。
所以我们现在已经设置这个页面 - 哦， 一对夫妇很快公布。
>> 本星期五，如果您想加入CS50 吃午饭，去平常的地方，
cs50.net/rsvp。
最终项目 -
所以每教学大纲，我们已经发布了 项目最终规范已经。
要认识到，这并不意味着 这是由于特别快。
它的贴吧，真的，只是为了得到 你们想着它。
果然，有一个超级显著 将解决你的百分比
最终项目的材料，我们 甚至还没有得到在课堂上，
但下周初。
>> 但请注意，该规范要求 几个不同的组件的
最终的项目。
第一，在几个星期内，是一种 建议前期，很随意的电子邮件
你的TF告诉他，或者你在做什么 想为您的项目，
没有承诺。
建议将您的特定 的承诺，他说，在这里，这是什么
我想为我的项目做。
你觉得呢？
太大？
太小？
是管理？
你可以看到更多的细节。规范
>> 几个星期后，状态 报告，这是一个类似的
休闲电子邮件到TF说多么 不甘落后，你在你的最终
项目的实施，其次是 CS50 Hackathon大家
被邀请，这将是一个事件 下午8:00至7:00一个晚上
AM第二天早晨。
比萨，因为我可能会提到周 为零，将担任下午9:00，
中国食品在凌晨1:00。
而如果你还醒着上午5:00， 我们带你去IHOP早餐。
>> 因此，黑客马拉松是其中一个比较 类中的难忘的经历。
然后执行由于 然后高潮CS50展。
在所有这些的更多细节 在今后几个星期。
>> 但是，让我们回去的东西 旧学校 -
再次，一个数组。
所以数组是不错的，因为它解决 的问题，像我们看到的只是一个
刚才学生结构 开始有点失控，如果我们
希望有学生，学生， 学生点点点三，学生，
一些任意数量的学生。
>> 所以阵列，几个星期前，猛扑 并解决我们的问题不
事先知道有多少东西 某种类型的，我们想要的。
我们已经看到，结构可以帮助我们 进一步组织我们的代码，并保持
概念类似的变量，就像一个 名称和房子一起，使我们
可以把它们当作一个实体，里面 其中有小块。
>> 但是，阵列具有一些缺点。
的一些缺点是什么 我们遇到
阵列，从而有多远？
那是什么？
固定大小 - 所以即使你可能 能够分配内存的
阵列，一旦你知道有多少学生 你有，你有多少个字符
从用户，一旦你分配 数组，你样的画
自己陷入了困境。
>> 因为你不能插入新元素 到一个数组中。
您不能插入更多的元素 在结束一个数组。
真的，你不得不求助于创造一个 全新的数组，如我们已经讨论了，
复制旧到新。
再次，这是头痛 则由GetString引发为您处理。
>> 不过，你不能甚至插入 成的中间的数组的东西
如果利率没有被完全填充。
例如，如果该数组的大小 六只有五件事情，
好了，你可能只是粘 到年底的东西。
但是，如果你要插入的东西 到中间的
阵列，即使它可能有 五六个的东西在里面？
>> 哦，那我们做的时候，我们都 我们人类志愿者在舞台上
周过去？
如果我们希望把这里有人，无论是 这些人该如何移动
的方式，还是这些人该如何移动 方式，并且变得昂贵了。
里面的人转移 阵列加起来和成本
我们的时间，因此我们很多ñ平方 运行时间，如插入排序，
例如，在最坏的情况下。
所以数组是伟大的，但你必须 提前知道你希望他们有多大。
>> 这样就OK了，这里是一个解决方案。
如果我事先不知道多少 我可能有学生，而且我知道，一旦
不过，我决定，我坚持与 许多学生，为什么不我只是一直
分配两倍的空间 因为我可能认为我需要什么？
那是不是一个合理的解决方案吗？
>> 实际上，我不认为我们 将需要超过50个插槽
阵列中的一个中等大小的类， 因此让刚刚围捕。
我会让我的数组，只需100插槽 这样我们就可以肯定得到
我期望的学生数 在一些中等大小的类。
那么为什么不围捕和分配 更多的记忆体，典型地，一个数组
比你想象的，你甚至可能需要？
这是什么简单的推托 这个想法？
>> 你只是浪费内存。
从字面上看你写的每一个程序，然后 也许使用两倍的内存
你的实际需要。
而这只是不觉得自己像一个 特别是优雅的解决方案。
此外，它只是降低了 出问题的概率。
如果你碰巧有一个流行的课程 一个学期，你有101
学生，你的程序仍然是 从根本上面临着同样的问题。
>> 令人欣慰的是，有一个解决方案， 这个广告的形式我们所有的问题
的数据结构的 之外的更复杂的
到目前为止，我们已经看到了。
，我要求，这是一个链表。
这是一个数字列表 -
9，17，22，26，34 -
已连在一起的方式 什么，我画箭头。
>> 换句话说，如果我想代表 我可以做一个数组，
这样的事情。
我就把这个开销 在短短的时刻。
我可以做的 -
你好，所有的权利。
待机。
在这里，新的计算机明确 -
所有权利。
>> 所以，如果我有这些数字阵列 -
9，17，22，26，24 -
未必按比例绘制。
所有的权利，所以这里是我的数组 -
噢，我的上帝。
所有的权利，所以这里是我的数组。
哦，我的上帝。
>> [笑]
>> 国宝马兰：假装。
这是太多精力回去 解决这个问题，所以有 -
26。
因此，我们有这阵 9，17，22，26，和34。
对于那些你可以看到 令人尴尬的错误，我只是做了
它是。
>> 因此，我要求这是一个 非常有效的解决方案。
我分配尽可能多的int类型， 我需要 - 一，二，三，
四，五，六 -
然后我存储的数字 这个数组里面。
但是，假设，然后，我要插入 8号这样的值？
那么，它在哪里去了？
假设我想插入 20这样的数字。
那么，它在哪里去了？
某处有在中间， 或数字35去
某处在年底。
但我所有的空间。
>> 所以这是一个根本性的挑战 的阵列，它的解决方案。
刚才我声称是，GetString 解决了这个问题。
如果你想插入第六号 进入此阵列，什么是至少一种
解决方案，您可以依傍的肯定， 就像我们做的GetString？
那是什么？
>> 嗯，使其更大 说起来容易做起来难。
我们不一定可以使数组 大，但我们能做些什么呢？
创建一个新的更大的数组，大小 6，或者大小为10，如果我们想要
出人头地的东西，然后复制 旧到新的数组，然后
释放旧的阵列。
>> 但是，什么是运行时间 现在这一进程？
大O n的，因为复制 要花费你一些单位
时间，所以不是那么理想，如果我们有 分配一个新的数组，这是怎么回事
消耗的两倍多 暂时记忆。
复制旧到新的 -
我的意思是，它只是头痛， 再次，我们为什么写
则由GetString引发你。
>> 所以我们可能会做什么呢？
那么，如果我们的数据结构 实际上有差距？
假设我的目标是让我放松 连续的内存块，其中9
至17日，这是旁边 旁边22，依此类推。
>> 假设9可以在这里 RAM，17能在RAM中，在这里
22可以在这里，在RAM中。
换句话说，我并不需要他们 甚至背靠背了。
我只是必须以某种方式穿针 通过每个这些数字，或每个
这些节点，我们称之为 我画的矩形，
记得怎么到最后 从第一个这样的节点。
>> 那么，什么是编程构造 我们最近见过不少与我
可以实现，线程，或者 吸引到这里，我可以
实现这些箭头？
所以指针，对不对？
如果我不只是一个分配 int，但是一个节点 - 和
节点，我的意思只是容器。
和视觉，我的意思是一个矩形。
所以一个节点显然需要 包含两个值 -
的int本身，然后，如所暗示的 矩形的下半部分，
类型为int的足够的空间。
>> 所以只是想提前在这里， 有多大，这是节点，这
容器中的问题？
多少字节的整数？
大概4，如果是 一样平常。
那么有多少字节 指针？
4。
所以这个容器中，或此节点 将是一个8字节的结构。
哦，这是一个令人高兴的巧合， 我们刚刚推出这个概念
一个结构或C结构。
>> 所以我要求，我要采取的一个步骤 朝着这个更复杂
实施数字的列表， 链表的数字，我需要做一个
多思考一点前面 声明不只是一个int，但结构
我会打电话的，传统 在这里，节点。
我们可以把它称为我们想要的东西，但 节点将是在一个特定的主题
的事情，我们现在开始寻找。
>> 该节点的内部是一个INT N。
那么这个语法，一点点 怪异的第一眼 -
结构节点*。
形象好了，那是什么？
这是下半部分的 我们看到的矩形
刚才。
>> 但是为什么我说结构节点* 而不是只是节点*？
因为如果指针指向 在另一个节点时，它只是
一个节点的地址。
这是符合我们什么 关于指针讨论迄今。
但是，为什么，如果我要求这个结构 称为节点，我不得不说结构
内部节点这里？
>> 没错。
这是一个愚蠢的现实C. typedef的，可以这么说，有没有
尚未发生。
C的超级字面。
它读取你的代码顶级 底部，从左到右。
直到它击中，分号 底线，你猜怎么着不
作为数据类型存在？
节点，报价引文结束节点的。
>> 但由于更详细 声明，我做的第一行 -
的typedef struct节点的 -
因为来之前，首先 大括号，有点像
前教育锵，你 知道吗，给我一个struct
所谓结构节点。
坦率地说，我不喜欢调用的东西 结构节点，结构节点
在我的代码。
但我会只使用一次，只是里面， 让我能有效地
创建一个循环引用，而不是 一个指针，指向自己本身，而是一种
另一个指针 属于同一类型。
>> 所以，事实证明，一个数据结构 这样，有几
操作，可能会对 我们感兴趣的。
我们可能要插入 进入这样的名单。
我们可能想要删除 从这样的名单。
我们可能要搜索一个列表 值，或者更普遍的是，遍历。
和横向只是一个奇特的方式 说你应该开始在左侧和移动全部
的方式的权利。
>> 通知，即使有这样的稍多 复杂的数据结构，让
我建议，我们可以借用一些 在过去两个星期的思想和
执行一个函数调用 搜索这个样子。
这将返回true或 false，表示yes或
不中，n为在列表中。
它的第二个参数是一个指针 列表本身，所以
到一个节点的指针。
>> 我要那么做是申报 一个临时变量。
我们叫它PTR按照惯例， 指针。
我给它等于 开始的名单。
>> 现在注意到while循环。
只要指针不等于 空，我要来检查。
指针箭头n等于 中传递的n？
并等待一分钟 - 新 一块语法。
什么是箭头一下子？
是吗？
>> 没错。
因此，而在几分钟前，我们使用 点符号访问一些东西
内部的一个结构中，如果变量 你是不是该结构
本身，而是指向结构的指针， 令人欣慰的是，一块语法
终于使得直观的感觉。
箭头指按照指针， 像我们的箭通常意味着
形象，并去 数据字段内。
所以箭头是点，但同样的事情 你使用它的时候，你有一个指针。
>> 因此，只要回顾一下，然后，如果n场 里面的结构称为指针
等于等于N，则返回true。
否则，这条线的位置 - 指针 等于指针。
所以，这是什么做的，通知，如果我 我目前指向的结构
含有9，和9的不数 我要找的 - 假设我要找
n等于50 -
我要更新我的临时指针 在这个节点不指向
了，但指针旁边的箭头， 正打算把我在这里。
>> 现在，我意识到是旋风 的介绍。
上周三，我们将真正做到这一点 用一些人类和一些较
代码以较慢的速度。
但要意识到，我们现在正在做我们的数据 更复杂的结构，使我们的
算法可以得到更高效， 将是必要条件
pset中六，当我们加载，再次，那些 15万字，但需要这样做
高效，理想的情况下，创建一个 我们的用户不是在运行的程序
线性的，而不是在n的平方，但在 恒定的时间，在理想。
>> 上周三，我们会看到你。
>> 演讲嘉宾：在未来CS50大卫 忘记了他的基本情况。
>> 国宝马兰：这就是你如何发送 短信与C -
>> [各种短信 通知的声音]