[音乐播放] ROB BODEN:好吧。 所以,首先第一件事情的视频, 从一个熟悉的面孔。 [视频回放] - 所有权利。 这是CS50,这是 本周三开始。 对不起,我不能和你在一起 今天,但请允许我介绍 CS50自己的罗布博登。 [完视频回放] [掌声和欢呼声] ROB BODEN:在本片目 该视频是太棒了。 好的。 因此,首先,有另一个午餐。 这是明天1:15。 有没有吃午饭这个星期五。 这是与Quora的。 和汤米是一个还没来,但 那里的人是前负责人的CF, 汤米McWilliam。 所以他是一个有趣的家伙。 你应该来。 好的。 所以上周,我们开始分崩离析 什么字符串确实是。 从一开始我们已经知道, 它是一个字符序列。 但上周,我们深入研究的事实 那什么是真正的一个序列 字符,好了,我们现在有 字符数组。 而我们知道,一个字符串,它是一个数组 的字符,在最后, 我们有这个特殊的空字节,这 反斜线0,则表示的端 该字符串。 所以一个字符串数组 字符,但我们可以有一个以上 个字符的只是一个数组, 我们可以有任意的阵列 我们想要的东西的类型。 所以,如果你从上周还记得, 大卫介绍了中世纪程序 真的很快。 我们将这样做第一件事是 要求用户输入一个整数,则 人在房号。 一旦我们有一个整数, 我们声明数组。 请注意这个括号的语法。 你会习惯的。 因此,我们声明一个整数数组 所谓的年龄,并有n个 整数此数组中。 因此,这种模式就在这里,这4整型 i等于0,i小于N,I加 再加上,这也将是一个模式 你得到非常习惯。 因为这几乎是你是如何 总是要遍历数组。 所以请记住,n是 我们的长阵。 所以在这里,我们反复询问 对于人,我在房间里的年龄。 在此之后,我们要下去,不管是什么 乱的原因,我们再 打印出他们是如何将老 从现在开始的一年。 并运行该程序,让我们 让不同年龄,点斜线青睐。 所以,人在房号, 让我们说有三种。 并说,第一个人是13, 接下来是26,最后是30。 这样的话,它会遍历这三个 人,打印出14,27,和31。 所以请记住,当我们声明 大小为n的数组,该指数 数组,数组有值和 索引0,1,2,一路 最多n减去1。 因此,当我们说,有三个人 在房间里,和我们摆在这里 通过本第一次迭代 循环中,i将是0。 因此,在指数0。 我们正在分配第一 年龄的增长,用户输入。 那么在未来一,我们正在进入 第二n用户输入,并且在 接下来的两个,最后n。 所以请注意大小的数组 3没有什么 在索引3。 这是无效的。 好的。 因此,回到这里。 所以,现在,我们已经处理了数组, 我们有一定的了解。 现在,我们要进入到命令 行参数,这将是 漂亮与此问题相关设置。 所以直到现在,每当你已经 宣告你的main函数,我们已经 说整型主作废。 所以虚空只是意味着 如果我们没有任何 参数给这个函数。 现在,我们要看到,主 可以采取一些参数。 在这里,我们称他们为整型的argc 和字符串argv的括号内。 在括号中,再次指示 我们正在处理的数组。 所以在这里,字符串argv的支架,我们 处理字符串数组。 这样的argc,那将表明 我们有多少争论已经 通过这一方案。 而看到这意味着什么, 让我们关闭这个。 确定。 所以到现在为止,我们已经运行每 程序像点斜线年龄。 我们还可以在命令行中,过去 传递参数,从而术语,命令 行参数。 所以第一个参数,你好世界。 所以在这里,ARGC将三人。 它的参数的数量 在命令行中。 的argc总是至少1中,由于点 斜线的年龄,本身算作一个 命令行参数。 然后招呼是第一个。 如果点斜线历来是零,那么 你好是第一位的,世界是 第二个命令行参数。 因此字符串argv的,我们要看到, 包含字符串,点斜线 年龄,你好,和世界。 而且,由大卫的要求,我们将 播放视频介绍了。 [视频回放] - 到现在为止在我们已经计划 写的,我们已经声明 主要为INT主要作废。 而这一切的时候,也有无效 只是被指定的 程序不采取任何 命令行参数。 换句话说,当用户执行一个 节目中,他或她可以提供命令 写入额外的行参数 词或短语后程序的 在提示名称。 好吧,如果你不想要你的程序 采取命令行参数,一个或 更多的这样的话,我们需要更换 丧失与一对夫妇的参数。 因此,让我们做到这一点。 包括CS50.h. 包括标准io.h. 诠释为主。 而现在,而不是无效的,我要去 指定所谓的argc一个int和一个 数组叫做argv的字符串。 现在,argc和argv是 简单的约定。 我们可以称这些论点 大多数我们想要的东西。 但是,什么是重要的是,是ARGC 一个int,因为按照定义,它是 要包含参数计数, 字数在总数的 用户在键入他或她的提示。 argv的,同时,参数向量,是 会实际上是一个数组存储 所有的用户具有的字 在键入他或她的提示。 让我们继续做一些事情现在 与一个或​​多个这些 命令行参数。 尤其是,让我们继续和打印 不论字的用户类型 该程序的名称后 在提示符下。 打开支架。 关闭支架。 printf的百分比s反斜线和逗号。 现在我要告诉printf的价值是什么 插入到该占位符。 我想,该用户具有的第一个字 该程序的名称后输入, 所以我要去指定 argv的支架1,接近 括号,分号。 现在,为什么支架1和支架不是0? 嗯,事实证明,自动存储 argv中0将是该 程序的实际名称。 因此,第一个字的用户类型 之后,该程序的名称是,由 按惯例,将是 存储在argv中1。 现在让我们来编译和 运行此程序。 做的argv 0,点斜线的argv 0。 现在一个字像打招呼。 输入。 我们在那里有它,你好。 [完视频回放] ROB BODEN:好吧。 关闭了。 因此,采取一看那个程序, 我们只是向我们介绍了,好了,只是 显示,如果我们打印的argv 0,使得现在 它是什么,ARGV 0,点斜线的argv 0。 因此,正如所料,它打印出 该程序的名称,因为ARGV 0 总是会在 该程序的名称。 但是,让我们做的东西 更有趣。 所以在这个问题集,你会 介绍了此功能,atoi的。 那么,我们用什么atoi的呢? 那将转换 字符串到整数。 所以,如果我把这个字符串,一二三, 以atoi的,那将是转换 为整数,一二三。 所以,我们要转换的第一 命令行参数为整数, 然后只打印该整数。 所以基本上,我们是那种 重新实现调用getInt,只是 输入整数,在命令 行,而不是在程序 交互。 那么,做的argv 0,让我们做 它在这里,并关闭。 所以运行的argv 0,让我们进入 整数,一二三四一二。 所以它会打印出整数,1 一二三四一二。 有一些微妙之处给atoi的 它会停下来关心什么 超出有效数字字符, 但是,这并不重要。 所以,你觉得会发生 如果我这样做? 分段错误。 那么,为什么会这样? 如果你回头看看我们的计划,我们 转换的argv 1,第一个参数 程序名之后,为整数。 但没有传递的参数 程序名后。 所以在这里,我们看到这是一个越野车 方案,因为如果我们尝试运行它 不带任何参数, 它只会崩溃。 所以,你会看到另一个常见模式 是一样的东西,如果ARGC是少 大于2,表明有不 至少程序名和一 第一个参数,然后我们会做一些事情 如printf,没有足够的 命令行参数。 这可能不是一个很好的打印, 它可能是什么东西,像 你应该输入一个整数 在命令行中。 我刚刚结束了在那里。 然后返回1。 所以请记住,在我们的结束 程序,如果我们回到0,诸如此类的 表示成功。 和主也会自动 返回0,如果你不这样做。 所以在这里,我们重新调整1来表示 那这是不是成功。 而且你可以返回任何你想要的, 只是,0表示成功, 别的表示失败。 因此,让我们运行这个版本的东西。 所以,现在,如果我们不进入命令行 参数,它会正确地告诉 我们没有足够的命令行。 没说完这句话。 否则,如果我们真的把它传递的, 它可以完成该程序。 因此,这是你将如何使用的argc在 为了验证数 命令行参数 实际上通过。 因此,让我们使这个程序有点多 复杂的,并期待在第二 迭代的事情。 所以,现在,我们不只是打印 第一个命令行参数。 在这里,我们从int i等于迭代 0,i是小于的argc,我加 再加上,印刷的argv,索引i。 所以此模式下,再次,这是相同的 图案和以前一样,除了代替 调用该变量的 N,我们使用的argc。 因此,这是遍历每个索引 在数组中,并打印每个 元素在数组中。 所以,当我们运行这个程序,那么, 我没有输入任何命令行 参数,所以它只是打印 程序名称。 如果我输入了一堆东西,它会 打印一份,每个各占一行。 确定。 因此,让我们这一步。 和而不是打印每个参数 在自己的行,让我们每个打印 每个参数的字符 在自己的行。 所以请记住,argv是 一个字符串数组。 那么,什么是一个字符串,但 字符数组? 这样就意味着argv是一个真正的 字符数组的数组。 因此,采取这种优势, 让我们忽略这个现在。 让我们只考虑字符串的argv 0。 因此,如果我们想带给每个字符 argv的0在自己的行,那么我想 做我们已经习惯的模式,我是 小于所述阵列的长度, 这这里,是strlen的,那就是 不是我想做的事情,串 s等于argv的0。 所以我不到我们的长 阵列,在这种情况下是一个数组 人物中,我加再加。 因此,正如我们上周所看到的,它是理想的 如果我们朝那个strlen的外 的条件下,由于n将增加 第每次我们去时的strlen 通过循环,并且它是 不会被改变。 因此,我们将其设置等于n在这里。 确定。 所以,现在,我们遍历 每个索引的数组中。 所以,如果我们要打印的每个 字符数组,百分比c是 我们要使用的标志 对于字符。 现在支架我将是该 字符串索引字符我,所以如果 字符串为你好。 则s 0将是H,S支架 1将通过电子邮件,等等。 所以,现在我们要结合 这两样东西。 我们要打印的每个字符 每个命令行参数。 因此,我们将有 一个嵌套的for循环。 与以往,第一计数器 是我,接下来的将是J,N 将是我的argv strlen的,我 小于n,我加再加。 而不是印刷的argv我和现在,所以 argv的支架我打算指数 - 这将是第i个命令行 参数,argv的I,J是要 是第j个字符 第i个说法。 我会摆脱现在这种在这里 因为我们把它放到这个循环。 这样就相当于字符串s等于 argv的我,和则S支架Ĵ。 好了,我们不需要声明 这个变量s。 相反,我们就结合这 两成我们的曾经,的argv I,J。 扬声器1:[听不清]。 ROB BODEN:良好的通话。 所以这是破碎。 如果我真的跑了,我们就 已经意识到这一点。 所以,我所关心的计数器 在这个特定的供 环为j,迭代器。 所以,你会遇到的问题, 可能是一个无限循环,如果我们 没有固定的。 这就是为什么我们还在谈 有关调试今天。 确定。 因此,让我们运行这个程序。 而且,我们实际上添加一个单独的printf的 在这里,将刚刚打印 另一条线,因为这意味着,当我们 运行该程序,就会有一个空白 在每个字符之间的行 每个命令行参数。 那么,我们将看到这意味着什么。 空中接力。 得到了一些bug。 错误隐式声明 库函数strlen的。 所以要回到我们的节目,我 忘了哈希包括string.h中。 所以string.h中会是在 该声明的头文件 该函数strlen的。 好了,它编译。 现在,让我们来运行它。 所以这一点。 这将打印出我们的 程序名,你好世界。 这将打印每一件事情,每一个 人物,在自己的行。 确定。 因此,让我们确实有此 进了一步。 而不是使用string.h中和,让我们 想了解我们如何想实现自己的 strlen函数。 于是我马上给 一个函数签名。 因此,让我们在my_strlen调用,它的 要采取一个字符串作为参数, 和我们预期的回报 长度字符串。 因此,如果是那个人吗? 是。 确定。 因此,从早期的幻灯片记得 也是从上周开始,即一个 字符数组,那么,一个字符串, 所以让我们说这是我们的字符串s。 所以,如果s是字符串,你好,那么, H-E-L-L-O,内存,那将 定,然后将这个反斜杠 0字符。 那么,如何才能得到s的长度? 好了,关键是找这个 背隙0字符,此空 终结者。 所以该算法是怎么回事 要像数 足够的字符 - 让我们来这一手代表的一些 计数器,让我们称这个整数长度。 所以,从在这里开始,我们 要遍历我们的字符串。 所以第一个字符,它的H, 而且它不是反斜杠0,所以 的长度为1。 迭代到下一个字符, E,并且它不是反斜杠0。 长度为2。 L,3。 L,4。 O,5。 最后,我们到达反斜线 0,这样就意味着,好吧, 这个字符串就结束了。 因此,让我们回到5。 因此,实际上执行的是,第一, 我的N长度等于0,我的右手。 而且我们要遍历 - 扬声器1:[听不清] ROB BODEN:哦,拍摄。 良好的通话。 热潮。 因此n长度等于0。 所以现在,而S长度不 平等,那么,反斜线0。 所以请记住,这个反斜线0,它是一个 实际的字符,它表示 字符串的结尾。 就好像,另外,反斜杠 n是一个实际的字符。 反斜线0是要表明 我们的字符串的末尾。 我不希望把他们那里。 并同时通过索引的长度s是不 等于空终止,然后 我们只是要增加长度。 那么,在我们节目的最后, 长度最终将 是5在这种情况下。 我们将只返回长度。 确定。 所以,现在在这儿,我不 做my_strlen。 让我们来编译它,以确保 一切顺利。 我是在2干什么? 或者是1? 这应该做的。 好的。 所以这是ARGV 2。 作品如预期,但 是一个我在做的吗? 是。 确定。 这个版本的东西没有 printf的新行之后,但它 没有任何区别。 确定。 因此,如预期般运作。 现在,我们甚至可以结合这一步 进一步,在这里通知,好了, 首先,我们要抓住的argv的strlen的 我,然后我们遍历 每个字符在该字符串。 而不是这样做,那么,如果我们 只是结合在等待这个逻辑 直到我们打反斜线0右 这个for循环? 所以,当遍历ARGV I,J呢 不等于反斜线0。 因此,让我们运行它第一次。 好的。 所以在这里,这种情况是说 - 让我们澄清这一点。 所以,现在,让这次成为我们的argv。 所以,当我刚刚才跑了程序, argv是一个字符串数组。 所以,如果我用点斜线的argv运行 2,你好世界,那么在argv 本身是一个长度为3,为ARGV 零,你好,和世界。 而这些指标里面是, 本身是一个数组,其中该会 点,这将是斜线,我不知道 如果这是正确的方向,我 不认为它是。 A-R-V的仪表板,需要更多的空间。 让我们切入这个数组。 A-R-V的仪表板0,然后反斜线0。 然后趁乱会打招呼。 比方说,H-E反斜杠0。 最后,W-O反斜杠0。 所以,我们刚刚编写的算法, 嵌套的for循环,他们在做什么 做的是,我们首先有 计数器i和则j。 这与代码上更容易 屏幕上,让我们回到这一点。 确定。 所以请注意,我是迭代器的 遍历每个命令 行参数。 和j为迭代器迭代 过在每一个字符 命令行参数。 那么,这个最里面的printf是做 是,我们的printf的argv 0 0,printf的 argv的0 1,printf的ARGV 0 2 0 3 0 4 0 5,0 6,但现在,argv的0 7即将 等于反斜线0。 于是我们退出了for循环, 现在我遍历1。 现在我们将要打印 argv的1 0,argv的1 1 - 好了,现在,因为我砍你好短, argv的1 2再次将是 反斜杠0。 因此,增加我和继续, 依此类推,直到我们打印出所有的 世界的,那些是三个命令行 的论点,我们会退出了 最外面的圈,并 完成我们的计划。 确定。 因此,让我们再回到这里。 所以,你会获得一些熟悉 在这个命令行参数 特别是设置的问题。 现在,调试。 所以,你可能已经不得不做 与以前的一些调试 问题集。 和调试的一个非常简单的方法, 首先,让我们来看看一个错误的程序。 好了,走过这个程序, 我们要问一个用户 整数,抢了整数,然后, 随意,我们有一个while循环, 只是要递减 我直到它等于10。 让我们只是假设我进入 的整数大于10。 所以我递减,直到它等于10。 然后我们还有一个while循环 ,虽然我不等于0,我们是 要通过3递减我。 所以,如果你看到错误的意图 在这里,它是这将减小到我 是10,然后这个while循环的意志 递减我从10到07到4,1, 至负2,负5,依此类推, 负无穷大,因为我将 从来没有实际等于0。 然后在这个节目的最后, 我们有foo函数是 怎么回事打印出来,我。 因此,这是一个短期和琐碎的程序, 而错误是显而易见的, 特别是在我刚 说什么错误了。 但这里的意图是,很好,这可能 实际上看起来像你的一些 从最后贪心解 问题集,也许你确实有 一些无限循环在你的程序, 而你不知道 什么导致它。 所以有一个非常有用的调试技术 是刚刚加入的printfs 在你的代码。 所以在这里我想外面一个printf 第一个while循环。 在这里,我想一个printf, 我将只打印我。 我什至可以做第一个while循环,我。 外,第二个while循环。 再次,里面打印 这里,i的值。 让我们来运行这个。 所以点斜线调试。 输入的整数。 让我们做13。 和热潮。 我们看到,我们是无限循环 里面的第二个while循环。 所以,现在我们知道到底是什么错误。 但printf的调试是完全很棒, 但是一旦你的程序得到 更长,更复杂,有 更复杂的解决方案, 把事情的工作。 因此,让我们删除所有这些的printfs。 并让我们确保我没有 破坏任何东西。 确定。 所以我们要去的程序 引进被称为 GDB,为GNU调试器。 嗯,事实上,我们删除的调试 第二,并再次调试。 嗯,其实第一次,一个很好的教训 在命令行参数。 请注意,这锵命令是 编译一切都被传递 在命令行中,这些 命令行参数。 那么究竟如何你将要使用 命令行参数,因为我们 做之前,并且你会在PSET 2,这就是铛是如何使用它们。 所以请注意,这第一个标志,破折号 ggdb3,是什么在说的是,铛, 你应该与编译这个文件 意图,我们最终将 需要调试它。 所以只要你有该标志, 那么我们就可以GDB调试。 它会打开GNU调试器。 所以有很多的命令 你需要去适应。 第一个,你可能会 立即需要的是执行。 那么,什么是运行怎么办? 这将开始我们的节目。 所以运行,启动程序,该程序 要求我们为一个整数,13。 然后它是无限循环的 预计,除了我删除了 的printfs,所以我们甚至看不到这一点。 正常退出。 呵呵。 这是可能的,它包裹着所有 倒过来,回 - 忽略了。 假设它没有正常退出。 有一个复杂的答案。 所以,现在,这不是非常有用。 因此,只要运行我们的程序里面 这个调试器不会帮助我们在任何 这样,既然我们刚才做 点斜线调试的GDB之外。 这样一个命令 你可能 - 我将退出这个。 控制-d或退出,两者的工作。 因此,让我们再次打开它。 另一个命令,你可能会 马上要 习惯就是休息。 因此,我们将打破对主要就目前来看, 然后我会解释。 好了,在这里我们看到,我们设置一个断点 在此行中debug.c。 那么,什么破手段是,当我 键入run,该程序将 继续运行,直到 我打一个断点。 所以,当我打的运行,程序启动时, 然后,只要它打破 进入主函数。 突破主要将是什么 你很常见的事情。 现在,给你介绍 一些更多的命令。 注意这里,它在说,我们 打破了在第11行,这是 printf的,输入一个整数。 因此命令下一步将是如何 我们去的下一行代码。 这将允许我们加强 通过我们的节目一行行。 等下次。 现在,第12行,我们要 得到的整数。 下一步。 如果你只是打再次输入,它会 重做你做的最后一件事。 所以我不需要键入 接下来的每一次。 这样输入的整数,13。 所以,现在,第14行,而我是更大 大于10,并且我会做下一个。 我们看到我们将要递减我。 所以,我们要再次递减我。 所以,现在,另一种有用的 命令打印。 因此,打印将会打印出 该变量的值。 让我们带出的价值 的变量i。 让我们来打印我。 它会说,我是11。 现在,我们接着再而 i大于10。 所以我仍然大于 10,因为它是11。 我减减。 让我们再次打印我。 正如预期的那样,它是10。 所以,现在,未来。 这是要回的情况下,我是 大于10,但我现在是10,所以 它不是大于10,因此我们预计 它掉下来的while循环。 而现在我们下面的那行代码。 而另一个命令,列表,只是将 显示上一页和下一页 几行代码,在 如果你失去了你自己。 所以我们只是退出这个while循环, 现在我们已经进入了这个 while循环中,第18行。 因此,虽然我不等于0。 而且,接下来,我等于我减3,我们将 请注意,这将只是继续前进。 我们可以打印我。 排序的每个命令都有快捷键。 因此P是短期的打印。 因此,我们可以p我。 只要继续保持N, 或者继续做下一步。 再次打印我。 现在你看到它的负面167。 因此,这将永远继续下去,但不 真的永远,因为你刚才看到,它 实际上在某个点结束。 所以这是开始GDB。 但让我们做一件事的GDB。 呃,调试。 所以,在这种特定情况下,本 无限循环恰好是内 的主要功能。 而现在,只接受了我 要移动的无限循环 foo函数。 只要记住,在本月底 计划,嗯,这本来是 调用foo,这只是 要打印我。 但现在我们调用foo,这是 要我递减,直到它的0, 然后打印该变量。 确定。 保存。 做调试。 而现在,GDB调试。 确定。 所以,如果我只是运行那么我不会去 可以通过实际步骤我 程序行由行。 因此,让我们在主破裂, 然后键入运行。 所以经过这个,printf的输入 的整数,得到的整数,13。 因此,我们要保持递减 直到i大于10。 那么我们要落空了 while循环,并获得了线 - 让我们打开它,在一个单独的窗口。 因此,我们递减,直到我不再 大于10,然后就 称为函数foo。 所以,只要我打发生了什么 函数foo,好,我叫foo,并且 然后,我不再有超过GDB的控制。 所以,只要我打接下来的这条线, 事情一直持续到发生这种情况, 当程序退出的时候 - 假设它最终没有存在。 你看到它停顿了一会儿,但。 那么,我为什么失去了控制 该方案在这一点? 好吧,当我输入下一个,那去 代码的文字下一行 将执行。 所以在第21行的下一行代码 将执行的是22行, 这就是,从主要退出。 所以,我不想只是去 对下一行代码。 我想进入该函数foo, 然后还通过加强 那行代码。 因此,对于这一点,我们有一个替代。 让我们再次退出了。 突破为主。 呃,1,下一步,下一步,13,接下来, 下一步,下一步,仔细, 之前我们打线富。 确定。 所以,现在,我们正处于第21行, 在这里我们调用foo。 我们不希望接下来的输入,因为这 只是调用函数foo,以及 去的下一行代码。 我们要使用的是什么步骤。 因此,有步骤之间的差异 而接下来,在步骤步入 功能,并进入下一步 以上的功能。 它只是执行的全部 功能,并保持下去。 所以第一步是要带给我们 入函数foo。 我们在这里看到,现在,我们回到了 这个while循环的,从理论上讲, 要继续下去。 如果你打步骤,当它甚至不是 要调用的函数,那么它的 相同的下一步。 因此,只有当你在一条线 正在调用步骤的函数 打算从明年有所不同。 所以步骤会带给我们这里。 一步,一步,一步,一步,一步,一步, 我们只是无限循环下去。 所以,你可能习惯了,作为您的 查明无限循环的方式,是 只是抱着这个回车键 看到这里你会被卡住。 有更好的方法来做到这一点,但 就目前而言,这是完全足够了。 和曲风,以符合样式 50,我应该这样做。 确定。 所以最后一个命令介绍。 那么,让我们用gdb调试英寸 因此,而不是在破主,如果我 知道foo函数也是 的问题,那么我可以只 说,在打破富,而不是。 比方说,我在突破 这两个主要和foo。 所以,你可以设置尽可能多的断点 只要你想。 当我键入​​run,这是怎么回事 停在 - 哦,让我们重新编译,因为 我改变的东西。 你会看到这条线,警告,源 文件比可执行的更近一些。 因此,这意味着,我只是在走到这里 而这些改变,以符合样式 50,但我没有重新编译 该方案。 所以GDB让我意识到这一点。 我会退出,再次进行调试, 打GDB调试。 确定。 所以,现在,回到我在做什么。 主要的突破,打破富。 现在,如果我运行这个程序,所以它的 要继续,直到撞到 断点。 断点发生在 是第一个在主。 现在,而不是做下一步,下一步,下一步, 下一步,下一步,直到我打富,我 可以输入持续,这将继续 直到你打一个断点。 我必须先输入整数。 继续将继续下去,直到我打的 下一个断点,这是 函数foo。 所以运行将运行,直到你打一个 断点,但你只有在键入run 你开始的程序,然后, 从那时起,它的继续。 如果我只是做了突破和主 然后跑,它会打破在 主,然后继续。 因为我没有一个破发点时富, 输入的整数,那么现在我 不会打破在foo中。 它只是将无限 循环,直到这一点。 确定。 所以这是介绍到GDB。 你应该开始使用它 在你的习题集。 它可以是非常有帮助 识别错误。 如果你真的只是,线,由线,走 通过您的代码,并比较什么是 实际发生的事情与你的期望 发生的,那么它是相当 很难想念你的错误。 确定。 所以上周大卫提出这个 密钥加密的东西了 第一次,在这里我们不希望 密码只是被储存在我们的 计算机在某些纯文本文件,其中 有人能过来,只是 打开来阅读它们。 理想的情况下,他们会被加密 以某种方式。 而在问题2,你会被处理 用的加密方法之一, 或者,好了,两个方法,但 他们并没有那么大。 如果你这样做的黑客版,你 也将被处理 解密一些事情。 所以,现在的问题是,好吧,就算 我们有强大的加密 算法中的世界,如果你选择了一个 密码特别差,那么它 不会帮你了,因为人们 仍然能够弄明白。 即使看到加密的字符串和 它看起来像垃圾的一塌糊涂 这意味着什么给他们,如果他们 还是只需要尝试一些密码 弄明白,那么你 都不是很安全的。 所以,看一个视频, 使得该点。 [视频回放] - 头盔,你魔鬼,是吧。 这是怎么回事? 你在做什么,以我的女儿? - 请允许我介绍的辉煌 年轻的整形外科医生,菲利普博士 Schlotkin,最大的鼻子 工作的人在整个 宇宙,和比佛利山庄。 - 殿下。 - 隆鼻? 我听不懂。 她已经有了一个隆鼻。 这是一个甜蜜的16出现。 - 没有。 这不是你的想法。 这是非常非常糟糕。 如果你不给我组合 空气盾,Schlotkin博士将 给你的女儿回她的老鼻子。 - 没有。 你从哪儿弄来的? - 所有权利。 我会告诉。 我会告诉。 不,爸爸。 不,你不能。 - 你是对的,我亲爱的。 我会想念你的新鼻子。 但我不会告诉他的组合, 不管是什么。 - 很好。 Schlotkin博士,做你最糟糕的。 - 我的荣幸。 [工具中使用被削尖] - 没有。 等待。 等待。 我会告诉。 我会告诉。 我知道它是可行的。 好的。 把它给我。 - 组合是1。 一体。 一体。 - 两个。 - 两个。 - 两个。 三。 三。 三。 - 四。 - 四。 - 四。 五。 五。 五。 - 因此,组合是1, 两个,三个,四个,五个。 这是最愚蠢的组合 我听说过我的生活。 这是什么样的事情白痴 会对他的行李。 - 谢谢你,殿下。 - 你做了什么? 我关掉了墙上。 - 不,你没有。 你关闭了整部影片。 - 我一定是按错了按钮。 - 好吧,把它放回。 把电影重新打开。 - 是的,先生。 是的,先生。 - 让我们去,阿诺德。 来吧,格雷琴。 当然,你知道,我还是会 必须向您收取此。 [完视频回放] ROB BODEN:好吧。 所以,现在我们已经谈论 安全在某些方面,不错的 小电影的海报,所以在最近的 天,这些问题与国家安全局 监视一切。 它可以是很难感受到如你 有在某种隐私 网络世界,虽然我不能告诉 你最棱镜的细节。 所以超越棱镜,我们不会 要谈的是,现在 想想你的笔记本电脑。 所以在这里,我想切换 我的实际帐户, 我的小企鹅。 所以,我有密码设置,以及 密码是什么,我希望它是。 但要记住一点:我记录 同,所以这个登录 及时,一些程序。 它的一些程序,它是 写的一些人。 因此,这个人,如果它们是 尤其是恶意的,他们可以 已经说过,所有的权利,所以如果密码 我输入等于我 实际的密码,或者它等于 一些特殊的密码 - 大卫是真棒什么 - 然后让他们进来。 因此,一个恶意的程序员可以有 访问您所有的Mac电脑,或 Windows中,或任何东西。 所以这不是太大的关注,因为, 我的意思是,这是login程序 这是随OS X中,数百名 或数千人 审查这个代码。 因此,如果你在代码中的某处,你 说,如果该字符串等于等于 大卫是真棒,登录,然后谁家 将是一样,等待。 这是不对的。 这不应该在这里。 所以这是我们得到的东西的一种方式 是种安全。 不过想想,即使程序 你写。 比方说,你写的登录程序。 所以,你写了这个登录程序, 所以很明显,你是一个好 程序员。 你不会把任何恶意 如果x等于等于大卫是真棒 到你的代码。 但这个程序,你将怎么做 用它来编译这个程序? 类似锵。 那么,如果谁发生的人 写铛专用套管中锵 是这样,如果我编译 登录程序,然后输入这个代码 进入login程序,上面写着,如果 x等于等于大卫是真棒? 所以不太,但我们有同样的 问题在这里,在这里锵,好了, 成千上万,如果不是数以万计 人,都看着铛,有 看着它的代码行并表示, 没事,有什么不好在这里。 显然,没有一个是做 这什么恶意。 但是,什么是铛本身一样, 如果我编译铛? 如果我有一些编译器 编译锵说插入到锵 这个特殊的黑客,说,没事的, 当我编译锵,则 可执行我应该得到特别期待 login程序和插件的内部 此密码,等于等于 戴夫是真棒? 所以请记住,你的编译器本身 需要在某些时候编译。 所以,如果你选择什么样的编译锵 用,本身就是恶意的,那么你 可以拧全 后话。 所以在这里,我们有肯·汤普森 和丹尼斯·里奇。 因此,这是一个标志性的照片。 丹尼斯·里奇是在右边。 他是一个重要的 - 几乎写道C.所以,你可以 感谢他为这一类。 肯·汤姆森是在左边。 他们两个基本上写的UNIX。 那么,他们是主要的贡献者 在UNIX中。 还有一些人。 所以肯·汤普森,在某些时候, 他赢得了图灵奖。 和图灵奖,我一直听说 它引用这样一来,它的 计算机科学的诺贝尔奖。 因此,在图灵奖,他要 给他的获奖感言。 他给出了这样的非常著名的演讲 现在,呼吁信任思考 信任,这是我们链接 到课程网站上。 而在这次讲话中,他说,没事, 所以我写了UNIX,现在所有的 你们这些人使用的是UNIX。 现在,请记住今天,Linux是 直系后裔的UNIX。 OS X中直接使用UNIX。 Windows确实没有那么多,但很多 想法是从UNIX。 于是他去了舞台,并说, 没事,我写的UNIX。 而只是让你们知道,我是 能够登录到每个 你的电脑单之一。 自从我把这些特殊的一个如果x 等于等于肯·汤姆森是真棒, 然后我允许登录。 所以人们都喜欢,好了, 你怎么做呢? 我们看着login程序 仅此而已的存在。 他的样子,好了,我修改了编译器 登录login程序 让login程序现在将有 即x等于等于肯·汤普森 是真棒。 他们说,好,这是不正确的。 我们正在寻找的编译器和 编译器没有任何行 这样的代码。 他想,好,但你是什么 编译的编译器? 他们认为,和他的一样,很好, 我是谁给你的编译器之一 你使用编译的编译器,所以 你要编译一个编译器,即 本身就是恶意的,并会 打破登录程序。 因此,基本上,在这一点上,有 没有办法,你可以看看源 login程序代码 看看什么是错的。 你甚至不能看在 编译的源代码 看看什么是错的。 你需要看机 代码的实际的二进制 编译的编译器看,等待,这些 行代码不应该在这里。 但肯·汤普森把它一步 进一步说,好,有 这些特殊的程序,实际上 帮助你阅读程序的二进制文件, 所以,如果有人使用该程序来 读取二进制文件,他们将看到这些 行代码。 他修改这些程序的说,所有的 好吧,如果你正在寻找的 编译器,不显示这个特定的 组二进制的。 这样,那么你需要采取的步骤 进一步,基本上,这可以有 采取多层次的间接寻址, 在某些时候,没有人实际上 将被检查。 所以这个故事的寓意是,你 不会被写 铛在这个类中。 你将要使用攀登 在这个类中铿锵很多。 对于所有你知道的,铛是一种恶意 程序,它是每一个破坏 单个程序你曾经编译。 并留下你对此很不祥 注意,看你在星期三。 [掌声] 扬声器2:在接下来的CS50。 扬声器3:你怎么敢这么说。 你可以做到这一点。 你这样做之前,你可以这样做 今天,你可以做到这一点的明天。 你已经做了好几年了。 只是去那里做这个。 你可以做到这一点。 [音乐播放]