Subtitles section Play video Print subtitles [MUSIC PLAYING] DAVID MALAN: All right. This is CS50 and this is lecture five. And you'll recall perhaps that in this most current week, you've probably been tackling a little something like this. And if you don't actually have this experience from childhood, what we're referring to in this problem set is these kind of glasses that aren't 3-D glasses because it's both red eyes or sometimes it's just a big piece of plastic. But with this can you actually look up and see what the answer is supposed to be. And so this is the allusion to which we're referring and the goal ultimately in problem set five's who done it is to actually figure out how to implement that kind of red filter. But to do that, you first have to understand this thing, which at first glance, admittedly, looks pretty complicated. But if you dived into the problem already, you'll probably have wrapped your mind around at least a few of these fields like the size of the image or the width of the image and the height of the image, which should be a little more reasonably straightforward. But to implement this, you've had to deal with something called a struct or a structure. And so in C, we have this feature, recall. And we didn't really play with this that much last time. But you've seen it now in forensics, or you soon will. And here we have the definition of a student. So when C was invented decades ago, they didn't foresee the need for a student data type. They had int and char and float and double. But we can invent our own data types much like in Scratch. We can make our own puzzle pieces as follows. Typedef to define a type, struct to say here comes a structure. And what is the structure known as student? Well in this case, I arbitrarily decided that a student would just have a name and a dorm and both of those would be strains. And you can imagine putting other things in there like ID numbers, phone numbers, email addresses, or whatnot so that you can actually combine all of this information together. So let's just take a quick look at how you might use code like this. Here is a file called struct.h. It's common, but not necessary to declare your structures inside of a file that also starts with .h so that we can share it across multiple programs just like with other libraries' header files. And here I've taken those training wheels off as before where, string is actually just a white lie for char star. But this is really the same data structure and it's in a file called struct.h. So let's take a quick look now at a program that actually uses this in struct0.C. So let's take a look at what we've done here. In struct0.C we have some header files up top. But we also include this header file so that we have access to this new custom data type. And then in main we do a few things. We first go ahead and ask the user for an integer called enrollment. So hopefully they'll give us a positive number. If we then do get back a number as expected in line 13, what do we do in English here? How would you just describe what line 13 is doing at this point in the term? Anyone, yeah? AUDIENCE: [INAUDIBLE] DAVID MALAN: Yeah, give us an array of students of size enrollment. So even though on line 11 and prior we didn't know how many students we needed, we did get on line 12 that answer, the enrollment. And so on line 13 we declare an array using a variable saying, give me this many elements, this many students in my array to store things. And then we proceed, in the lines below, as follows. We start iterating over the enrollment from zero on up to enrollment. And we prompt the user on each iteration for a student's name and dorm. And the right hand side of those two lines of code is pretty familiar. You're just calling, get string. But on the left hand side, we do have a slightly new piece of syntax. We have students bracket I, which gives you the i-th students in the array. But what piece of syntax perhaps jumps out at you? Especially if you've never programmed before? And we've not used this symbol just yet in this context. What looks different? Yeah. AUDIENCE: [INAUDIBLE] DAVID MALAN: Yeah, so the .name. So you can probably infer that .name and .dorm is somehow accessing the student's name and the student's dorm. And that's literally all that's happening. This dot operator tells the computer, go inside of the student's structure at that i-th location and store the string that's coming back from get string in that variable. And similarly, do the same for dorm. So it's like taking a struct and then looking inside of it and going very specifically to one of the elements therein. We've never needed this .operator before because in the past, any array, any variable we've had has just been a string or an int or float. We haven't had anything to dive deeper into. So that's all that's going on there. We've encapsulated, so to speak, inside of a student structure, name and dorm. And then this last part is actually just a printing out of that same information. We're just printing out, so-and-so is in such-and-such a dorm by passing in those two strings using our familiar percent S. Now this program at the end of the day is kind of pointless because you prompt the user for some number of students' names and dorms, you print them out, and then you throw them away forever. And that's not all that useful of a program long term. And so we have in our second version of this program, struct 1.C a new trick, too. That's a teaser as well for the direction we're going in this problem set, next problem set, and beyond, where we're actually using files where files on a computer are just a whole bunch of bits, zeros and ones. Those zeroes and ones follow some pattern. But we have yet to see a mechanism for actually saving files. But here's how we can do it. So above this line here, 21 and above, same program. Just get a bunch of students from the user, per their name and dorm. Then here line 24 we see something that's a little new, though you have seen this in the forensics problem so far. We call a function called F open, meaning file open. That takes two arguments, according to its documentation. The name of the file you want open and then the second argument is how you want to open the file. And even if you've never seen this before, what might the W there represent? AUDIENCE: [INAUDIBLE] DAVID MALAN: Yeah, right. So it's read and write are two of the most common operations for a computer. R would be read, W would be write. And this kind of makes sense if the goal now is to save these students to a file so that the program is actually useful if you run it again and again. So here we have a new data type on the left. It's all caps, which is a bit of an anomaly, even in C. But file, star, file just says, hey, give me a variable of type file that can store the address of a file, so to speak. And technically, that's not the address of the file on disk. That's the address in RAM once you've opened the file. But for now, just assume that this is an abstraction for the file. And it's just called literally file. So what is line 25's purpose in life? Even though we've never written this code before now. Yeah, what do you think? AUDIENCE: If the file exists. DAVID MALAN: If the file exists, or more generally, if the file was successfully opened. Because there could be bunches of things that go wrong. One, as you've implied, the file might not exist. Two, maybe you don't have permission so it exists but you can't open it. Three, maybe there's not enough memory in the computer to open yet one more file. So any number of things could go wrong. And recall, what is the special sentinel value that typically represents errors now that we're in the world of pointers? Null, so N-U-L-L in all caps is sort of the opposite of having a valid address. It means no such address. So we use it to check for errors. So that's all line 25 is doing. And then the rest of this is almost identical to the previous program, except we're not using print F. What are we apparently using? F print F and take a guess as to what the F in print F stands for? Yeah, so file print F. So it works almost the same except it takes one more argument. The very first argument now is not a format string like it's been for ages now. It's instead a variable that references an open file and then the rest of this is all the same. So what's really cool about F print F is that you don't just print to the screen. You actually print to whatever file you've opened so that then, on the very last line here, when I call F close, that's equivalent to saving the file.