[Powered by Google Translate] [演练 - 习题集4]
[Zamyla陈 - 哈佛大学]
[这是CS50。 - CS50.TV]
好的。你好，大家好，欢迎来到演练4。
>> 今天，我们的pset取证。
取证是一个非常有趣的pset中涉及位图文件
发现谁犯了罪。
然后我们要改变某些位图文件，
然后我们要处理一个真正有趣的部分称为恢复，
我们基本上是交给一个记忆卡
有人不小心删除他们的所有文件，
我们要求恢复这些文件。
>> 但是，首先，在我们进入的pset中，我真的只是想祝贺大家。
我们在这门课程的中点。
测验0是在我们的身后，我们在pset4，所以基本上，我们已经完成一半。
我们已经走过了很长的路要走，如果你回头看看您的pset中，pset0和pset1移动，
所以祝贺了解，
我们会得到一些真正有趣的东西。
>> 因此，我们的工具箱，这pset的，而不是运行sudo yum的-Y更新，
我们可以只运行update50，如果你在17.3及以上版本的设备。
所以一定要运行update50 - 这是一个容易得多，少一些字符 -
以确保你在最新版本的设备。
尤其重要的是update50当我们开始使用CS50检查。
所以一定要确保你这样做。
>> 对于所有此pset的部分，
我们将要处理的文件的输入和输出，文件I / O。
我们将要超过了很多的阵列处理的程序
指向文件之类的东西，
所以我们要确保我们是非常熟悉和舒适的
处理与如何到文件中的输入和输出。
>> 在分配的pset此代码是一个文件名为路径'％s'，
这就是我们要寻找的是要真正对我们有用的
因为我们要结束了，其实复制copy.c文件
，只是略微改变，能够实现第2部分的问题集。
>> 这样的话，正如我之前提到的，我们正在处理的位图，以及为JPEG格式。
所以，真正了解这些文件是如何组织的结构，
我们如何才能真正转化到结构的“0”和“1
和活动，我们实际上可以理解，解释和修改，
这将是非常重要的，
进入JPEG和位图文件，并了解这些结构。
>> Pset4，像往常一样，开始了部分问题。
这些将处理文件I / O，让你习惯了。
第1部分是谁是凶手，你给定一个位图文件
看起来有点像所有的红点。
然后基本上我们要做的是这个文件，只是稍微编辑
到一个版本，我们可以阅读。
从本质上讲，一旦我们完成，我们将具有相同的文件，
除了我们就可以看到隐藏的信息隐藏所有那些红点。
然后调整是一个程序，给定一个文件
然后给予它输出的文件的名称，然后给出一个数字，以及
实际上将调整该位图的大小，整数的值。
最后，我们有“恢复”的pset。
我们有一个记忆卡，然后恢复所有的照片
被意外删除，
但是，正如我们将要学习的，而不是被真正删除，并从文件中删除;
我们刚刚失去了他们在该文件中，但我们要恢复的。
>> 大。因此，进入文件I / O具体而言，这是一个整体，你将要使用的功能列表。
你已经看到了一点点的FOPEN的基本知识，FREAD和FWRITE，
但是，我们要进一步研究的一些文件I / O功能，如的fputc，
在你只写一个字符的时间，
FSEEK，在那里你一种向前和向后移动文件指针位置，
然后一些人。但我们会进入一个位在pset的。
>> 因此，首先进入文件I / O之前，我们去到的pset
打开一个文件，例如，你有什么做的实际上是一个指针，指向该文件。
因此，我们有一个FILE *指针。
在这种情况下，我称这是一个指针，因为这将是我的INFILE。
所以我要使用该功能打开，然后文件的文件名
然后我要的模式，在这模式下，将处理文件。
因此，有“R”在这种情况下，阅读，“W”的写作，然后“A”为追加。
例如，当你正在处理一个INFILE
所有你想要做的是阅读的比特和字节存储在那里，
那么你可能会想使用“r”作为您的模式。
当你想真正写，一种新的文件，
然后我们要做的是，我们要打开新文件
使用“w”模式编写。
>> 那么，当你读入的文件，其结构如下。
首先，你的struct的指针将包含你正在读的字节。
所以这将是你正在读的字节的结束位置。
然后，你要显示的大小，基本上是想有多少个字节
你的程序读入的文件的大小基本上是一个元素，
然后你要指定你想读多少个元素。
最后，你必须知道你正在阅读，
所以这将是您在指针。
我的颜色编码，这是因为FREAD也很类似FWRITE，
但你要确保你使用正确的顺序，
确保你实际写入或读取正确的文件。
>> 那么像以前，如果我们有元素的大小，以及元素的数目，
那么我们就可以在这里玩一点点。
假如我有一只狗的结构，这样的话，我想读的两条狗在一个时间。
有什么我可以做的，是说一个元素的大小将是一只狗的大小
我要到实际读取他们两个人。
另外，我可以做什么，说我只是要读一个元素
一个元素将是两只狗的大小。
所以这是类似的，你可以玩耍的大小和数量
根据更直观的给你。
>> 好的。所以现在我们得到的书面文件。
当你想要写一个文件，第一个参数实际上是你正在阅读。
所以，基本上，你要写入文件的数据，
这是满分指针末端。
所以，当你正在处理的pset中，确保你不要混淆。
也许有并排的定义。
你可以把定义在本手册中键入man，然后FWRITE，例如，
在终端上，或者你可以参考这个幻灯片
并确保您使用的是正确的。
FWRITE，所以，再一次，当你有一个文件，你要写入，
那将是最后一个参数，那将是一个指针，指向该文件。
那么，我们如何处理也许是几个字节写一次，
但说你只想写的只是一个单一的字符。
正如我们将看到在这个例子中，我们将不得不使用的位图，。
这时候，我们可以使用的fputc，基本上只是把一个字符的时间，字符，
文件指针，这就是我们的了指针。
所以，每当我们寻求或写在一个文件中，
该文件是跟踪我们的地方。
因此，它是一种指针，文件指针位置。
所以每当我们到一个文件中写入或读取，
该文件实际上还记得它在哪里，
因此它继续从光标所在。
这可能是有益的，当你想，说，读一定量做一些事情
然后阅读以下金额，
但有时我们可能要回去，其实从一定的参考价值。
那么的fseek函数，它的作用是让我们将光标移到特定的文件
一定数目的字节。
然后我们要做的是指定的参考价值。
因此，无论是向前或向后移动光标目前，
或者我们可以指定它应该只是从开头的文件
或从该文件的结束。
所以你可以通过在正面或负面的价值金额，
将一种向前或向后移动光标。
>> 在我们进入其他pset，任何问题上的文件I / O？
好吧。当我们进入更多的例子，随意停止我的问题。
>> 因此，在谁是凶手，你交给一个位图文件，这个红色的幻灯片上的类似，
和它看起来像这样 - 一堆红点 - 你真的不知道写的什么。
如果你眯着眼睛，你也许可以看到一个淡蓝色的颜色殿内正中。
从本质上讲，这是其中的文本存储。
有一宗谋杀案发生这种情况，我们需要找出是谁做的。
为了做到这一点，我们需要一种转换图像转换为可读格式。
如果你们遇到过，有时会有小的包
在这里您将有一个放大镜，用一个红色的膜。任何人？是啊。
所以，你会交到这样的事情，你将有一个放大镜
红色薄膜，你需要把它的形象，
你就可以看到其中隐藏的信息。
我们没有一个放大镜红膜，所以不是我们要创建我们自己的
在此pset中。
这样一来，用户要输入的侦探小说，然后线索，BMP，
所以这是infile中的红点消息，
然后他们说，将是verdict.bmp我们outfile中。
因此，它要创建一个新的位图图像，类似的线索之一
除了以可读的格式，我们可以看到隐藏的信息。
>> 既然我们要处理的编辑和操纵某种形式的位图，
我们要深入到这些位图文件的结构种。
我们走过去，这一点在课堂上，但让我们看看他们更多一些。
位图是本质上只是一个字节安排
在我们所指定的字节的意思是什么。
因此，这里是有点像一个地图的位图图像
说，它开始与一些头文件，开始在那里的一些信息。
您看到的大小，字节数14位图图像显示，
它继续。
那么是什么在这里，我们真正感兴趣的字节数54左右开始。
我们这些RGB三元组。
会做的，是包含的实际像素的颜色值。
一切都在头以上，一些信息
对应的图像的大小，图像的宽度和高度。
当我们去填充后，我们将看到为什么大小的图像
可能会对不同比的宽度或高度。
那么这些代表 - 这些位图图像的字节序列 -
我们可以做什么，说好了，我会记住，在指数14，
这就是的大小，例如，而是我们要做的是什么使这更容易
被封装在一个结构。
因此，我们有两个结构，对我们来说，BITMAPFILEHEADER
和BITMAPINFOHEADER，
所以每当我们阅读到该文件，默认情况下它会为了，
等，以便它也是要填写到变量，如biWidth和biSize。
然后最后，每一个像素由三个字节表示。
第一个是蓝色的量，在像素中，第二个是绿色的量，
最后，红色，其中0基本上是没有没有绿色或蓝色或无红
然后ff是最大值。
这是十六进制值。
那么，如果我们有FF0000，然后，对应于最大数量的蓝色
，然后没有绿色，没有红色的，这样的话，会给我们一个蓝色像素。
然后，如果我们有FF的所有一刀切，那么这意味着我们有一个白色像素。
这是一种相反通常，当我们说RGB。它实际上是要BGR。
>> 所以，如果我们真正寻找到一个位图图像的一个例子 - 让我拉一起来这里。
这是小了点。
我放大，我们可以看到它的像素化。它看起来像块的颜色。
你有白块，然后红色块。
如果您在Microsoft Paint发挥，例如，你可以做这样的事情
由基本上只是画的某些方块以特定的顺序。
那么这将转换为位图中如下。
在这里，我们第一个白色像素，所有f的，然后我们有红色像素，
由0000FF表示。
所以，我们的字节序列表示的位图图像去看看。
那么，我在这里所做的只是写出来的所有字节，然后在红色着色
所以，你可以看到那种，如果你眯着眼睛一点点，这样的表示了一个笑脸。
>> 位图图像是我工作的方式，设想它基本上是作为一个网格。
并且默认情况下，每行的网格是一个4字节的倍数。
如果我们看一下在一个位图图像，你填写的每一个值。
例如，您可能有一个红色的，绿色的，蓝色的，
但你必须确保图像被填充在与四个字节的倍数。
所以，如果我希望我的3块宽的图像，那么我将不得不放了一个空值
中的最后一个，使其四的倍数。
那么我想补充的东西，我们称之为填充。
我只是要表明，有一个x。
现在说，我们想要的是7个像素的图像，例如。
我们有1，2，3，4，5，6，7，
所有这一切都填充有颜色。
位图图像的工作方式是，我们需要一个8。
现在，我们有1，2，3，4，5，6，7。
我们需要8个空格的正确读出的位图图像。
那么我们需要做的只是一点点填充添加
以确保所有的宽度是均匀的
和所有的宽度是4的倍数。
所以，我曾表示，填充x或波浪线，
但在实际的位图图像的填充表示由十六进制的0。
因此，这将是一个单一的字符，0。
可能会派上用场的，是xxd命令。
它的作用是告诉你，像类似我以前的笑脸
当我真正打印出每种颜色的像素
颜色编码，当您运行XXD用下面的命令，
然后，它实际上会打印出这些像素的颜色是什么。
你必须做的是，在这里我表示，如第54
说，我要在第54个字节开始
因为在此之前，记住，如果我们回头看地图的位图，
这是所有的头信息之类的东西。
但是，我们真正关心的是实际像素，显示的颜色。
因此，通过增加标志，第54条，我们能够看到的颜色值。
不用担心复杂的标志之类的东西。
在问题设置规范，你会如何使用XXD显示像素的方向。
所以，如果你在这里看到的，它看起来像一个绿色的盒子，这个小东西。
我颜色编码的00FF00，基本上可以说没有蓝色的，有很多绿色，没有红色的。
因此，对应于绿色。
当你看到这里，我们看到了一个绿色的长方形。
这绿色的长方形只有3个像素宽，所以我们必须做什么
以确保4宽的图像是一个多添加额外的填充。
这样的话，你怎么看这些0。
这实际上是调整大小的pset的结果，
基本上采取的位图，然后把它做大了4。
因此，我们看到的是，其实这个图像的宽度为12像素，但12是4的倍数，
，所以我们没有看到任何结束时为0，因为我们不需要添加任何
因为它的完全填充。它没有任何更多的空间。
>> 好吧。任何填充的问题吗？
好吧。酷。
>> 正如我之前提到的，只是一个位图的字节序列。
因此，我们所拥有的，而不是确切的字节数进行跟踪
对应于一个特定的元素，我们实际上已经创建了一个结构来表示，。
所以，我们是结构的一个RGBTRIPLE。
只要你有一个RGB三元组的一个实例，
因为这是一个类型定义结构，然后您可以访问rgbtBlue的变量，
类似地，绿色和红色的变量，这将表明多少蓝色，绿色，红色，
分别，你有。
>> 因此，如果我们有蓝色的变量设置为0，绿色设置为FF，
这是最大的值，可以有，然后红色的变量设置为0，
然后这个特殊的RGB三什么颜色代表什么呢？ >> [学生]绿色。
绿色。没错。
这将是有益的知道，只要你有一个RGB三元组的一个实例，
实际上，可以访问的颜色量 - 蓝色，绿色和红色 - 分开。
>> 现在，我们已经讨论过的结构，让我们来看看在BMP文件。
这些为你做的是结构。
在这里，我们有一个BITMAPFILEHEADER结构。
有趣的是大小。
后来，我们的头部信息，其中有几个很有趣的事情，我们，
即的大小，宽度，和高度。
正如我们将要进入​​以后，当你在阅读该文件，
它会自动读取的，因为我们已经设置的顺序是一样的。
所以biSize将包含对应于该图像的实际大小的正确的字节。
那么在这里，最后，正如我们已经谈到，我们有RGBTRIPLE typedef结构。
我们有rgbtBlue，绿色，红色与。
>> 大。好吧。
现在，我们一点点了解位图，了解我们有一个文件头
和信息头与它，然后在那之后，我们有一个有趣的东西
的颜色，这些颜色RGBTRIPLE结构表示的，
和那些，反过来，具有相关联的三个值的蓝色，绿色和红色。
>> 所以，现在，我们可以一种想恢复一点。
抱歉。想想谁是凶手。
当我们有我们的线索文件，然后我们想要做的是阅读像素的像素
然后以某种方式改变那些像素，这样我们就可以输出到一个可读的格式。
因此，对于输出，我们要去，写像素的像素到verdict.bmp文件。
这是种有很多事情要做。我们意识到这一点。
所以，我们做了什么，我们实际上已经为您提供了copy.c.
路径'％s'不只是一个给定的位图文件的精确副本，然后将它输出。
因此，这已为您打开该文件，读取像素由像素
然后将数据写入到输出文件中。
>> 让我们来看看在那。
这是确保正确使用，
这里的文件名。
这是什么做的是设置输入文件是什么，我们已经通过在这里的infile，
这是我们的第二个命令行参数。
检查，以确保我们可以打开该文件。
检查，以确保我们可以建立一个新的输出文件在这里。
这是什么在这里所做的，只是基本上从一开始就读取位图文件。
开始的时候，我们知道，包含BITMAPFILEHEADER，
这些序列位直接填写在BITMAPFILEHEADER。
所以我们在这里说，BITMAPFILEHEADER BF -
这是我们的新的变量类型BITMAPFILEHEADER -
我们打​​算把我们从指针内BF，这是我们的INFILE。
我们读多少？
我们读我们需要多少字节包含整个BITMAPFILEHEADER。
同样的，这就是我们做的头部信息。
因此，我们将继续沿着我们的文件将infile，
正在阅读这些比特和字节，和我们直接插入在
在这些情况下，我们正在做的变量。
在这里，我们只是确保该位图是一个位图。
>> 现在我们有一个输出文件，对不对？
因此，它代表我们创建它时，它基本上是空的。
因此，我们必须从根本上从头开始创建一个新的位图。
我们做的是，我们必须确保，我们将在文件头
和头文件的信息一样将infile。
我们做的是我们写的 - 并且要记住，BF是变量
类型BITMAPFILEHEADER，所以我们要做的是，我们只是使用这些内容
写入outfile中。
在这里，记得我们谈到了填充，
如何重要的是要确保，我们的像素量是4的倍数。
这是一个非常有用的公式来计算你有多少填充
您的文件的宽度。
我希望你们要记住，在路径'％s'，我们有一个公式计算填充。
可以吗？所以每个人都记住这一点。大。
那么什么路径'％s'下的是它遍历所有的扫描线。
它首先通过行，然后将它读取每三
然后将数据写入到输出文件。
那么在这里，我们正在阅读的时间只有一个RGB三
然后把同样的三到outfile中。
棘手的部分是填充不是RGB三，
，所以我们不能只是读，填充量的RGB三元组。
我们要做的其实只是我们的文件位置指示器移动，移动的光标，
种跳过所有的填充，使我们在下一行。
这是什么做的是复制显示你如何，你可能要添加的填充。
因此，我们计算我们需要多少填充，
所以，这意味着我们需要填充的0。
这是一个循环，将填补数的0到我们的OUTFILE。
然后，终于，您可以关闭这两个文件。关闭的infile和outfile中。
>> 所以这就是的copy.c作品，
而这将是非常有用的。
而不是仅仅居然直接复制和粘贴
或者只是看着它，输入任何你想要的，
你可能只是想在终端中执行此命令，
CP路径'％s'whodunit.c，这将创建一个新的文件，whodunit.c，
包含的确切内容相同的复制品。
那么，我们能做些什么，作为一个框架，用于构建和编辑
我们的侦探小说文件。
>> 这些都是我们的待办事项给谁是凶手，但什么copy.c
实际上他们大多数人对我们的照顾。
所以，接下来我们需要做的是根据需要改变像素
真正使文件可读。
请记住，对于一个给定的像素三倍，所以对于一个给定的变量的类型RGBTRIPLE的，
可以访问的蓝色，绿色和红色的值。
这是怎么回事就派上用场了，因为如果你可以访问他们，
这意味着，您还可以检查它们，
这意味着，你也可以改变他们。
>> 所以，当我们又回到了我们的红色放大镜的例子，
基本上，这是对我们的一种过滤器。
所以我们想要做的是，我们要过滤所有的三元组来
有几种不同的方法来做到这一点。
基本上，你可以有你想要的任何类型的过滤器。
也许你想改变所有红色像素
也许你想改变不同的颜色，不同的颜色的像素。
这是给你的。
记住，你可以检查像素是什么颜色的
然后你也可以改变它的时候，你会通过。
>> 好吧。所以，谁是凶手。
一旦运行了谁是凶手，你会知道谁是犯罪的罪魁祸首。
>> 现在，我们将去调整大小。
我们将仍然可以处理位图。
我们要做的是，我们将有一个输入位图
然后我们要通过一个号码，然后得到一个outfile中的位图
基本上是我们INFILE比例由n。
说我的文件只是一个像素大。
然后，如果我的n为3，缩放，3，然后我会重复n次的像素，
如此3遍，然后还扩大了3倍为好。
所以，你看我将其扩大为水平和垂直方向。
>> 那么这里是一个例子。
如果您有n = 2时，您会看到第一个蓝色像素重复两次
水平良好两次垂直。
然后继续，让你有一个直接的原始图像缩放2。
>> 那么，如果我们要详细的伪代码，我们要打开的文件。
然后知道，如果我们回到这里，
我们看到的宽度与outfile将是不同的宽度将infile。
这是什么意思呢？
这意味着，我们的头信息是不会改变。
因此，我们会想要做的是更新的头信息，
知道，当我们读到的文件，如果你经营的copy.c框架，
我们已经有了一个变量，它的大小是什么之类的东西。
所以，一旦你有，你可能想要做的是改变这些特定的变量。
请记住，如果你有一个struct，你如何访问内的变量。
您可以使用点操作符，对不对？
那么，你知道，你需要改变的头信息。
所以这里只是一个将要改变你的文件列表中的实际元素。
文件的大小将被改变的图像，以及在宽度和高度。
因此，然后回过头来在地图上的位图，
看是否包含该信息的文件头或头文件的信息
然后根据需要进行更改。
同样，说CP路径'％s'resize.c。
这意味着，resize.c现在包含一切的包含在复制
，因为副本为我们提供了在每个扫描行的像素由像素的阅读方式。
但现在，而不是仅仅改变的值，就像我们在谁是凶手，
我们想要做的是我们要写入多个像素
只要作为我们n是大于1的。
>> 然后我们想要做的是，我们要伸展它由n个水平，
以及由n个垂直伸展。
我们怎么可能这样做呢？
假设n是2，你有这样的INFILE。
你的光标将开始在第一个，
你想要做什么，如果n是2，你要打印2。
所以，你打印2。
然后将光标移动到下一个像素，它是红色的，
这将打印出的那些红色的，其追加到它做什么之前。
然后将光标移动到下一个像素，并吸引2。
如果你回头看看在这里copy.c框架，这是什么做的
它创建了一个新的RGB三，一个新的变量三。
这里读入它，它会读取从INFILE 1 RGBTRIPLE
，并将其存储，三联变量的内部。
那么你确实有一个变量，代表特定的像素。
然后，当你写，你可能想要做的是包住的fwrite语句转换成一个for循环
，将其写入到您的outfile中根据需要尽可能多的时间。
这是很简单的。
只需基本上重复n次写作过程中它的规模水平。
>> 那么，我们一定要记住，我们的填充是不会改变的。
在此之前，说我们有一些东西长度为3。
然后，我们想添加多少填充？只是多了一个4的倍数。
但说我们在这个特殊的图像缩放为n = 2。
那么我们有多少蓝像素的结束吗？我们有6个。
1，2，3，4，5，6。好的。
图6是不是4的倍数。最近的4的倍数是什么？这将是8。
因此，我们实际上有2个字符填充。
>> 如果有谁还记得我们有一个公式来计算填充
和可能是什么？
[听不见的学生响应呀，copy.c.右。
有一个公式计算你有多少填充在路径'％s'
给定一个特定的位图图像的宽度。
那么，那将是非常有用的，当您需要添加一定量的填充
找出你需要添加多少填充。
不过，虽然是一个音符，您要确保您使用的是正确的大小。
只是要小心，因为你基本上要处理的两个位图图像。
您要确保您使用的是正确的。
当你计算的填充outfile中，您要使用的宽度与outfile
的宽度，而不是以前的一个。
>> 大。那种需要护理的水平拉伸整个位图图像。
但是，我们想要做的就是伸展和垂直方向。
这将是一个有点棘手，因为当我们已经完成了复制行
和书面行，光标要在年底。
因此，如果我们看了一遍，然后它只是要读入到下一行。
所以我们想要做的是找到某种方式再次复制这些行
或只是一种采取这一行，然后重写一遍。
正如我种提到，有几种不同的方法来做到这一点。
你可以做的是，你要通过读通过特定的扫描线
和在必要时改变它，然后种存储在数组中的所有的那些像素。
后来你知道，你需要再次打印出该数组，
，所以你可以使用该数组来做到这一点。
做到这一点的另一种方式是你可以复制到下一行，
知道你需要再次复制，所以实际上你的光标移动，
这就是将要使用的方法FSEEK。
你可以将你的光标所有的方式回到，然后再重复复制过程。
>> 因此，如果我们缩放数为n，则多少次，我们要回去
并重写一条线吗？ >> [学生] N - 1。 “是的，完美的。 N - 1。
我们已经做了一次了，这样的话，我们将要重复的回头路过程
N - 1倍量。
好吧。所以，你有你的大小调整功能。
>> 现在，我们可以得到一个真正有趣的部分，我最喜欢的pset，这是恢复。
而不是位图，这个时候，我们正在处理的JPEG文件。
我们实际上没有给定文件的JPEG文件一样，
我们基本上是一个原始的记忆卡格式。
因此，这包含一个位的信息和垃圾值开始，
然后它开始和它有一堆的JPEG文件。
但是，我们递上一张卡，我们已经删除了照片;
从本质上讲，我们已经忘记了位于卡内的照片。
那么在恢复我们的任务是去通过此卡格式
再次找到这些图片。
>> 幸运的是，JPEG文件的结构，卡文件是有点帮助。
它肯定是有点麻烦，如果不是在这种特定的格式。
其实每一个JPEG文件有两个可能的序列，上面列出的开始。
基本上，只要你有一个新的JPEG文件，
开始序列FFD8 FFE0或另一个，FFD8 FFE1。
另一个有用的东西知道的是，JPEG文件连续存储。
所以，每当一个JPEG文件的结束，另一个开始。
这样就不会有在值之间有任何种。
一旦你点击开始，如果你已经读一个JPEG的JPEG，
你知道你已经打了结束的上一个和下一个开始。
>> 种形象化，我做了一个示意图。
另一件事对JPEG文件，我们可以阅读他们在一个时间序列中的512个字节，
同样与该卡的开头。
我们并不需要检查每一个字节，因为这会吸。
因此，不是，我们能做些什么，其实只是在512个字节读取一次
然后，而不是检查之间的这些微小的小片，
我们可以只检查开始的512个字节。
从本质上讲，在这幅画中，你看到的是在开头的卡，
你有值的实际JPEG文件本身是不是真的有关。
那么是什么我已经是一个明星来表示两个序列的JPEG。
所以，当你看到一个明星，你知道你有一个JPEG文件。
然后每一个JPEG文件将是一些512字节的倍数
但不一定是相同的多。
你知道你已经达到了另外一个JPEG的方式，是如果你击中​​另一颗恒星，
另一种起始的字节序列。
你在这里的是你有红色的JPEG文件继续，直到你击中的明星，
这是一个新的颜色表示。
您可以继续，那么你击中另一颗恒星，你打另一个JPEG，
你继续一路，直到结束。
你在这里的最后一张照片，粉红的。
去年底，直到你击中的文件结束符。
这将是非常有用的。
>> 有一些主要的takeaways：
卡中的文件无法启动与JPEG，
但，一个JPEG一旦开始所有的JPEG文件存储并排彼此。
>> 一些伪代码的恢复。
首先，我们要打开我们的卡中的文件，
这就是将要使用我们的文件I / O功能。
我们要重复以下过程，直到我们已经走到了尽头的文件。
我们要读512字节的时间。
我在这里说的是，我们将其存储在缓冲区中，
所以基本上举行，512个字节，直到我们知道该怎么做与他们。
然后我们想要做的是，我们要检查我们是否已经打了星型或不。
如果我们碰到一个明星，如果我们碰到一个起始序列，
然后，我们知道，我们已经打了一个新的JPEG文件。
我们将要做的是，我们将要创建一个新的文件在我们pset4目录
继续该文件。
但同时，如果我们已经做了一个JPEG之前，
然后，我们要结束该文件，并将其推的pset4的文件夹，
我们将在这里，因为如果我们不指定，我们已经结束，JPEG文件，该文件存储
基本上，我们将有一个不确定的量。 JPEG文件将永远不会结束。
因此，我们要确保，当我们在阅读中的JPEG文件，并书面，
我们要明确关闭，在打开​​下一个。
我们需要检查几件事情。
我们要检查是否我们在开始一个新的JPEG与我们的缓冲区
并且，如果我们已经找到了一个JPEG前
因为这会稍微改变你的过程。
那么，你通过所有的方式，你打到最后的文件，
然后你会想要做的是，你要关闭当前打开的所有文件。
这将可能是最后的JPEG文件，你有，
以及卡中的文件，你已经处理。
>> 最后的障碍，我们需要解决的是如何使一个JPEG文件
以及如何将其推到该文件夹​​。
pset的要求，每一个JPEG，你觉得在下面的格式，
在那里你有多少jpg文件。
的数量，即使是0，我们把它称为000.jpg。
无论何时你发现在你的程序中的一个JPEG，
你会想要将它命名的顺序，它的发现。
这是什么意思呢？
我们需要跟踪我们发现有多少种
每个JPEG数应该是什么。
在这里，我们将充分利用sprintf函数。
类似printf，它只是打印到终端，
sprintf的打印文件到该文件夹​​中。
因此，这是什么会做，如果我的sprintf，标题，然后还有的字符串，
它会打印出2.JPG。
假设我已经关闭了正确的文件，
将包含的文件，我已经写出来。
但有一件事是代码，我这里有
并不完全满足pset的要求。
pset的要求，第二JPEG文件应该被命名为002，而不是只有2。
所以，当你打印出了名，那么也许你可能要稍微改变了占位符。
>> 有谁还记得我们如何让多余的空格，当我们打印的东西吗？
是啊。 >> [学生]你把3百分号和2之间。 “是的，完美的。
你会在这种情况下，因为我们希望把3 3空间。
％3D可能会给你002.JPG而不是2。
到sprintf函数的第一个参数实际上是一个字符数组，
我们以前所认识的字符串。
那些意志，一种更像是一个临时的存储，只存储所得到的字符串。
你不会真的要处理这个问题，但你需要把它列入。
>> 知道每个文件名的数量，这会占用三个字符，
。JPG，多久这个数组应该是什么？
扔掉了一些。多少个字符的标题，在名称？
因此，3＃标签，期间，JPG。 >> [学生] 7。 >> 7。不完全是。
我们要去想，因为我们希望允许空终止。
>> 最后，就是画出来，你会做恢复的过程中，
你有一些开始的信息。
您可以继续，直到你找到一个JPEG文件开始，
而且可以是任一个的两个起始序列。
您继续阅读。在这里每一个斜线代表512个字节。
您继续阅读，继续读，直到你遇到另一个序列。
一旦你有，你结束当前的JPEG - 在这种情况下，它是红色的，
所以你要结束。
你想sprintf的，到您的pset4文件夹的名称，
然后，你要打开一个新的JPEG，然后继续阅读
直到你遇到下。
继续阅读，继续读下去，
然后最后，最终，你会到达终点的文件，
所以你要关闭的最后JPEG您正在使用，
sprintf的，到您的pset4的文件夹，然后看所有的图片，你已经得到了。
这些图片实际上是图片CS50人员，
所以这是在pset的奖金有趣的部分来
是，你在你的小节竞争的图片中找到TFS
并与他们拍照，以证明你已经做了的pset
所以你可以看到，这名工作人员的图片。
那么你拍照的工作人员。有时你会追下来。
也许有些人会尝试离开你。
您与他们拍照。
这是正在进行中。这是不是因为在pset是由于。
在规范中，将公布的截止日期。
然后一起与您的部分，取其部分的大多数图片
与大多数工作人员将获得一个非常可怕的奖品。
这是一种激励得到尽快您的pset4完成
因为这样你可以正事
追捕不同的CS50工作人员。
不过，这不是强制性的，因此，一旦你得到的图片，
那么就大功告成了与pset4。
>> 我完成了演练4，所以，谢谢你的光临。
祝你好运与取证。 [掌声]
[CS50.TV]