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 - [各种短信 通知的声音]