DAVID J. MALAN: All right, this is CS50 and this is the end of Week 1, so study cards are in and the total number of classmates that you have this year is 745. And we're so thrilled to have so many of you in the course this semester, but even though this course is so large, realize that it's these things like Friday lunches, like office hours, 15-person sections, and so forth that are really meant to create this more intimate environment. So even though we may gather once or twice a week, here in Sanders, know that much of your experience in this course will very much be hands-on on alongside of your classmates and the teaching staff. So here we go, Fall 2012. So recall that last time we ended on a note of imprecision, talking about the representation of numbers. And we looked at one of the failures that happened, in the real world, when it came to misunderstanding how computers work. Well, today we'll revisit another one of those ideas as well as continue our discussion of the CS50 client and C and what it means really to program. But first, just a couple of whirlwind announcements. Sections begin this Sunday, and the first week is always a bit of a rapid start, because we just got in your section forms. We're doing the same, now, with the teaching fellows, now that they know their schedules, so we're aiming, by Saturday morning, to follow up with you with your section assignment and TF. Realize that they'll start the next day, Sunday or Monday or Tuesday. And then we will accommodate section changes as they arise in the days to come. Office hours, meanwhile, are, again, tonight, 8 PM to 11, in Annenberg, as well as tomorrow night. Even though the problem sets are generally due on Thursdays at noon, realize you have up to five late days to spend, hence the availability of office hours on Thursdays if you cash in one of those late days and, thereby, submit something on Friday. Let me suggest that Scratch is among the more fun, among the more low key problem sets. And I would hang onto those late days, strategically, just for later in the semester when life starts to get in the way with midterms and other classes. Problem Set 1, meanwhile, would be posted on the course's website this Friday, as will be at the course's walk through video, which will be filmed at 2:30 PM on Friday and then posted online by the next day. So we ended on Monday. I want to--actually, one note here. Because the classes--because Sanders doesn't exactly lend itself to casual Q&A back and forth terribly well, we're going to try something a little new this year, whereby if you're not comfortable raising your hand or you just would rather not raise your hand in a room like this, we're going to have some of the teaching fellows and CAs manning cs50.net/discuss during lecture. So if you have a question because I was completely unclear about something or you're curious about some topic, try posting it there. Tag it with a label of Lecture, and we'll do our best today and next week--we'll try this out--to field it either electronically, online, or if it feels like we should really address it en masse, one of the teaching fellows or CAs will raise their hand and ask anonymously on your behalf. So we'll give this a try and see how well this works. But, by all means, continue to raise hands as you would like. So last time we revealed that 10% or one-tenth is not, in fact, 0.1, like you were taught many years ago. It's in fact, a value like this. But that's not wholly true, right? We just have this constraint in computers whereby, if you only have a finite amount of memory, RAM, or more specifically bits, well, there's only a finite number of things you can represent. For instance, if we have the number zero, and we want to represent in binary, using eight bits, where a bit, again, is a zero or a one, we might represent it as 00000000. And that's a little unnecessarily verbose. Just like in the decimal system in the real world, generally, if you want to write the number 123, we humans probably don't write 00000123 even though, functionally, that's the exact same number. We just drop leading zeros, so to speak. In binary, we can do the same. Binary and zero, zero and binary is just zero. You only need a single bit. But again, the most common unit of measure in the world of computing is bytes, eight bits. Just because one bit, pretty useless. Eight bits, not terribly useful, but at least it's more useful than a single unit of measure. So with eight bits, we'll typically represent binary. So here we have the numbers zero, one, two, and then, as Nate did in our video last Wednesday, we can continue counting up to seven, to eight. And then if we use more and more bits, we can count up to infinity. But if you only have a finite number of these bits, as is the case in any computer system, or even missile system, well, indeed you only have a finite amount of precision. So if you want to represent the number like 0.1, well, the computer has to pick and choose. And if it only has a finite number of numbers it can represent, it can come close to 0.1 for you, but it can't necessarily give you exactly the value that you want. And this is just one of the challenges of computers, underneath the hood, thankfully. As we move farther in the semester, these lower level details become much less interesting, but certainly the application of these ideas can have some very real world ramifications. One is a bit fun. How many of you have seen the amazing movie Office Space? If you haven't, that's your unofficial homework for the week. But in Office Space, the fellows in that movie take advantage of precisely this idea, but they actually stole it from another movie that you might have seen, even years prior. So let me give you a few seconds of this trailer from this amazing movie and this is very much academically relevant. [PLAYS MOVIE] Actually I'm being promoted. I can program a virus that will rip that place off big time. Well, how does it work? Every time there's a bank transaction where interest is computed, there are thousands a day, the computer ends up with these fractions of a cent. But I'm not going to do anything illegal. Illegal? Samir, this is America. You have to swear to God. If nobody knows about this but us, all right? No family members, no girlfriends, nobody. [INAUDIBLE]. Don't worry, man, I won't tell anyone either. [MOVIE ENDS] All right, so maybe I found this movie better than most people here, but in any case, the virus that they were trying to create-- and in the movies, anytime they'd call something a virus, it's generally not actually a virus. It's just a program that someone wrote to do something. And in this case, the guys were trying to write a program that took advantage of their company called Innotech's computing system, whereby computers, too, even when it comes to money, can't necessarily represent money precisely. So even though you might have $0.10 in your bank account, 0.10, well, the computer might actually think that you have this many cents in your bank account. And so what these guys were aspiring to do--and they stole the idea, it turns out from Superman III, where Richard Pryor did the same thing--they were essentially writing programs that aspire to take all of the trailing numbers, all of the tiny, tiny, tiny fractions of pennies, and siphoning those off so that the humans just thought, oh, it's only $0.10 there, but all of those trailing numbers eventually add up. So a wonderful idea and it backfired hilariously in that particular film. But in the real world, too, there are much more concerning implications of these sorts of things. And one of the reasons to dive into the field of computer science is, again, its applicability not to the engineering sciences alone, but just to other fields as well. So this is a less lighthearted look at what can go wrong, but it's also quite eye opening, I think, when it comes to understanding exactly how omnipresent technologies like computers and programming or these days, in the form of software. So this next clip is just about six minutes, continues where we left off last time, but allows us to look a little more in depth at one such of these issues. Let me skip ahead to where we left off, which was right here. And we have part two of two, for about six minutes here. [PLAY MOVIE] Plagued modern rocket technology. In 1991, with the start of the first Gulf War, the Patriot missile experienced a similar kind of number conversion problem. And as a result, 20 people, 20 American soldiers, were killed and about 100 others wounded, when the Patriot, which was supposed to protect against incoming Scuds, failed to fire a missile. When Iraq invaded Kuwait and America launched a Desert Storm in early 1991, Patriot missile batteries were deployed to protect Saudi Arabia and Israel from Iraqi Scud missile attacks. The Patriot is a US medium-range surface-to-air system, manufactured by the Raytheon company. The size of the Patriot interceptor itself, it's about roughly 20 feet long and it weighs about 2,000 pounds. And it carries a warhead of about--I think it's roughly 150 pounds. And the warhead itself is a high explosive which has fragments around it. The casing of the warhead is designed to act like buckshot. The missiles are carried four per container and are transported by a semi trailer. The Patriot anti-missile system goes back at least to 20 years now. It was originally designed as an air defense missile to shoot down enemy airplanes, in the first Gulf War. When that war came along, the Army wanted to use it to shoot down Scuds, not airplanes. The Air Iraqi Force was not so much of a problem, but the Army was worried about Scuds. And so they tried to upgrade the Patriot. Intercepting an enemy missile traveling at MACH 5 was going to be challenging enough. But when the Patriot was rushed into service, the Army was not aware of an Iraqi modification that made their Scuds nearly impossible to hit. What happened is the Scuds that were coming in were unstable. They were wobbling. The reason for this was the Iraqis, in order to get 600 kilometers out of a 300 kilometer range missile, took weight out of the front warhead and made the warhead lighter. So now the Patriot's trying to come at the Scud, and most of the time, the overwhelming majority of the time, it would just fly by the Scud. Once the Patriot system operators realized the Patriot missed its target, they detonated the Patriot warhead. To avoid possible casualties, it was allowed to fall to the ground. That was what most people saw, as big fireballs in the sky, and misunderstood as intercepts of Scud warheads. Although, in the night sky, Patriots appeared to be successfully destroyed Scuds, at Dhahran, there could be no mistake about its performance. There, the Patriot's radar system lost track of an incoming Scud and never launched due to a software flaw. It was the Israelis who first discovered that the longer the system was on, the greater the time discrepancy became, due to a clock embedded in the system's computer. About two weeks before the tragedy in Dhahran, the Israelis reported to the Defense Department that the system was losing time. After about eight hours of running, they noticed that the system was becoming noticeably less accurate. The Defense Department responded by telling all of the Patriot batteries to not leave the systems on for a long time. They never said what a long time was--8 hours, 10 hours, 1,000 hours. Nobody knew. The Patriot battery stationed at the barracks at Dhahran and its flawed internal clock had been on over 100 hours on the night of February 25th. It tracked time to an accuracy of about a tenth of a second. Now a tenth of the second is an interesting number because it can't be expressed in binary, exactly, which means it can't be expressed exactly in any modern digital computer. It's hard to believe. But use this as an example. Let's take the number one third. One third cannot be expressed in decimal, exactly. One third is 0.333 going on for infinity. There's no way to do that with absolute accuracy in decimal. That's exactly the same kind of problem that happened in the Patriot. The longer the system ran, the worse the time error became. After 100 hours of operation, the error in time was only about one third of a second. But in terms of targeting a missile traveling at MACH 5, it resulted in a tracking error of over 600 meters. It would be a fatal error for the soldiers at Dhahran. What happened is a Scud launch was detected by early warning satellites and they knew that the Scud was coming in their general direction. They didn't know where it was coming. It was now up to the radar component of the Patriot system, defending Dhahran, to locate and keep track of the incoming enemy missile. The radar was very smart. You would actually track the position of the Scud and then predict where it probably would be the next time the radar sent a pulse out. That was called the range gate. Then, once the Patriot decides enough time has passed to go back and check the next location for this detected object, it goes back. So when it went back to the wrong place, it then sees no object, and it decides that there was no object. It was a false detection and drops the track. The incoming Scud disappeared from the radar screen. And seconds later, it slammed into the barracks. The Scud killed 28 and was the last one fired during the first Gulf War. Tragically, the updated software arrived at Dhahran the following day. And the software flaw had been fixed, closing one chapter in the troubled history of the Patriot missile. PATRIOT is actually an acronym for "Phased Array Tracking Intercept of Target." All right, so a much more sorrowful outcome of not quite understanding this world. And the takeaway, really, from the film is that the solution there was reboot your missile defense system every once in a while. And so again, one of the aims of this course, certainly on a more humble scale than these applications, is to really open everyone's eyes to exactly how you go about making machines do what you want them to do and how you go about doing that correctly, while along the way doing it well, elegantly, and so forth. And so today, let's dive into a little bit more of this, but so that we don't go too fast, particularly for those less comfortable, but also so that we can retain the interest of those more comfortable, let's just quickly begin with a bit of recap of some of these ideas. And again, ask away, both in person or online, if you have questions so we can keep everyone on the same page. So the CS50 Appliance, quick step back, is what, in your own words? It's OK if you have no idea what those words may be yet. [INAUDIBLE] Okay, so a universal interface for-- that we can all share. Absolutely. So we could, for instance, tell you to go to some website, download this software for Mac OS. Download this software for Windows, configure in this way and that. But the reality is then we run into innumerable technical support issues. And also these days, much of what's being done server side, in the world of computing, especially when it comes to web development and web based applications, is actually quite often done on Unix or Linux computers, as opposed to Macs or Windows PCs. So among the upsides, then, of using this thing called the CS50 Appliance is we'll all have the same environment. So everyone's on the same page no matter what hardware you came to campus with but also will be dabbling in exactly the same environment that you'll be using toward semester's end as well for web development, as well as in the future for real world applications thereof. So more concretely, the CS50 Appliance is a free piece of software that allows you to run another operating system, Linux, in this case, on your own computer, in a window. Now you can't just download the appliance. You need a program with which to play or run the appliance. And that piece of software is generally known as a hypervisor. Hypervisors come in the form of products like VMware, Virtual Box, Parallels. All sorts of companies make software, both free and commercial, alike. What you'll see in Problem Set 1 are instructions on how to obtain free software with which to run the CS50 Appliance. And once you do, you'll have, in a window on your Mac or PC, a desktop environment that looks quite like this, where it has a Start menu-like thing in the bottom left-hand corner. It has a Home folder, or Home directory, in the top left there, a trash can, and so forth. So we'll tease apart the necessary details as we go. But now let's start to dive into C. So C is this programming language, similar in spirit to Scratch, but far less graphical, but ironically, far more powerful once you get savvy with it. So in C, we write programs by writing source code, which is this English-like syntax, similar to the socks demonstration that we did last time that allows you to express yourself fairly precisely, if arcanely, to the computer. So what kind of product software do you actually need to write programs in a language like C, based on our conversation on Monday? [INAUDIBLE] OK, you just need a text editor. You don't need any special software per se to write programs. You just need a text editor like Notepad, on Windows, TextEdit on Mac, or something called gedit, in the world of Linux, which we'll use here. And that's it, to write the programs. But writing's only half of the equation. You then need to run them. But in order to run programs-- you can't run source code. You instead have to do what to it first? Yeah. DAVID J. MALAN: You need to compile it. And, someone else, compiling the source code means-- [INAUDIBLE] DAVID J. MALAN: Exactly. Translating it to zeros and ones. Because all of us, these days, have computers that have CPUs, almost all of which are made by a company called Intel, and Intel Inside, means there's this brain inside of your computer, known as the CPU. And one of the things that that brain does is, it knows how to understand patterns of zeros and ones. It knows what pattern of bits represents addition, what pattern represents subtractions, what pattern of bits represent printing, and creating an audible sound. So in short, the CPU, coupled with the operating system, which is a piece of software that runs on top of the CPU, so to speak. Together, those two pieces know how to run programs that we humans write. So if I go into the CS50 Appliance here, I need to open up a text editor and I can access this in a couple of ways. I can either go to Menu, Programming, and then I can select-- nope, not that menu. I can go to Accessories/gedit here to open my little text editor. Or more simply, I can click this little icon in the bottom left hand corner. And now I get this environment here. It's pretty reminiscent of a simple text editor, with just one or two differences. In the top, where the cursor is blinking now, this is where I can start writing my code. In the bottom is this thing called the terminal window. And what kinds of things can I do in this so-called terminal window? [INAUDIBLE] Okay, so I'll run commands. And some of the commands we ran on Monday were a little cryptic at first, but ls for list, cd for change directory, rm, for remove. So it's sort of an old-school way of navigating your computer, using only your keyboard and textual commands, and not, generally, using a mouse. But we'll see, before long, this actually gives us a little more power and a little more precision with which to express ourselves. And then over here at the left, we're just going to see, as we start writing software, a little summary of the program that we've written at top left. But we'll see that again before long. So let's do something fairly simple here. Let me first go ahead and go to File, Save, and I'm just going to click on jharvard here, over at left, and jharvard is, again, the name for my home folder, my personal files, me, now being John Harvard, as all of you will soon be John Harvard in this environment. He's got this Home directory, My Documents and so forth, that I want to save, now, this file in. So I'm going to call it hello.c. Then I'm going to go ahead and click Save, and now what I have here is a tab called hello.c, so much like another type of editor. So now let me go ahead and start writing a program. int main (void). And then I just did last time, printf, for print formatted, ("hello, world!" );. Almost complete. But I'm missing a couple of details. What is missing from this program that I really need for it to actually compile? Yeah. [INAUDIBLE]? DAVID J. MALAN: Yeah, so I need to include the standard I/O library. So this needs to go above main, so I'm just going to make some room for it there. And I'm going to do #include . And notice the angled brackets there. And as an aside, gedit is a little user friendly, if sometimes a little confusing, in that it tries to help your eyes notice what lines up with what. So the fact that my cursor is right next to this angled bracket, notice how it's highlighting the other angled bracket plus this one. And that's just to draw my attention to the fact that I have symmetry. And symmetry in programming is generally a good thing. Similarly, if I move my cursor to the end, notice how the curly braces line up to show that, yes, I have an open one and a closed one, so to speak. All right, and I can do one other thing. It's not strictly necessary, but good practice, to say return 0. And return 0 does what for us here? Or signifies what? [INAUDIBLE] DAVID J. MALAN: But nothing's wrong. And frankly it's hard for much to go wrong in a program this short. So I'm just being super explicit that all is well. I, the human, when I run this program, will probably never see that 0. Generally, these numbers that are being returned from main only rear their heads to the humans when something goes wrong. And you get a little pop up saying system error, one, two, three, or whatever the number was that was actually returned. So anything else wrong with this? [INAUDIBLE] DAVID J. MALAN: So this is not so much a functional mistake but an aesthetic one. I should probably put in a newline character there at the end of this string so that we actually move the cursor to the next line, and the program just looks a little prettier. So now let me go down to my terminal window and zoom back in. And this thing here, it's called the prompt. It's just reminding me who I am, jharvard@appliance, where appliance is the name of the computer I'm on. In parentheses is this tilde, the squiggle symbol, which represents what? AUDIENCE: Home directory. DAVID J. MALAN: Home directory. So that's just a shorthand notation for saying you are in your personal folder where all of your files go by default. So now, in here, I can type ls for list. And the only thing I see here at the moment is hello.c. And that's good because I just wrote this. So let me go ahead and do make hello. And notice I'm not typing make hello.c. Instead, I'm only typing the base name of the file, hello. And make, as we saw on Monday, will just infer that I want the .c file. So now I've typed make hello. Now I see this fairly long command and will continue seeing this again and again. But to be clear, clang, the word that just appeared, that's the actual compiler. Make is just a build utility. It's just a more user friendly program that saves me, in the long run, from having to type out incredibly tedious long commands like that one. So you could run Clang manually. You could type all of that manually. Just gets very tedious. And so make is just a program that simplifies our lives and runs more complex commands for us. All right, so now what file should I have in my current directory? Not just hello.c, but also hello. So if I want to run hello, recall that I say dot slash, where dot means go into the current folder, wherever you are, and then run the program called hello, and indeed, now, I have hello world. All right, any questions on the workflow or the syntax of what we just did? All right, so let's take things up a notch again. So this was underwhelming to just write a program that only ever says hello, world. So we changed it, on Monday, to say, hello, David. It's a little more personal, but just as hard coded as the first version. So not all that compelling. But there exists, in C, functions certainly besides print, functions that let you get user input. And the way we did this, the other day, was as follows. Before I actually print out something, I first got something from the user. So let me do this again. String s, where s is just an arbitrary name, here, for a string, equals GetString. So what was GetString? It obviously gets a string, based on its name. But what is it, more technically? It's a function. So it's a function that doesn't come with C per se. CS50 staff wrote this. And so to use this, you can't just include stdio.h, You also need to include what? Yeah. So cs50.h, which is just a file we wrote some years ago. We installed it on the appliance for you alongside all of the standard files. And so in these first few weeks of the class, we'll use this just to simplify the process of doing very basic things like getting user input. Because as we'll see in a few weeks, getting user input in a language like C is actually surprisingly complex, particularly because you don't know in advance, usually, how much stuff the user is going to type in. And when you don't know how much data to expect, you don't know how much memory to allocate. And if you actually have an adversarial user who's trying to hack into your system, crash your computer, well, generally the first method of attack is, just as I did on Monday, type a whole long sequence of random characters, hit Enter, and see what breaks. Because generally, if a program breaks, that hints at a security flaw, potentially. It certainly hints at you, the programmer, having made a mistake, but more dangerously, you might have made a security-related mistake, and generally we'll see that that's how machines are compromised to this day, both in the world of the web and programs at the command line, like this. All right. So string s equals GetString. So more concretely now, what does line 6 do here? So the function on the right gets string, takes how many arguments? Okay. So none. A little sanity check. An argument, again, is just an input to a function to alter its default behavior in some way. But in this case, I don't want to alter the behavior of GetString. I just wanted to get a string. So I put nothing in the parentheses, and then I put a semicolon demarking the end of the line of code. Now, the equals sign doesn't mean equal, per se. It means assignment, which means put whatever gets outputted on the right inside of whatever is on the left. So on the left, we say that we have declared a string called s. And more specifically, we've allocated memory inside of which we'll put the bits that represents a sequence of characters. But for today, we have allocated or declared a string. All right. So now once I've done this, I want to plug in the value of s, not the value of David. So this is wrong why? So this is just literally the hard-coded s. It's to say "hello, s," which is not what I want. So I can do this. The percent sign is a placeholder, but now I need to pass into print a second argument. Recall that arguments to functions are separated by commas, so the next comma here I put after this the letter s. And in this context now, s is the variable, and printf, upon receiving those two inputs-- the string on the left and the variable name s on the right-- it will plug the latter into the former for us, and just print out a nice beautiful string containing whatever it is that we typed in. So let's try this. Going to go ahead and zoom out, back to my terminal window. Zoom in at the bottom here. Retype make hello. Clang seems to have been rerun. I'm going to type ./hello, Enter. Nothing seems to be happening yet, but it's at this prompt that I can type something like Nate, Enter, and now we have Hello, Nate. And I can do it again with Rob, and so forth. So hopefully now this program is behaving as I intend. Now, not all that user friendly. I've no idea what's being expected of me. So we can certainly clean this up a little bit. Let me go back up here, and instead of just diving in and asking the user for a string, let me explicitly tell the user what I'm expecting. So printf("Enter a string: " ); So no variables here. No percent signs. Just the simple English phrase. Let me now go to the bottom here and rerun my program. But nothing seems to have changed. Why? I have to recompile it. So easy mistake to make. But you have to not only save the file but recompile the program. And so if I re-run make hello, now Clang runs. Now I can run ./hello. And now I see "Enter a string: ". Okay. Now it's a little more user-friendly. Nate, Enter, hello, Nate. Well, let's try this again and start thinking about corner cases. So just like in Scratch, you're encouraged or are being encouraged in the spec to kind of think about what could go wrong if you don't anticipate everything the user might do. Bugs, therefore, might ensue. So enter a string-- what's a corner case here? What's a scenario that I, the programmer, might not have anticipated? Yeah. Okay. So what if I type in a number like this? All right. So it still works. Gramatically makes no sense. But at least the program works. What's another corner case? Something I didn't expect. Yeah? Okay. So we could do something like a really, really big number. So let's do this here. Let me zoom out for a second, let me highlight. Can't copy and paste down here. All right. So I can't copy and paste in this terminal window, so we'll just simulate it. Let me zoom out, going to wrap. I'm not going to do this for too long, because it won't actually break in this program. But it could. Enter. But it didn't. All right. But it's a genuine corner case. And the only reason that behaved correctly, so to speak, is because the CS50 function GetString is actually designed underneath the hood, as we'll see in a few weeks, to automatically allocate more and more RAM, more and more memory from the operating system, when it realizes, wow, you've really typed in something quite long. Now, this is a bit of a white lie. If we actually paused for quite a while and I typed in something like 5 billion characters at the keyboard here, or really hit copy-paste quite a bit, we quite possibly could cause the program to crash. Just a little harder to simulate that with a finite amount of time. What's another corner case we could try? Yeah? Yeah. So why don't we answer nothing? So we actually have to take some action, because otherwise the program's going to sit there blinking all day. But if I just hit Enter-- OK, now, still looks wrong. Didn't crash, but maybe there's now an opportunity to start implementing a more rigorous program that actually checks. And if the string, the sentence, the word that I typed in has length 0, well, maybe I should yell at the user, or tell him or her to enter a string again, so that we actually get what looks like correct behavior and not just complete oversight on my part. Question in back? Decimal number. So we could try that, too. 1.10000005. Seems like that's going to just work actually okay. And that actually is expected. Even though we might have typed that number there, or a bigger number earlier, realize that when we're typing user input and we're using the GetString function, doesn't matter if what I'm typing looks like a number. Recall that according to ASCII, everything on your keyboard has a numerical value that can be mapped to a character, a char. So in this case, even though I might type a number, the computer is going to think of it, so to speak, as a string-- something that looks like a number, but is not actually a number. But that's actually a perfect segue, because now we can actually transition to writing programs that use other data types. So besides using chars, or rather, besides using strings, realize that we have other data types in C as well as in other languages. A char, as the name suggests, is just a single character. A float is a floating point value, and that's just a fancy way of saying a real number-- something that has a decimal point in it with some numbers to the left and/or right. An int is an integer, which is just a number like 123. And now more interestingly are things like double. What did we say a double was last time? It's 64, right. So whereas typically a float is 32-bit-- so it's this long in memory, it uses 32 zeros and ones to represent values-- a double is literally twice that, which means that you can either represent bigger numbers, or you can represent more precise numbers. So you can have more numbers after the decimal point, but as the fellow said in the video, even something simple conceptually like 1/3 cannot be represented precisely by a computer, because eventually you run out of bits, and therefore you can only do .33333333 so many times, at which point you just have to say I'm out of representation space, I have to just call it a day and represent it somewhat imprecisely like that. And a long long-- stupid name, but it's because there's a data type known as a long in C which coincidentally is often 32 bits, just like an int is 32 bits, but a long long is generally 64 bits. So it just means you can represent bigger numbers than this. All right. So if we actually want to start representing things, we might need more sophisticated types, and that's why we have string. So in the CS50 library, that file called cs50.h, we've actually declared a data type, so to speak, called string, but string does not actually exist. This is, again, one of these layers we're going to peel back in a week or two and throw it away, and actually look underneath the hood at what a string actually is, and how it's represented. We're also going to look at Boolean values. So what was a bool in the context of Scratch? It's true or false. So it's just a value that's true or false, on or off, 1 or 0, however you want to view the world. So in C, thanks to the CS50 library, which in turn includes another library underneath the hood, we have access to a data type that's called bool, which will literally allow us to assign the values true or false to things in a program. So let's go ahead here and write a little program that does something involving numbers instead. So let me go back to the CS50 Appliance, let me go ahead and create a new file here called-- let's just say something simple, like math.c. All right. And now go up to the top of my program, I'm going to do the usual-- #include , so that I can use printf, int main (void)-- we'll come back to, eventually, what int means here, what void means here, but for now, just know that you have to start programs like this. Now I'm going to go ahead and say something a little different-- printf("Give me a number: " );. Then I'm going to do int n = GetInt, because it turns out GetInt is another function in the CS50 library besides GetString. And now I'm going to do something stupid, like "thanks for the %d," for decimal integer, and then comma n, and then return 0. So again, return 0 has nothing to do with the number I'm asking the user for. Just signifies at the end that all, presumably, is well. So let me go down to my terminal window here. Let me type make math, enter. And something's wrong. Make math did not work. Here's the first of our error messages. Why? A little cryptic, but-- Yeah. So cs50.h. So again, especially early on, you'll write your first program for pset 1 in sections, in office hours, and frankly, it'll be overwhelming sometimes what these things are actually saying. But you'll realize very quickly they start to fall into buckets whereby this one means that you've left off one of the #includes at the top of the file. And Clang, the compiler, is informing you of this by saying, rather fancifully, implicit declaration of function GetInt is invalid. All right. So what does that mean? It just means you've implicitly declared GetInt in the sense that you haven't explicitly declared it. To explicitly declare int, you have to teach Clang that it exists. And the very simple solution for that is to teach it by including this other file, cs50.h, at the top of your file. Because literally, what #include does is it tells Clang pretty much to go find the file called cs50.h, copy, paste it automatically into the top of my program for me, and then convert the source code to zeros and ones. But that would obviously be very tedious if we humans had to go copying and pasting these big files all the time, so #include just does all that automatically without muddying my code with someone else's library. And a library is just another file containing functions and other things that someone else has written, that we are leveraging for our own sake. All right. Let's try again. Make math. Enter. Good. So that seems to have worked. So let me now run math; ./math. Enter gives me a number, 123. Thanks for the 123. Now let's try another corner case. A string is pretty generous, because a string can be anything. Can look like numbers, look like characters, look like words. But an int is an int. So now if I'm the difficult user, and it's saying "Give me a number," what if I try to do something like 0.1? Well, that's a number, and it's consistent with the grammar I used here, but underneath the hood, I'm of course using the function GetInt. So let's see what happens. Enter, retry. All right. Let me be difficult and just hit Enter again. Enter, Enter. So now it seems that GetInt is a little more powerful than GetString. We, the staff, implemented in such a way that if we notice you have not given us an int-- and an int is a decimal number containing zeros, ones, twos, threes, fours, fives, sixes, sevens, eights, or nines. And that's it. No decimal points, no characters, no punctuation. It seems that we have to cooperate. So let me try four, five, six, and that gets me through. So really, to be anal here, I should probably say "Give me an integer" in order to convey to the user exactly what I intend. Now let's think about underneath the hood. We're not going to look at how cs50.h is implemented today, that library. But if it keeps saying retry, retry, retry, what programming construct am I presumably using underneath the hood to implement that? So just a loop, right? One of the simplest ideas that we saw on Scratch. The Forever construct, the Repeat construct. Presumably, in this program, underneath the hood, even though it's written in C and not scratch, it's doing something called equivalent to forever if the user has not typed in an integer, say retry, retry, retry, retry, so then finally when we do get an integer, then you break out of that loop. So what other functions can we use here in CS50's library? Well, kind of the obvious ones, at least based on the data types that we now know exist. We implemented GetString, GetInt, but throughout the first weeks of the term, you can also use GetFloat and GetDouble and GetLongLong in order to get precisely the data types that you want. Because the key detail here is that unlike some languages, like Python and Ruby, where you don't necessarily have to declare the data type of a variable-- you don't have to tell the computer what kind of stuff you're going to put into the variable-- in C, you have to be ever so precise. So if you want a variable called n, a chunk of storage that in this case happens to be 32 bits by convention, you have to tell the computer that these bits are going to store a number-- not a character, not a string, not a float. And this addresses the issue we effectively ran into last week. If we're using zeros and ones numbers to represent not just numbers but As and Bs and Cs, how in the world is a computer going to know that this pattern of bits actually represents the number 65, as opposed to representing the letter A, which coincidentally, according to ASCII, recall, was equivalent to 65? So these data types provide context to the computer, so that it knows if these bits should be interpreted as an int or as a string. Any questions, then, on this? Yeah? DAVID J. MALAN: Good question. If we take out stdio.h, we save the file-- let me go down to the terminal window and run make math, zoom in and enter-- now I get a different error, because I'm implicitly declaring what function now? Printf. So now I've created a new problem, whose solution is essentially the same. I need to put that back. AUDIENCE: [INAUDIBLE] DAVID J. MALAN: Oh. So if I take out-- Okay, yeah. So if I remove the standard I/O library's inclusion up here, and then you're saying if I get rid of printf, get rid of printf? Yes. This should work, because I'm no longer using any-- whoops. Did I just lie? Oh, okay. This won't work because of a new error we just introduced. And this one is a little more self-explanatory. What's the problem? Unused variable n. So this error is the result of our having configured the appliance to be particularly pedantic, to really yell at you for every possible mistake, even if it's kind of a non-fatal mistake like this--is it really such a big deal that I allocated an int, put a number in it, and then just did nothing with it? So functionally, no. That's not going to break the program. It's just kind of stupid, right? There is no value to having asked for that number, stored it in a variable, if you're never going to do anything with it, whether print it or save it. So in this case, Clang is acknowledging as much, and it's saying unused variable n. So we can fix this if we really want. But again, this is not good programming now. So I could just do this-- go down here, let me clear the screen, make math. That works. Now I can run my math program, takes input-- well, that was bad. Takes input, and that is all it does, in this case. So actually, let's try one other corner case that we didn't think of earlier. In this case--here, let's go back to the one that's a little more user-friendly. Let me go back here and run make math again. Whoops, what did I do wrong? Got to roll back further. Okay. Now we're back in the original state, where all is hopefully well. And now if I run math, 123 seems to work. But this is not really an effective proof, to just say okay, that works. 789, that works. Time to submit. Because there's other corner cases here. A string did not really give us much trouble by typing in a whole lot of characters. But what if I type in this? Hitting the number 1 a whole lot, whole lot here-- all right, it's getting a little boring, so I'm going to stop here, and I'm going to hit Enter. What the hell just happened? So this can actually be explained. So did it take it as binary? A good thought, but no, it's not the fact that it took it as binary, because indeed, that was just kind of a coincidence. We can do this again. So there's no 2 in the binary system, that's probably enough anyway. Enter. So that wasn't the problem. What else? Exactly. So think back to what an int actually is. It's 32 bits which collectively are interpreted as a number. If you have 32 bits, that means each of the bits can be a 0 or a 1, 0 or a 1. So that means there's two possibilities for this bit, two possibilities for this, two possibilities for this bit-- so that's 2 times 2 times-- so that's 2 to the 32 power is the total number of permutations of zeros and ones if you have 32 placeholders, zeros or ones, in front of you. So if I have 2 to the 32, mathematically, that's what? So it's a lot. It's 4 billion, give or take. And 4 billion does not seem to be what was printed out here. In fact, this looks closer to 2 billion. But this isn't a coincidence. The fact that the computer has misinterpreted my huge number, my huge sequence of ones and then my huge sequence of twos, as roughly 2 billion, is explained how? There's a cap on the int. There's a certainly a maximum value that you can represent. But it's usually 4 billion, right? If 2 to the 32 is roughly 4 billion, that seems like that's the biggest number. So not a remainder, but a good thought. Negative numbers. So if you have 4 billion possible things you can represent with these various permutations of 32 0s and 1s, well, it stands to reason that we humans might want to represent not just positive integers but negative integers. And indeed, that's the assumption that C makes. So with 32 bits, you can represent roughly negative 2 billion all the way up to positive 2 billion. And so in this case, what we're really seeing is just the fringe of the capacity of our integer, and we have, so to speak, overflowed an integer. We've tried to cram more bits into it than can actually fit. So the end result is we essentially have all 1 bits. We've flipped all of our bits on, we've tried to represent the biggest number possible, but it's clearly not nearly big enough to represent the two things I've just typed in. Yeah? AUDIENCE: [INAUDIBLE] DAVID J. MALAN: Good question. Why can't we just represent that negative sign as just a character? So we absolutely could, and we could then save an additional bit. But you're still going to have to represent that dash, and that's going to cost you at least something, presumably a bit. So yes, we could have 32 bits used for our number, but now we need another bit used for our dash symbol, the minus sign. So now we have 33 bit values, which we could do, but it's just not the way it's done. We made a judgment call years ago, 32 bits is sort of the unit of measure here. So we're going to use one of those bits effectively to represent negativity, and 31 bits to represent the number. Other questions? All right. That's a lot. Why don't we go ahead and take our five-minute break here? All right. So again, not to overemphasize the mathematical applications of programming, let's just pluck off this one example before we move into other constructs, just because it will illustrate a few common stumbling points on some of the basics when it comes to writing programs. In this case, doing arithmetic expressions that have some interesting relevance to the syntax. So this is just a formula with which we can convert temperatures from Fahrenheit to Celsius. If you don't recall, this is just the formula. So if we plug in Fahrenheit value of 32 degrees, which is freezing, that's going to be 32 minus 32 is 0, and indeed, 0 in Celsius is also freezing. So quick sanity check there-- that's the familiar formula. Let me go over to the appliance, though, and start writing a program called, like, f2c; "Fahrenheit to Celsius dot c". And up at the top here, I'm going start off with #include stdio.h, and I'm going to do int main (void), and again, we'll come back in the future as to what int means there and what void means there. And now let me go ahead and implement a program that essentially does this conversion for us. So printf, let's say, temperature in Fahrenheit. And then let me go ahead and get the value from the user. What kind of value should I get from the user if I want them to give me a temperature in Fahrenheit? Yeah? What would you propose? Yeah. So float feels pretty reasonable. We have, again, just a few options that we've seen thus far. We have things like char, double, float, int, long long, bool, string. So of these, float feels pretty reasonable. We could use a double, right, because if we really want to represent a human's temperature-- 98.60000-- we could use 64 bits to do that, but it feels like overkill for the temperature. So let's just go with float. Now I need a variable. Just to keep things simple, I'm going to call it f, but I could just as correctly call it temperature, but either is fine. So float f = GetFloat. As soon as I now have decided to use GetFloat, though, I need to make one correction. Yeah. So we need to #include , otherwise the compiler is going to yell at us. Now that I have a float, let me go ahead and do the conversion. So first, let me also get into the habit here of commenting my code. So again, a comment is just a notation to the human that's not part of the program per se, but it one, helps you understand what you did the next morning, or the next month, it helps your teaching fellow understand what you did or what you intended to do, so it's generally very good practice. Every few lines of code, write a comment to yourself or your colleague. So here, I'm going to say, "Ask user for temperature." Doesn't have to be a complete sentence, just a short phrase. But the idea behind commenting in C is that each of your comments should empower you-- or, say, a TF or a colleague-- to skim your program and know exactly what it does, by not so much reading the code, but by reading the comments, which should be succinct and clear. All right, so now let me go ahead and say, "Convert Fahrenheit to Celsius." So I'm going to go ahead and do, let's say, float c. We'll keep Celsius as a floating point value. And let me take a stab at this. The formula is, again, up here. As 5/9 times F minus 32. So let's do this. So 5 divided by 9, minus-- whoops, I messed it up already. Times. So 5/9 times F minus 32. So F minus 32, semicolon. And now, down here, I'm going to go ahead and say, print result. And this part's easy. Printf. How do I go about printing this? Well, I could say "That number in Celsius is %f\n", just for some aesthetics. And then what value do I want to plug in here as printf's second argument? Okay. So just c. So we'll start with this and then just return 0. Again, it has nothing to do with the math. It just means all is well. Now, is this correct, this program? All right. So I've made some mistakes. Even if you have no idea what programming is, you can sort of infer back to grade school what the mistakes here might be. What's one of the first? AUDIENCE: [INAUDIBLE] DAVID J. MALAN: Yeah. So we're missing parentheses. It was deliberate that I did parentheses in the keynote slide here, because there's actually this notion of order of operations, or precedence, whereby certain operations-- multiplication-- have higher binding, have higher precedence, than things like addition or subtraction. So we've done this for years just to make clear exactly what mathematical operation should be done first. So I should probably mimic exactly this. Otherwise, the computer is presumably going to try to do something like divide 5 by 9, then multiply F, then subtract 32 from the whole thing. Which is not, in fact, what we want to do. So let's parenthesize. Let's add my parentheses here, parentheses here. Let's put this over here. Here, I just noticed another mistake I made along the way. Yeah? AUDIENCE: [INAUDIBLE] DAVID J. MALAN: Ah. Good. So we actually have the same integer division issue from before. I correct that, let's see what the symptom is. But we're going to have to correct one other mistake here. Yeah? AUDIENCE: [INAUDIBLE] DAVID J. MALAN: Yes. So, stupid mistake I made, but incredibly important. The computer is not going to just turn a blind eye and let me use capital F, when I actually declared the variable as a lowercase f here, in line 8. So I need to correct in line 11 my capitalization, which a moment ago was a capital F by mistake. What about here? Should this be lowercase as well? It should be, but that's a coincidence. That %f has nothing to do with the variable. So just to be super clear here, let me go ahead and rename this, briefly, "temperature." Let me rename this "temperature." Let me not rename this. Because, again, %f globally means, "floating point value." Has nothing to do with my variable. But "temperature" all over the place is just a little wordy, so I'm going to go back to my lowercase "f"s. Now, let me go ahead down to my window here. Make f2c-- which was, again, the arbitrary name I gave to this file. Seems to have compiled. Let me run f2c. Enter. Temperature in Fahrenheit--let's do an easy one. 32. OK, correct. But, if I now do 212 for boiling-- damn. All right. So, clearly not correct, if your TF tries at least two values. So what's the problem here? Well, you already put your finger on what the issue is. But why is that the case? Up here, when I'm doing the math of 5 divided by 9. So conceptually, that's perfectly correct. Totally consistent with the formula. But computers only do precisely what you tell them to do. And what we're effectively telling the computer here is divide the integer 5 by the integer 9 and give me the result. The problem is, though, when you do division using data types, the output is the same data type as the inputs. And so if the two inputs are both ints, the output is going to be an int. And so 5 divided by 9 is point something. But what's the closest integer to point something? So, it's actually 0. So as we discussed on Monday, everything after the decimal point gets truncated. It just gets thrown away. So this is a complete mistake, because I might as well just multiply everything by 0 here. Now, I can fix this in a couple of ways. I could do this. 5.0 divided by 9.0. Technically, I don't even need to do that. It does suffice to just make one of the numbers a float-- or double-- by putting the decimal point here. Because what happens now is when you divide an integer by a float, or a double, the computer's going to realize oh, one of those is more precise. Let me err on the side of giving you more precision than you intended. So it will convert the result-- it will return the result as a floating point value as well. So that would work. This would work. And there's one other mechanism that we'll see in greater detail next week. You can actually, as the programmer, tell the computer to actually treat one data type as though it were another. So I could actually do this. In parentheses, I can say something like (float), open paren, close paren. And this is what's called "casting." Again, more on this next week. But this is just the programmatic way of telling the computer, yeah I know 9 is an integer or a long. I know it's not a floating point value. But treat it as such anyway. So to cast a data type means to convert from one to the other. Frankly, this is just a little ugly, so I would propose we go back to the original suggestion of just converting these things to floating point values manually. Because now it's just super clear what's going on, and it's not all that distracting. So let's now go back into my terminal window. Make f2c. Let me go ahead and run this. And, as an aside, you get bored typing these commands again and again, realize that computers, like Linux here, tend to be pretty smart. And if I hit Up, we can go through my entire history of commands, Up and Down. So in this case here, I can just go Up to run make f2c. I'm being yelled at, because I just did that a second ago. It's already up to date. So now I can run f2c again. Let's try 32 Fahrenheit. Now let's try 212 Fahrenheit. Phew. Seems to work. Now, this is good, but it feels a little arbitrary that I'm showing six numbers after the decimal points. Right? If you're the weather person on TV, you're kind of a doofus if you're reading the temperature to this degree of precision. So let's simplify this. So let's actually go up here, to my printf. And yeah, I want to float. But I want to now specify the precision. And I'm going to be a little succinct. I'm going to say, give me one point after the decimal place. So rather than say %f, I'm going to say %.1f. And this just means give me one position after the decimal point. All right. Let's try this again. Let me re-run it after compiling. And now I type in 32, and I get back a more succinct value. And I can type in, now, 212, and get back a more succinct value as well. And there's other things you can do with printf. You can actually specify how wide the number should be. If you want to have padding on it, so you can right-align or left-align all of your numbers or try to center things. So realize there are little tricks you can do there. But they just boil down to format codes, like we have there. So in terms of this issue of precedence. This is a very boring table to go through methodically. But realize that the authors of C have come up with the rules that specify which operators have higher precedence, more binding power, than others. So whereas in grade school, we generally knew that it was multiplication and division, then addition and subtraction, then some other stuff. In a world of programming, there's a much longer list of things. And this is not something worth memorizing now. You'll get acclimated to it before long. But just like in grade school, parentheses generally solve the issues of precedence, by making super clear to the computer and human alike what is intended. So consider this just a little cheat sheet there. But most of those details we won't get to for some time. All right. Now, let's build up and move away from these silly little mathematical examples. Still use the same fundamentals, but start expressing ourselves a little more like Scratch. So in Scratch, we had these Boolean expressions. And in English, a Boolean expression is what? True or false. It's something that evaluates to true or false. 1 or 0. On or off. Whatever you want to call it. Now in Scratch, the puzzle pieces looked like this. And that's the combination, on the bottom there, of three puzzle pieces. One conjunction-- something that has blank and blank. And then two Boolean expressions inside of it. So you can nest Boolean expressions to get more complicated Boolean expressions. For instance, if it is Saturday, and it is nice weather, then go outside. Or something arbitrary like that. So you can join Boolean expressions to come up with a larger truth value, whose answer is based on the smaller ones. Now, in C, thankfully, this mapping is actually pretty simple. Parentheses help make things clear here. && is what means "and." So that's how we're going to convert those blocks from Scratch to C. And for the conditions we saw in Scratch, on the left hand side there, I can stack them similarly in C. If x is less than y, then do this. Else if x is greater than y, then do this. Else logically they must be equal, so say that they are equal. So we can now start to build these things up. So let's do an example. Let me open up a file that's on the course's website that I wrote in advance. That is called nonswitch.c. And we'll see why in just a moment. So in this file--nonswitch.c-- first realize that there's a whole bunch of comments at the top. That's just explaining the name of the file, what it does, and so forth. And it apparently demonstrates the use of Boolean AND-ing-- conjoining two expressions. So let's see how this program works. I include my two files, cs50.h and stdio.h. If I scroll down, now, to the program, it's a little longer than we've written before, but pretty readable. So I first print to the user, on line 18, "Give me an integer between 1 and 10." So that's right there. Now I get the integer. But realize that GetInt--pretty simple. It's just going to get an int. It's going to ensure that it does get an int and not a string or a float. But it's not going to do any kind of boundary checking. It's not going to filter the numbers to be between a certain range. So we have to implement that ourselves. So just like in Scratch, where I could do a conjunction of two expressions, I can do that in C as follows. If n is greater than or equal to 1, and n is less than and or equal to 3, I am going to very arbitrarily decree that number to be a small number. Just for the sake of a statement. Else if n is between 4 and 6, print "You picked a medium number." Else if n is between 7 and 10, print "You picked a big number." Else print "You pick an invalid number." Because logically, that follows if we've exhausted our range. So realize this is not quite how we write greater than or equal to in a math class. Right? You usually draw it like this, with the line under it. But there is no such key on my keyboard. So the symbol in C for expressing greater than or equal to is two characters, and the symbol for less than or equal to is two characters as well. All right. So if I run this program, you can probably guess what it's going to do. If I go ahead and make nonswitch, Enter. And then run nonswitch. Give me a number between 1 and 10. I'm going to give it 11. I picked an invalid number. Let me try the number 3. I picked a small number. So fairly straightforward there. What if I want to change the behavior of this program and do something a little different instead? Let me go ahead and say this. Let me get rid of all this. And let me say if (n == 42). And then I'm going to go ahead and say print "You picked the right answer." Else we're going to go ahead and say, printf("You picked the wrong answer."); Okay. Just because. Now, a few points we can make here. One, I did not type the symbol that you would think is the most reasonable. When I want to check equality, turns out you don't use the equal sign. You instead use the equal equal sign. And why might that be, just intuitively? Yeah. AUDIENCE: [INAUDIBLE] DAVID J. MALAN: Correct. The equal sign is already used for assignment. Someone didn't really think this through. And so now, when it comes to equality testing, we have to be more explicit, and say equals equals. A very common mistake is to do this. And, if in office hours or sometime next week or in the next two weeks you do something like this and then struggle with it for 10, 20 minutes trying to figure out what the damn bug is, realize that you are one of those people who made this mistake. So, super easy to make. But the goal now is to ward off this mistake. This could evaluate, because what is this really saying? If n gets 42. So the verb people use, verbally, to express the notion of assignment is "gets." So if n gets 42. So that means assign 42 to n. Now I have a Boolean expression in parentheses, inside of this condition, the value of which is 42. Right? Because if you evaluate it from the inside out, the total answer, now, is 42. So if I asked you the question, "if (42)," what is that really saying? Well, Boolean expressions can only be true or false. 1 or 0. On or off. So we seem to have a corner case here, whereby all of a sudden, I'm saying "if (42)". That is not a Boolean value. So what computers do, though, is it essentially equates anything that's not 0 is interpreted to be true. 1. On. They're all functionally equivalent. Only the value 0, or the keyword false, as we'll eventually see, is actually false. So "if (42)" would actually be true, because it is non-zero. So to be more precise here, a Boolean value is really not so much true or false, but for this case, if is 0 or non-zero. So false or not false. And that allows us to encompass all the more possibilities in the parenthetical expression. So we need to, ever so carefully, say this-- if (n == 42). Simply because we need to specify a test of equality, not an assignment of a value. What else is worth noting here? These curly braces are actually not necessary. I've been doing them just to be nit-picky here. But when you have a condition that only has one line of code, as a convenience, programmers do not need to use the curly braces. It suffices to just indent, for aesthetic reasons, and then write your line of code. Only when you want to write two lines of code--for instance, else printf("Bye!"). If you want to do that, this is broken. You can indent all you want, but the fact that you have typed two lines of code without using curly braces means that this program would not run correctly or might not even compile correctly. So for now, to be honest, I think the best habit is just use the curly braces, and you'll find that they make super clear what's going on. Also, as an aside--especially if you're among those who use the recommended books or resources online-- realize that there's this notion of style in programming. And some people actually prefer to put the curly brace over here on a line. Some people prefer to do ridiculous things, like put them here. There's no wrong answer when it comes to style, but this is wrong. But some people do it. [LAUGHTER] DAVID J. MALAN: So I mention this now, simply because as you read up on things in books or online, you're going to get different messages from different teachers and different authors. And just realize that, functionally, they're generally equivalent, but be consistent. So in this case, we'll standardize on the curly braces lining up here on the left. All right. So let's go ahead now and run this, and see what happens with this program. Make nonswitch. Then run nonswitch. Give me an integer between 0 and-- so that's not relevant anymore, but I'm just going to arbitrarily say 42. And I picked the right answer. Well now, let's actually take this in a different direction. It turns out there's some other syntax we can use in a program. Here's a new piece of syntax that is functionally the same, but just introduces another way of expressing ourselves. So this is what's called a "switch statement." And a switch statement operates as follows. It takes, in parentheses, a value that you want to "switch" on. You want to behave differently based on its value. So this means switch on the value of n. And what does this mean? Well, if n is 1 or 2 or 3, go ahead and print out "You picked a big number" and then break. The reason for the break is that the way C works is as soon as it finds a case that matches, it starts executing all of the code below it. So if I have one line of code, as I do here on line 27, it gets executed. If I add another line here, it gets executed. Another line here, it gets executed. The program only stops executing what's below the applicable case statement when I explicitly say "break." So wrong. Right, in this case, as a result. Case 4 or 5 or 6, similarly, is going to print out a message. In this case, medium number. Break. Case 7, 8, 9, 10, it's going to print out "You picked a big number." Break. And then there's literally a keyword called "default" that's effectively like the "else" construct. So new syntax, but intellectually, nothing at all new here. It's just like the Scratch. If, else if, else if, sort of block. So that's the switched version of this program. But notice that we did it with numbers here. Let me open up a second version, just to show something a little more concrete. So here we have grades instead. Turns out you can use switches not just on integers, but on characters. Not in all data types, but at least on characters. So here, we could do something like if the value of C that the user typed in, in line 19, by using the GetChar function, is capital A or lowercase a, let's interpret it as a grade, and say they picked an excellent grade. And down along the switch statement, do we have other cases for "B"s and "C"s, and so forth. But let's now round out one other thing. And again, kind of flying through some of these examples. But it's really so that we can apply them, now-- or really, just translate them now-- to C. So let me go ahead and do this. I'm going to open up a new file. And I'm going to do include . And then I'm going to do int main (void). Let me save this file as a loop.c. Just as an example. And I'm going to go ahead and do the following. I want to write a very tedious program. So 10. Let's do this. 9. All right. As soon as you start doing this in programming, you're probably doing something wrong. But we'll start there anyway. Oops. That's actually wrong. 7. 6. 5. 4. Nothing's going to happen when we get to 0. 3. 2. 1. Okay. 0. Delete. All right. So return 0. So this program's obviously going to do what it very tediously says it's going to do. It's going to print all of those values, from top to bottom. So let me do make loop. And then--whoops. Make loop. I was in the wrong directory. And now let me run loop. Enter. Woohoo. Very nice. Nice, long program. All right, but now let's do this better. Just like in Scratch, when you started using a looping construct, instead of just copying and pasting all of the puzzle pieces, let me introduce this thing. So in C, there are various looping constructs, one of which looks like this. A "for" loop has three things, separated by two semicolons. And then, inside of the body of the loop, so to speak-- the stuff inside of the curly braces-- we can do something again and again. So what I have here on the screen, this is literally just a comment. The // means here comes a comment. This is not code. This is just English description, to me, the human. So initializations, conditions, and updates. Well, let's see how this works. This allows me to rewrite this program as follows. For-- so here comes my loop-- int i-- here comes a variable called "i"-- gets initialized to 10. So there is my initialization. I want to do this loop so long as "i" is greater than or equal to 0. And on each iteration of this loop, I want to do i--. So we saw ++ on Monday. -- is the opposite. It decrements the value by 1. Inside of this loop, I want to actually do something. So I'm going to say something like printf. I don't want to say 10 now, because this obviously is just going to print the same value. What do I want to print instead, probably? Yeah. So "i." So %d, i. So I'm going to steal one of those ideas from earlier-- this substitution for format codes-- and then down here, at the bottom, I'll return 0, just for good measure. But now, I have a more succinct program. It's only a few lines, and not some 10 or 11 lines. Let me go to my prompt down here. Remake loop. Rerun loop. And it appears to be the same. Now, the program's no more interesting. But now I can type something like this. I can change this to 100. I can then recompile my program. And then I can re-run my program. And now it goes super-fast on today's computers. But there I have-- and actually, my scrollback buffer doesn't even go that far. There we go. So there we have all 100. But it's easy to make mistakes here. What's going to be the expected behavior if I accidentally do that? So it feels like infinite. So let's see if the computer behaves. So let me go ahead and make loop. And let me run loop. So let's come back to that in just a moment. We'll let that run. Because what should we count up to, minimally? Probably at least 2 billion, if we have that many bits, and we're using positive values. So let's jump back here. Besides these kinds of loops, we have what are called while loops. So, just like in Scratch, you had Forever blocks, and you had Repeat blocks. Similarly, in C, you just have other ways of expressing yourself. So you have this notion of a while loop that allows you to express yourself a little differently. And then you have something called a do-while loop, which operates slightly differently as well. And we'll tease these apart over time. But let's take a look at this last one here. If we go into-- still running. It's pretty infinite. So let me go into positive, and show how we can actually govern user input a little more effectively. It's a pretty short program. And here we have, in main, an int n declaration. So give me a variable called n. Now, I literally say "do." And then I've got open curly brace, close curly brace. And then notice, right after that, it says while n is less than 1. So notice that these lines-- 19 to 24-- compose collectively a do-while loop. And again, new syntax, not a new idea. It's just another way of looping, syntactically. So what does this do? Do the following while n is less than 1. So what do I want to do? I demand that you give me a positive integer. Then I actually try to get an integer from the user. But in terms of the order of operations here, because the while condition is down here, I'm then going to check, is n less than 1? So suppose that the user-- after being demanded in this way-- types in the value 0. This condition is going to be true or false? Well, it's actually going to be true. Because n is 0, and 0 is less than 1. So what does that imply? Do it again. Do it again. Do it again. Only once that condition evaluates to false. If I type in 42. Well no, 42 is not less than 1. Therefore this loop is done executing. And so at that point, the program will say, thanks for the 42, in this case. Now that you have this way of expressing yourself-- We should not wait for this to finish. It's going to take some time. To be continued next time, perhaps. But now, you have the ability to hopefully to understand a bit of geek humor. Apologies. This is not representative of humor in the computer science world, but it's cute. [LAUGHS] Let's end on that note. And we will see you on Monday. [APPLAUSE]