WEBVTT X-TIMESTAMP-MAP=LOCAL:00:00:00.000,MPEGTS:900000 00:00:00.000 --> 00:00:03.493 [INTRIGUING MUSIC] 00:01:01.377 --> 00:01:06.220 DAVID MALAN: All right, so this is CS50. 00:01:06.220 --> 00:01:09.310 And this is week 1, zero index, so to speak. 00:01:09.310 --> 00:01:12.890 And it's not every day that you can say that you've learned a new language, 00:01:12.890 --> 00:01:14.260 but today is that day. 00:01:14.260 --> 00:01:18.010 Today, we explore a more traditional and older language called C. 00:01:18.010 --> 00:01:22.450 And rest assured that even if what you're about to see-- no pun intended-- 00:01:22.450 --> 00:01:25.420 looks very cryptic, very unusual, particularly if you're 00:01:25.420 --> 00:01:28.967 among those less comfortable, cling to the ideas from last week, 00:01:28.967 --> 00:01:32.050 week zero, wherein we talked about some of those fundamentals of functions 00:01:32.050 --> 00:01:35.230 and loops and conditionals, all of which are coming back today. 00:01:35.230 --> 00:01:37.815 Indeed, whereas last week, and with problem set 0, 00:01:37.815 --> 00:01:39.940 we focused on learning how to program with Scratch, 00:01:39.940 --> 00:01:44.770 which, again, you might have played with as a younger student days back. 00:01:44.770 --> 00:01:46.870 Today, we focus on C instead. 00:01:46.870 --> 00:01:50.260 But along the way, we're going to focus, as always, frankly, 00:01:50.260 --> 00:01:51.850 on learning how to solve problems. 00:01:51.850 --> 00:01:54.820 But among the goals for today and really on an entire class like this 00:01:54.820 --> 00:01:58.610 is just to give you week after week all the more tools for your toolkit, 00:01:58.610 --> 00:02:00.680 so to speak, via which to do exactly that. 00:02:00.680 --> 00:02:03.860 So for instance today, we'll learn how to solve problems all the more 00:02:03.860 --> 00:02:06.420 so with functions, as per last week. 00:02:06.420 --> 00:02:07.910 We'll do the same with variables. 00:02:07.910 --> 00:02:10.789 We'll do the same with conditionals, with loops, and with more. 00:02:10.789 --> 00:02:13.190 But we'll also learn at the end of today's class 00:02:13.190 --> 00:02:14.970 really how not to solve problems. 00:02:14.970 --> 00:02:18.410 It turns out as powerful as Macs, PCs, cell phones are nowadays, 00:02:18.410 --> 00:02:21.890 there's actually certain things that they can't do very well 00:02:21.890 --> 00:02:24.650 and information they can't represent very well. 00:02:24.650 --> 00:02:28.760 And that actually leads to a lot of real-world problems, both past 00:02:28.760 --> 00:02:29.940 and surely future. 00:02:29.940 --> 00:02:33.540 So more on what we're not going to be able to do with programming before 00:02:33.540 --> 00:02:34.040 long. 00:02:34.040 --> 00:02:36.600 But beyond that, let's come back to this picture here. 00:02:36.600 --> 00:02:38.900 So this was the very first program that I wrote, 00:02:38.900 --> 00:02:40.880 that you wrote presumably in some form. 00:02:40.880 --> 00:02:43.400 And all it does is say "Hello, world." 00:02:43.400 --> 00:02:47.660 But as promised, today, this puzzle piece, or these puzzle pieces together, 00:02:47.660 --> 00:02:50.880 are going to very quickly start to look more like this. 00:02:50.880 --> 00:02:54.295 And I've deliberately color coded it in a way so that the text on the screen 00:02:54.295 --> 00:02:55.920 now kind of resembles the puzzle piece. 00:02:55.920 --> 00:02:59.540 So if I go back, notice that we had this, when green flag clicked puzzle 00:02:59.540 --> 00:03:02.780 piece, mostly in yellow with the green flag, that sort of kicks off 00:03:02.780 --> 00:03:04.550 the whole process once you actually click 00:03:04.550 --> 00:03:07.640 the button at top right of Scratch's user interface. 00:03:07.640 --> 00:03:11.990 And then there's the purple block which actually is the verb, the action, 00:03:11.990 --> 00:03:13.620 the function that does something. 00:03:13.620 --> 00:03:16.820 So if I bring us back over to what we're about to see today, 00:03:16.820 --> 00:03:20.477 there's going to be some boilerplate, so to speak, some orange text here 00:03:20.477 --> 00:03:23.060 on the screen that for now you just type and take for granted, 00:03:23.060 --> 00:03:25.430 like you need to write your code like that. 00:03:25.430 --> 00:03:27.435 But more interesting is going to be the purple. 00:03:27.435 --> 00:03:29.810 And we're going to see today that the function previously 00:03:29.810 --> 00:03:34.430 called "say" in Scratch is now called "printf" in this language called C. 00:03:34.430 --> 00:03:37.520 But in white here, you'll see similar text to our white oval 00:03:37.520 --> 00:03:40.550 last week, whereby that's where user input, like your input 00:03:40.550 --> 00:03:42.277 as the programmer, can actually go. 00:03:42.277 --> 00:03:43.610 So there's a lot of distraction. 00:03:43.610 --> 00:03:44.930 And honestly, it's these kinds of things that 00:03:44.930 --> 00:03:47.180 tend to distract and get frustrating early on when 00:03:47.180 --> 00:03:48.780 learning to code for the first time. 00:03:48.780 --> 00:03:52.170 But the ideas, most importantly, are going to be the same. 00:03:52.170 --> 00:03:54.060 So how are we going to go about using this. 00:03:54.060 --> 00:03:55.910 Well, it turns out, like last week, you're 00:03:55.910 --> 00:03:58.190 going to start writing something called source code. 00:03:58.190 --> 00:04:01.280 So code as we know it, quote, unquote, is more technically called 00:04:01.280 --> 00:04:02.060 "source code." 00:04:02.060 --> 00:04:04.460 That's what you and I as humans actually write. 00:04:04.460 --> 00:04:07.350 And indeed it might look a little something like we just saw. 00:04:07.350 --> 00:04:11.090 But unfortunately, computers only speak this, binary-- 00:04:11.090 --> 00:04:15.660 zeros and ones-- more properly known as machine code, in other words, 00:04:15.660 --> 00:04:19.550 those same patterns of zeros and ones last week, someone guessed, 00:04:19.550 --> 00:04:23.090 print out "hello, world" on the screen because one of those patterns 00:04:23.090 --> 00:04:27.570 is an H. Another pattern is an E, an L, and L, and an O, and so forth. 00:04:27.570 --> 00:04:31.880 And then other patterns of those zeros and ones are commands or instructions 00:04:31.880 --> 00:04:37.280 to the computer that literally say, show H-E-L-L-O comma "world" on the screen. 00:04:37.280 --> 00:04:40.520 But machine code would not be nearly as much fun 00:04:40.520 --> 00:04:43.070 to write if it were indeed in zeros and ones. 00:04:43.070 --> 00:04:45.080 Entirely for us, ideally, you and I are going 00:04:45.080 --> 00:04:49.100 to write source code, which conceptually is sort of up here, high level. 00:04:49.100 --> 00:04:52.790 But we're going to need a program to convert it to the lower-level machine 00:04:52.790 --> 00:04:56.240 code so that we don't spend our lives actually having to read and write 00:04:56.240 --> 00:04:59.000 zeros and ones, which back in the day, kind of in yesteryear, 00:04:59.000 --> 00:05:01.160 you kind of did with things called punch cards 00:05:01.160 --> 00:05:03.050 and holes on physical sheets of paper. 00:05:03.050 --> 00:05:06.440 We're beyond that because after years and years of innovation, 00:05:06.440 --> 00:05:09.462 folks have given us higher-level languages instead. 00:05:09.462 --> 00:05:11.420 So here's what we're going to need to do today. 00:05:11.420 --> 00:05:14.900 If at the end of the day you and I are writing source code 00:05:14.900 --> 00:05:18.260 but we want machine code as output, we need something 00:05:18.260 --> 00:05:21.900 in the middle that's going to convert that source code to machine code. 00:05:21.900 --> 00:05:23.900 You and I are not going to have to learn or talk 00:05:23.900 --> 00:05:25.672 about really any more zeros and ones. 00:05:25.672 --> 00:05:28.880 And the type of program we're going to start using today and introduce you to 00:05:28.880 --> 00:05:30.080 is called a compiler. 00:05:30.080 --> 00:05:34.130 So a compiler is a program that translates one language to another. 00:05:34.130 --> 00:05:35.720 And it can be any two languages. 00:05:35.720 --> 00:05:39.770 But today, and often, we'll talk about it in the context of source code 00:05:39.770 --> 00:05:40.890 to machine code. 00:05:40.890 --> 00:05:45.325 So this is Apple or Google or Microsoft or folks from other companies 00:05:45.325 --> 00:05:48.200 or even volunteers who have written software that do this conversion. 00:05:48.200 --> 00:05:51.230 You and I are essentially going to download a free compiler 00:05:51.230 --> 00:05:55.040 and use it to actually get our computer to understand the source 00:05:55.040 --> 00:05:58.595 code that you and I write in these higher-level languages. 00:05:58.595 --> 00:05:59.970 So where are we going to do that? 00:05:59.970 --> 00:06:01.845 Well, we could actually give you instructions 00:06:01.845 --> 00:06:05.340 and you could download the appropriate free open-source software 00:06:05.340 --> 00:06:06.607 onto your own Mac or PC. 00:06:06.607 --> 00:06:09.690 The reality is that creates so many technical support headaches because we 00:06:09.690 --> 00:06:11.280 all have slightly different computers. 00:06:11.280 --> 00:06:14.640 We all have slightly different versions of Windows or macOS or Linux 00:06:14.640 --> 00:06:15.840 or other operating systems. 00:06:15.840 --> 00:06:19.260 And that, too, tends to be a distraction at the beginning of any course 00:06:19.260 --> 00:06:20.730 like this or learning programming. 00:06:20.730 --> 00:06:22.680 So we're going to use the cloud instead. 00:06:22.680 --> 00:06:28.530 We're going to use a URL of the form https://cs50.dev. 00:06:28.530 --> 00:06:32.040 And what this will do for you is put inside of your browser window 00:06:32.040 --> 00:06:36.390 absolutely everything you need for the course, but it's going to use software, 00:06:36.390 --> 00:06:39.810 software called Visual Studio code, otherwise known as VS Code, 00:06:39.810 --> 00:06:41.730 that's actually free itself. 00:06:41.730 --> 00:06:43.200 It's very popular in industry. 00:06:43.200 --> 00:06:45.420 It's what "real" programmers use every day. 00:06:45.420 --> 00:06:47.560 But it's a cloud-based version thereof. 00:06:47.560 --> 00:06:50.250 And so everything will just work for you out of the box. 00:06:50.250 --> 00:06:52.530 But toward the end of CS50, the goal is going 00:06:52.530 --> 00:06:55.200 to be to get you off of CS50's infrastructure, 00:06:55.200 --> 00:06:59.040 to get you to download this freely available software onto your own Mac 00:06:59.040 --> 00:07:02.170 or PC if you so choose so that those training wheels, so to speak, 00:07:02.170 --> 00:07:02.840 can come off. 00:07:02.840 --> 00:07:05.170 And then even if you never take another class again, 00:07:05.170 --> 00:07:07.780 you don't need any class's infrastructure moving forward. 00:07:07.780 --> 00:07:10.960 You'll have everything you want and need on your own Mac or PC. 00:07:10.960 --> 00:07:13.250 But for now, it'll save us a bit of time. 00:07:13.250 --> 00:07:16.750 So in just a bit, I'm going to go to that URL myself on my computer. 00:07:16.750 --> 00:07:19.552 And I and you will see a user interface that 00:07:19.552 --> 00:07:21.010 looks a little something like this. 00:07:21.010 --> 00:07:23.170 The colors might be different based on your settings. 00:07:23.170 --> 00:07:24.800 Fonts might be different, and so forth. 00:07:24.800 --> 00:07:27.590 But in general, it consists of a few different regions. 00:07:27.590 --> 00:07:31.750 So over here at the top is where we are going to start writing code today. 00:07:31.750 --> 00:07:34.930 So it's a tabbed interface like any number of programs nowadays. 00:07:34.930 --> 00:07:38.058 And this is that same C code we saw a moment ago. 00:07:38.058 --> 00:07:40.600 So this is where, in a moment, I'm going to start to type it. 00:07:40.600 --> 00:07:43.330 Over here at the bottom is what we're going to call 00:07:43.330 --> 00:07:45.438 a terminal window, or a console. 00:07:45.438 --> 00:07:47.980 And the terminal window is where we're going to type commands 00:07:47.980 --> 00:07:50.500 for compiling our code, for running our code. 00:07:50.500 --> 00:07:54.860 And we'll see today a contrast between a graphical-user interface, 00:07:54.860 --> 00:07:57.370 or GUI, which has menus and icons and things 00:07:57.370 --> 00:08:01.270 you click and are very familiar with, versus a command-line interface, 00:08:01.270 --> 00:08:02.200 or CLI. 00:08:02.200 --> 00:08:04.270 And so we're using both of these together. 00:08:04.270 --> 00:08:08.007 And command-line interface just means, down here, you only use your keyboard. 00:08:08.007 --> 00:08:10.340 You can click, click, click if you want with your mouse. 00:08:10.340 --> 00:08:13.423 It's not going to generally do much because a command-line interface takes 00:08:13.423 --> 00:08:14.540 commands at the keyboard. 00:08:14.540 --> 00:08:16.840 So in a weird sense, it's going to feel like taking 00:08:16.840 --> 00:08:20.620 a step backwards from the Macs, the PCs, the iPhones, and Android phones we all 00:08:20.620 --> 00:08:22.660 have, which are very graphical. 00:08:22.660 --> 00:08:26.120 But it turns out, once you become a "computer" person or a programmer, 00:08:26.120 --> 00:08:29.680 you can be a lot more productive, a lot more efficient, I dare say, 00:08:29.680 --> 00:08:31.990 by learning to harness the command-line interface 00:08:31.990 --> 00:08:35.169 and using both types of interfaces for what each is good at. 00:08:35.169 --> 00:08:36.730 So more on that in just a bit. 00:08:36.730 --> 00:08:41.289 Over here at left, you're going to see soon a folder interface like Mac OS 00:08:41.289 --> 00:08:45.010 or Windows where any of the files or folders we create in CS50 00:08:45.010 --> 00:08:46.310 are going to end up, as well. 00:08:46.310 --> 00:08:47.990 So it gives you the best of both worlds. 00:08:47.990 --> 00:08:51.310 You can point and click on the left, or you can type commands at the bottom, 00:08:51.310 --> 00:08:52.420 as we'll soon see. 00:08:52.420 --> 00:08:54.670 And then along here is the so-called activity bar, 00:08:54.670 --> 00:08:58.500 where there's just VS Code-specific features but also CS50-specific 00:08:58.500 --> 00:08:59.000 features. 00:08:59.000 --> 00:09:01.420 And if you're in your own version of CS50.dev, 00:09:01.420 --> 00:09:03.580 you click through in the dot dot dot menu 00:09:03.580 --> 00:09:05.320 or zoom out so you can see everything. 00:09:05.320 --> 00:09:08.530 You'll see CS50's own rubber duck, virtually speaking, 00:09:08.530 --> 00:09:10.870 that will be there throughout the course to answer 00:09:10.870 --> 00:09:13.460 any and all of your questions, as well. 00:09:13.460 --> 00:09:15.190 So more on that soon, too. 00:09:15.190 --> 00:09:18.040 So here's the code that I propose that we write first, 00:09:18.040 --> 00:09:21.800 just like we wrote our very first Scratch program to say "hello, world." 00:09:21.800 --> 00:09:23.650 So let's go ahead and do exactly this. 00:09:23.650 --> 00:09:25.870 I'm going to switch over to this screen here, 00:09:25.870 --> 00:09:29.980 where I've already logged into CS50.dev on my computer. 00:09:29.980 --> 00:09:33.760 And just to keep the focus on the code, I've hidden the activity bar. 00:09:33.760 --> 00:09:36.140 I've hidden the File Explorer, so to speak. 00:09:36.140 --> 00:09:39.740 So you're seeing here the area where all of my tabs are about to go 00:09:39.740 --> 00:09:42.490 and the terminal window, where all of my commands are going to go. 00:09:42.490 --> 00:09:44.710 But I've just simplified the UI to keep our focus 00:09:44.710 --> 00:09:46.910 on the interesting parts for now. 00:09:46.910 --> 00:09:53.140 So how do I go about actually writing and compiling and running some code? 00:09:53.140 --> 00:09:55.690 Well, the teaser is going to be these three steps. 00:09:55.690 --> 00:09:58.510 One of these is a command called, aptly, Code. 00:09:58.510 --> 00:10:02.260 And Code is just going to let me to open or create a new file, 00:10:02.260 --> 00:10:03.930 like a file called "hello.c." 00:10:03.930 --> 00:10:06.960 Make is going to be, for now, my compiler that 00:10:06.960 --> 00:10:11.280 allows me to make the program, that is convert source code into machine 00:10:11.280 --> 00:10:13.710 code, so from C to zeros and ones. 00:10:13.710 --> 00:10:15.570 And then weirdly, but we'll soon see why, 00:10:15.570 --> 00:10:19.810 ./hello is going to be the command to run my actual code, 00:10:19.810 --> 00:10:23.760 so the textual equivalent of like double-clicking on a Mac or a PC icon 00:10:23.760 --> 00:10:25.890 or tapping an icon on your phone. 00:10:25.890 --> 00:10:26.670 So that's it. 00:10:26.670 --> 00:10:30.810 These three commands are going to allow me to write, to compile, and to run 00:10:30.810 --> 00:10:32.070 code ultimately. 00:10:32.070 --> 00:10:33.340 So let's go ahead and do that. 00:10:33.340 --> 00:10:35.170 I'm back in my VS Code interface. 00:10:35.170 --> 00:10:39.000 I'm going to go ahead and run "code hello.c." 00:10:39.000 --> 00:10:40.900 And notice a couple of details here. 00:10:40.900 --> 00:10:44.790 So one, there's this weird dollar sign, which has nothing to do with currency, 00:10:44.790 --> 00:10:48.000 but it's just a common convention in the programming world 00:10:48.000 --> 00:10:50.520 to represent your prompt. 00:10:50.520 --> 00:10:53.190 So if a TF, if I ever say, go to your prompt, 00:10:53.190 --> 00:10:55.170 we really mean, go to your terminal window. 00:10:55.170 --> 00:10:56.100 Go to the dollar sign. 00:10:56.100 --> 00:10:58.285 And the dollar sign is where you type the command. 00:10:58.285 --> 00:11:01.160 Sometimes it's a different symbol, but a dollar sign is conventional. 00:11:01.160 --> 00:11:03.950 Now that I've typed "code" space "hello.c," 00:11:03.950 --> 00:11:05.450 I'm going to go ahead and hit Enter. 00:11:05.450 --> 00:11:07.158 And maybe not surprisingly, this gives me 00:11:07.158 --> 00:11:10.850 a brand new tab, a new file if you will, called "hello.c." 00:11:10.850 --> 00:11:15.290 And just like Word documents have their own file extension, like DOC, DOCX, 00:11:15.290 --> 00:11:22.050 and Excel files have .XLSX and PDFs have .PDF and GIFs have .GIF and so forth, 00:11:22.050 --> 00:11:26.780 so do C files have a file extension by convention that is .C. 00:11:26.780 --> 00:11:28.350 Now, a couple of minor points. 00:11:28.350 --> 00:11:30.710 Notice that, by convention, I'm almost always 00:11:30.710 --> 00:11:32.630 going to name my files in lowercase. 00:11:32.630 --> 00:11:36.440 By convention, I'm never going to use spaces in my file names. 00:11:36.440 --> 00:11:39.080 And my file extension, too, is going to be lowercase. 00:11:39.080 --> 00:11:41.840 Long story short, accidentally hitting the spacebar 00:11:41.840 --> 00:11:44.180 or using file names with spaces just tends 00:11:44.180 --> 00:11:47.130 to make life harder when you're in a command-line environment. 00:11:47.130 --> 00:11:49.530 So just beware silly, stupid things like that. 00:11:49.530 --> 00:11:51.410 So all lowercase, no spaces for now. 00:11:51.410 --> 00:11:54.380 So my cursor is literally blinking because the program 00:11:54.380 --> 00:11:55.825 wants me to write some code. 00:11:55.825 --> 00:11:57.200 I'm going to do this from memory. 00:11:57.200 --> 00:12:00.607 It'll take you presumably some time to acquire the same instincts. 00:12:00.607 --> 00:12:02.940 But I'm going to go ahead and type this first line here, 00:12:02.940 --> 00:12:06.390 pronounced "include standard io.h"-- 00:12:06.390 --> 00:12:07.590 more on that soon-- 00:12:07.590 --> 00:12:11.190 int main(void), with some parentheses thrown in. 00:12:11.190 --> 00:12:13.740 Notice what's about to happen here is a little interesting. 00:12:13.740 --> 00:12:15.750 In the code I want to type, I want what we'll 00:12:15.750 --> 00:12:18.210 call curly braces, the sort of squiggles that you 00:12:18.210 --> 00:12:20.460 don't use often in English, at least, but are there 00:12:20.460 --> 00:12:21.750 on your keyboard somewhere. 00:12:21.750 --> 00:12:25.350 But notice what VS Code does, and a lot of programming environments, 00:12:25.350 --> 00:12:27.480 is it finishes part of my thought. 00:12:27.480 --> 00:12:30.330 So I'm only going to type a left curly brace, 00:12:30.330 --> 00:12:32.950 but notice I actually get two of them. 00:12:32.950 --> 00:12:36.820 And if I hit Enter, notice that not only does it scooch one down a bit, 00:12:36.820 --> 00:12:40.350 it also indents my cursor because, just like with pseudocode last week, 00:12:40.350 --> 00:12:43.320 whenever you're doing something logically that should only 00:12:43.320 --> 00:12:45.930 happen if the thing above it happens, similarly 00:12:45.930 --> 00:12:48.900 is indentation going to be a thing when we actually write code. 00:12:48.900 --> 00:12:51.870 So VS Code and programs like it just try to save us 00:12:51.870 --> 00:12:54.450 keystrokes so I don't have to waste time hitting the spacebar 00:12:54.450 --> 00:12:57.900 or hitting Tab or wasting my human time like that. 00:12:57.900 --> 00:13:00.180 All right, so with that said, I'm going to go ahead 00:13:00.180 --> 00:13:02.430 and type the last of these lines, "printf," 00:13:02.430 --> 00:13:05.860 where the F is going to mean "formatted," and then a parentheses. 00:13:05.860 --> 00:13:07.290 And notice it gave me two. 00:13:07.290 --> 00:13:08.910 It gave me the second one for free. 00:13:08.910 --> 00:13:10.270 Sometimes it will get confused. 00:13:10.270 --> 00:13:13.560 And you can certainly override this, delete it, and start over. 00:13:13.560 --> 00:13:16.680 And now, unlike Scratch, in C, It turns out 00:13:16.680 --> 00:13:18.870 I'm going to need to use double quotes anytime 00:13:18.870 --> 00:13:22.860 I'm using an English word or phrase or any human language for that matter. 00:13:22.860 --> 00:13:25.050 "Hello" comma "world." 00:13:25.050 --> 00:13:29.310 And then at the very end of my line, much like English uses periods, 00:13:29.310 --> 00:13:32.160 I'm going to use a semicolon in C. 00:13:32.160 --> 00:13:35.340 So that's a lot of talking, but it's not much coding. 00:13:35.340 --> 00:13:37.290 It's technically six lines of code. 00:13:37.290 --> 00:13:40.600 But honestly, the only interesting one intellectually, as we'll soon see, 00:13:40.600 --> 00:13:41.670 is really line 5. 00:13:41.670 --> 00:13:44.580 Like, that is the equivalent of that, say, block. 00:13:44.580 --> 00:13:46.500 Now here's where I'll cross my fingers, hoping 00:13:46.500 --> 00:13:48.750 that I didn't make any typographical errors. 00:13:48.750 --> 00:13:50.700 It's going to automatically save for me. 00:13:50.700 --> 00:13:53.790 And I'm going to go back to my terminal window where now I'm 00:13:53.790 --> 00:13:56.670 going to do that second command, "make" space "hello." 00:13:56.670 --> 00:14:00.180 Common mistake-- you do not say "make hello.c," because you 00:14:00.180 --> 00:14:01.350 already made that file. 00:14:01.350 --> 00:14:04.950 You say "make hello," which is the name of the program that in this case I do 00:14:04.950 --> 00:14:06.600 want to create. 00:14:06.600 --> 00:14:07.830 And Make is smart. 00:14:07.830 --> 00:14:09.550 It's going to look in my folder. 00:14:09.550 --> 00:14:12.060 And if it sees a file called "hello.c," it's 00:14:12.060 --> 00:14:14.910 going to convert that source code to machine code 00:14:14.910 --> 00:14:18.510 and save the results in a simpler shorter-named file just called 00:14:18.510 --> 00:14:20.650 "hello," like an icon on your desktop. 00:14:20.650 --> 00:14:22.650 Now, hopefully nothing will happen. 00:14:22.650 --> 00:14:25.560 And that is a good thing, quite paradoxically. 00:14:25.560 --> 00:14:28.350 If you do anything wrong when programming, odds are you're 00:14:28.350 --> 00:14:31.738 going to see one or many more lines of error sort of yelling 00:14:31.738 --> 00:14:33.030 at you that you made a mistake. 00:14:33.030 --> 00:14:35.950 Seeing nothing happen is actually a good sign. 00:14:35.950 --> 00:14:40.470 So the last command, to run my code, recall our three steps here. 00:14:40.470 --> 00:14:46.260 We've written code to create the file, Make to compile the file from source 00:14:46.260 --> 00:14:47.140 code to machine code. 00:14:47.140 --> 00:14:49.320 So lastly is "./hello." 00:14:49.320 --> 00:14:53.130 So this now is the equivalent of my double-clicking on a Mac or PC 00:14:53.130 --> 00:14:55.650 or single tapping on a phone. 00:14:55.650 --> 00:14:57.360 Enter. 00:14:57.360 --> 00:14:58.893 [SIGHS] So close! 00:14:58.893 --> 00:15:00.060 All right, it's pretty good. 00:15:00.060 --> 00:15:02.970 I got the H-E-L-L-O comma space "world." 00:15:02.970 --> 00:15:05.770 But there's something a little stupid about my output. 00:15:05.770 --> 00:15:09.565 What might rub some of you aesthetically the wrong way? 00:15:09.565 --> 00:15:10.065 Yeah? 00:15:10.065 --> 00:15:11.460 STUDENT: The dollar sign. 00:15:11.460 --> 00:15:14.430 DAVID MALAN: Yeah, so the dollar sign looks like I was like, "hello, 00:15:14.430 --> 00:15:16.390 world" dollar sign in my output. 00:15:16.390 --> 00:15:21.100 But no, that's just kind of a remnant of my prompt starting with a dollar sign. 00:15:21.100 --> 00:15:23.767 And this is a little nitpicky, but this just doesn't feel right, 00:15:23.767 --> 00:15:24.558 doesn't look right. 00:15:24.558 --> 00:15:25.600 It's not quite correct. 00:15:25.600 --> 00:15:27.030 So how can I go about fixing this? 00:15:27.030 --> 00:15:29.100 Well, here's where, at least initially, it's 00:15:29.100 --> 00:15:33.660 going to take some introduction to just new syntax in C to fix this. 00:15:33.660 --> 00:15:35.850 The simplest instinct might be to do this. 00:15:35.850 --> 00:15:37.590 Well, let me just hit Enter like that. 00:15:37.590 --> 00:15:40.095 But this should soon, if not already, rub you 00:15:40.095 --> 00:15:41.970 the wrong way because in general, we're going 00:15:41.970 --> 00:15:44.550 to see that programming in C and in Python 00:15:44.550 --> 00:15:46.920 and other languages tends to be line-based. 00:15:46.920 --> 00:15:49.763 Like, you should really start and finish your thought on one line. 00:15:49.763 --> 00:15:51.930 So if you're in the habit of hitting Enter like this 00:15:51.930 --> 00:15:54.360 and finishing your thought on the next line, 00:15:54.360 --> 00:15:57.250 generally programming languages don't like that. 00:15:57.250 --> 00:16:00.030 So this is, in fact, not going to do what we expect. 00:16:00.030 --> 00:16:02.390 And just to show you as much, I'm going to do this. 00:16:02.390 --> 00:16:04.430 Let me go back to my terminal window here. 00:16:04.430 --> 00:16:07.670 I'm going to rerun "make hello" after making that change. 00:16:07.670 --> 00:16:08.380 Enter. 00:16:08.380 --> 00:16:11.830 And there we have it, like the first of our erroneous outputs. 00:16:11.830 --> 00:16:12.940 And it's yelling at me. 00:16:12.940 --> 00:16:15.075 It's missing a terminating character. 00:16:15.075 --> 00:16:17.950 And there's some red in here, some green, drawing my attention to it. 00:16:17.950 --> 00:16:20.598 Sometimes these error messages will be straightforward. 00:16:20.598 --> 00:16:23.390 Sometimes you're going to rack your brain a bit to figure them out. 00:16:23.390 --> 00:16:24.970 But for now I've kind of spoiled it. 00:16:24.970 --> 00:16:27.200 Obviously Enter is not the right solution. 00:16:27.200 --> 00:16:30.200 So let me clear my terminal window just to hide that error. 00:16:30.200 --> 00:16:32.050 Let me delete this. 00:16:32.050 --> 00:16:36.850 And let me propose now that I add this incantation here. 00:16:36.850 --> 00:16:39.610 So backslash n, it turns out, is going to be 00:16:39.610 --> 00:16:43.000 the sort of magical way of ensuring that you actually get 00:16:43.000 --> 00:16:45.830 a new line at the end of your output. 00:16:45.830 --> 00:16:49.930 So let me go ahead now and rerun "make hello," because I've changed my code. 00:16:49.930 --> 00:16:55.390 I need to now reconvert, recompile the source code to new machine. 00:16:55.390 --> 00:16:56.290 "./hello." 00:16:56.290 --> 00:17:00.580 And now, there is the canonical "hello, world" program 00:17:00.580 --> 00:17:03.330 that I hoped to write in the first place. 00:17:03.330 --> 00:17:05.863 So for now, don't worry about the include. 00:17:05.863 --> 00:17:07.280 Don't worry about the standard io. 00:17:07.280 --> 00:17:10.369 Don't worry about int or main or void or the curly braces. 00:17:10.369 --> 00:17:12.508 Focus primarily on line 5 here. 00:17:12.508 --> 00:17:14.300 And over the course of today and next week, 00:17:14.300 --> 00:17:16.520 we'll start to tease apart the other characters 00:17:16.520 --> 00:17:18.680 that, for now, you should take at face value. 00:17:18.680 --> 00:17:22.200 Questions, though, on any of the steps we've just done? 00:17:22.200 --> 00:17:22.700 Yeah? 00:17:22.700 --> 00:17:27.580 STUDENT: Why is the backslash n inside the apostrophes? 00:17:27.580 --> 00:17:31.940 DAVID MALAN: Sure, why is the backslash n inside of the quotation marks, 00:17:31.940 --> 00:17:32.570 if you will? 00:17:32.570 --> 00:17:35.350 So short answer is that's just where it needs 00:17:35.350 --> 00:17:40.600 to be because inside of the quotes is the input that you want printf 00:17:40.600 --> 00:17:42.320 to output to the screen. 00:17:42.320 --> 00:17:46.030 So if you want printf, this function, to output a new line, 00:17:46.030 --> 00:17:50.470 it must be included in the quoted text that you give it. 00:17:50.470 --> 00:17:53.555 STUDENT: So the backslash n [INAUDIBLE]. 00:17:53.555 --> 00:17:54.430 DAVID MALAN: Exactly. 00:17:54.430 --> 00:17:58.840 Backslash n is a special pattern that "printf no" means, OK, I should 00:17:58.840 --> 00:18:01.060 move the cursor to the next line. 00:18:01.060 --> 00:18:02.330 Good question. 00:18:02.330 --> 00:18:04.010 Other questions on any of these steps? 00:18:04.010 --> 00:18:04.510 Yeah? 00:18:04.510 --> 00:18:05.562 STUDENT: [INAUDIBLE] 00:18:05.562 --> 00:18:06.770 DAVID MALAN: A good question. 00:18:06.770 --> 00:18:10.120 So what if you actually want to print backslash n? 00:18:10.120 --> 00:18:12.140 Things get a little tricky there. 00:18:12.140 --> 00:18:15.920 Let me go ahead and propose that we do this. 00:18:15.920 --> 00:18:18.490 So it turns out-- and this is often the case in programming-- 00:18:18.490 --> 00:18:20.890 when you want a literal character to appear, 00:18:20.890 --> 00:18:23.347 you actually put another backslash in front of it. 00:18:23.347 --> 00:18:25.430 But this is not going to be something we do often. 00:18:25.430 --> 00:18:27.340 But there is in fact a solution to that. 00:18:27.340 --> 00:18:30.145 But let me propose that beyond that now we compare it 00:18:30.145 --> 00:18:31.520 against what we've actually done. 00:18:31.520 --> 00:18:35.260 So here is the first Scratch program we wrote with the green flag there. 00:18:35.260 --> 00:18:37.690 Here, recall, is the mental model that I proposed 00:18:37.690 --> 00:18:41.950 we have for almost everything we do whereby functions are just 00:18:41.950 --> 00:18:45.820 an implementation, say, in code of algorithms, step-by-step instructions 00:18:45.820 --> 00:18:47.150 for solving problems. 00:18:47.150 --> 00:18:49.300 The inputs to functions, recall from last week, 00:18:49.300 --> 00:18:52.330 are called arguments, or in some contexts parameters. 00:18:52.330 --> 00:18:55.130 And sometimes functions can have side effects. 00:18:55.130 --> 00:18:58.280 Like last time with Scratch, there was the speech bubble 00:18:58.280 --> 00:19:00.440 that magically appeared next to the cat's mouth 00:19:00.440 --> 00:19:02.930 as a sort of side effect of using the Say block. 00:19:02.930 --> 00:19:07.310 So just like this then, we had the white oval as input. 00:19:07.310 --> 00:19:09.590 The Say block was the function last week. 00:19:09.590 --> 00:19:11.790 And then we had this here, side effect. 00:19:11.790 --> 00:19:14.550 Well, how do we compare these things left to right? 00:19:14.550 --> 00:19:16.010 Well, here's the Say block at left. 00:19:16.010 --> 00:19:17.990 Let's compare now to the C code at right. 00:19:17.990 --> 00:19:22.400 Notice a couple of things to adapt from Scratch to C. Print 00:19:22.400 --> 00:19:23.970 is almost the name of the function. 00:19:23.970 --> 00:19:26.780 It is technically "printf," for reasons we'll eventually see. 00:19:26.780 --> 00:19:32.210 Notice the parentheses in C are kind of evocative of the oval in Scratch. 00:19:32.210 --> 00:19:36.140 And that's probably why MIT chose an oval, because a lot of languages 00:19:36.140 --> 00:19:37.850 use parentheses in this way. 00:19:37.850 --> 00:19:42.050 You still write "hello, world" just as we did last week in Scratch. 00:19:42.050 --> 00:19:45.800 But per our demo thus far, you do need the double quotes-- 00:19:45.800 --> 00:19:49.220 and double quotes, not single quotes-- double quotes on the left and right. 00:19:49.220 --> 00:19:52.580 And in order to get that new line, you need the backslash n. 00:19:52.580 --> 00:19:54.630 And one more thing is missing. 00:19:54.630 --> 00:19:55.130 Yeah? 00:19:55.130 --> 00:19:55.460 STUDENT: Semicolon. 00:19:55.460 --> 00:19:57.920 DAVID MALAN: The semicolon to finish your thought. 00:19:57.920 --> 00:20:00.020 So all of these sort of stupid things now 00:20:00.020 --> 00:20:03.395 that honestly you will forget initially if you've never programmed before, 00:20:03.395 --> 00:20:05.270 but you'll soon-- within days, within weeks-- 00:20:05.270 --> 00:20:08.330 develop the muscle memory where all of that stuff just jumps off, 00:20:08.330 --> 00:20:10.700 jumps off the page right at you. 00:20:10.700 --> 00:20:14.420 All right, so this backslash n is generally known, 00:20:14.420 --> 00:20:16.920 just so you know, as an escape sequence. 00:20:16.920 --> 00:20:20.420 And so backslash n allows us to specify a character that 00:20:20.420 --> 00:20:21.890 might otherwise be hard to type. 00:20:21.890 --> 00:20:26.150 But let's tease apart some of the other things atop that function already. 00:20:26.150 --> 00:20:28.880 So include stdio.h. 00:20:28.880 --> 00:20:33.290 It turns out that in C, a lot of the functionality that 00:20:33.290 --> 00:20:36.900 comes with the language is tucked away in separate files. 00:20:36.900 --> 00:20:40.650 So if you want to use certain functions, you have to tell the compiler, 00:20:40.650 --> 00:20:43.430 hey, I want to do some standard input and output. 00:20:43.430 --> 00:20:45.680 Like, I want to print some things on the screen. 00:20:45.680 --> 00:20:48.980 And that's because, for now, you can think of printf 00:20:48.980 --> 00:20:52.340 as living in this file, stdio.h. 00:20:52.340 --> 00:20:53.870 That's a bit of a white lie for now. 00:20:53.870 --> 00:20:57.890 But in stdio.h is essentially a declaration for printf 00:20:57.890 --> 00:21:01.820 that will teach the compiler how to print things to the screen. 00:21:01.820 --> 00:21:05.090 So "hash include" here simply tells the compiler 00:21:05.090 --> 00:21:07.790 before it does anything else essentially go ahead and find 00:21:07.790 --> 00:21:10.700 on the local hard drive a file called stdio.h 00:21:10.700 --> 00:21:14.330 and copy/paste it there so I know now about printf. 00:21:14.330 --> 00:21:19.673 So this thing, this .h file, is what we'll technically call a header file. 00:21:19.673 --> 00:21:21.590 And if you've ever heard this word, especially 00:21:21.590 --> 00:21:24.800 if you have programmed before, it represents essentially what 00:21:24.800 --> 00:21:26.390 we'll start calling a library. 00:21:26.390 --> 00:21:29.330 So a library in the world of programming is just code 00:21:29.330 --> 00:21:31.740 that someone else wrote that you can use. 00:21:31.740 --> 00:21:33.968 It's usually free and open source, which means 00:21:33.968 --> 00:21:36.260 you can literally see the code that someone else wrote, 00:21:36.260 --> 00:21:37.670 or sometimes you pay for it. 00:21:37.670 --> 00:21:40.370 Sometimes it's closed source, which maybe Microsoft wrote it. 00:21:40.370 --> 00:21:43.850 They won't show you the code, but they will let you use the zeros and ones. 00:21:43.850 --> 00:21:46.670 So libraries are super useful because honestly 00:21:46.670 --> 00:21:49.700 even I don't really know how printf works. 00:21:49.700 --> 00:21:52.340 I've taken for granted for 25 years that if I use printf, 00:21:52.340 --> 00:21:53.780 stuff prints on the screen. 00:21:53.780 --> 00:21:56.330 But someone smarter than me had to actually write 00:21:56.330 --> 00:22:00.860 the code in C that figures out how to get the H, the E, the L-L-O, and so 00:22:00.860 --> 00:22:05.320 forth onto the Mac screen, the PC screen, the phone screen, or somewhere 00:22:05.320 --> 00:22:05.820 else. 00:22:05.820 --> 00:22:08.510 So libraries allow us to stand on each other's shoulders 00:22:08.510 --> 00:22:10.910 and so that someone else can do the hard work, 00:22:10.910 --> 00:22:14.550 and we can now solve problems that are more interesting to us, 00:22:14.550 --> 00:22:18.060 not the basic commodity stuff that everyone might want in their code. 00:22:18.060 --> 00:22:20.480 So again, library is code that someone else wrote. 00:22:20.480 --> 00:22:23.540 A header file in C is just a file ending in ".h" 00:22:23.540 --> 00:22:25.440 that gives you access to the same. 00:22:25.440 --> 00:22:28.040 And so for instance, if you to learn more about these, 00:22:28.040 --> 00:22:31.410 there are, what are called in the world of programming, manual pages. 00:22:31.410 --> 00:22:37.190 And these are textual files, like a documentation of sorts, 00:22:37.190 --> 00:22:39.860 via which you can just learn how a function works 00:22:39.860 --> 00:22:42.830 or how you can use its inputs or arguments. 00:22:42.830 --> 00:22:45.660 The reality is they're written for folks who aren't in CS50. 00:22:45.660 --> 00:22:48.410 They're written for folks who aren't just learning how to program. 00:22:48.410 --> 00:22:51.330 They're written for and by folks who have been programming for years. 00:22:51.330 --> 00:22:53.510 And so frankly, they're a little hard to understand. 00:22:53.510 --> 00:22:58.690 And so CS50 has its own version thereof at this URL, manual.cs50.io, 00:22:58.690 --> 00:23:03.260 where you'll see not only the official documentation for C, the language, 00:23:03.260 --> 00:23:07.360 but also staff-written simplifications in layperson's terms 00:23:07.360 --> 00:23:10.720 what all of the various popular functions are, what their inputs, 00:23:10.720 --> 00:23:12.130 and what their outputs are. 00:23:12.130 --> 00:23:17.990 So for instance, under stdio.h, you can actually go to that website. 00:23:17.990 --> 00:23:21.970 You can go to a URL like this, where stdio.h is in there. 00:23:21.970 --> 00:23:24.348 And you can actually see the documentation therefore. 00:23:24.348 --> 00:23:25.640 So let me go ahead and do this. 00:23:25.640 --> 00:23:27.640 I'm going to go ahead in my browser here, 00:23:27.640 --> 00:23:31.240 I'm going to go to manual.cs50.io. 00:23:31.240 --> 00:23:33.880 And let me go ahead here and select those functions 00:23:33.880 --> 00:23:36.220 that are frequently used in CS50. 00:23:36.220 --> 00:23:39.820 And under stdio.h, you'll see a bunch of functions, 00:23:39.820 --> 00:23:42.730 only one of which we've even discussed called printf. 00:23:42.730 --> 00:23:44.560 I'm going to click on printf there. 00:23:44.560 --> 00:23:46.573 And you'll see an interface that at first glance 00:23:46.573 --> 00:23:48.490 might be a little overwhelming, but it's going 00:23:48.490 --> 00:23:50.300 to start to look more and more familiar. 00:23:50.300 --> 00:23:54.620 So first of all, you'll see that if you want to use printf under Synopsis, 00:23:54.620 --> 00:23:56.690 you need to include this header file. 00:23:56.690 --> 00:23:59.960 Like, you literally copy and paste that line into your own code. 00:23:59.960 --> 00:24:03.440 You'll also see this, which for now is a bit arcane, 00:24:03.440 --> 00:24:07.890 but this is kind of a hint as to what the function is going to look like. 00:24:07.890 --> 00:24:09.043 But more on that soon. 00:24:09.043 --> 00:24:11.460 But more importantly, you can read a description about it. 00:24:11.460 --> 00:24:14.390 And because these descriptions, when you're in less comfortable mode, 00:24:14.390 --> 00:24:17.432 are written by me and the course's teaching fellows, teaching assistants, 00:24:17.432 --> 00:24:20.970 and course assistants, you'll find them to be much more in layperson's terms. 00:24:20.970 --> 00:24:23.340 And so long story short, rely on this site 00:24:23.340 --> 00:24:25.580 once you want to learn how to use some function 00:24:25.580 --> 00:24:27.960 and also what other functions exist. 00:24:27.960 --> 00:24:29.970 In fact, if I go back to the main page here, 00:24:29.970 --> 00:24:33.890 you'll see that there are all of these functions like are frequently 00:24:33.890 --> 00:24:35.000 used in CS50. 00:24:35.000 --> 00:24:37.190 And there's hundreds more that come with C. 00:24:37.190 --> 00:24:40.340 But learning a programming language is not about learning all of those 00:24:40.340 --> 00:24:45.020 but rather just getting a sense of where you find answers to questions when 00:24:45.020 --> 00:24:47.760 you do want to try something new. 00:24:47.760 --> 00:24:50.330 But what is important to know for CS50 today 00:24:50.330 --> 00:24:55.600 is that we have our own header file called cs50.h which has functions 00:24:55.600 --> 00:24:57.910 that we have written just to make life easier 00:24:57.910 --> 00:24:59.675 in the first few weeks of the class. 00:24:59.675 --> 00:25:02.050 These are training wheels that we'll eventually take off. 00:25:02.050 --> 00:25:04.270 But it turns out in C, especially if you've 00:25:04.270 --> 00:25:07.120 programmed before, it's actually really hard and annoying just 00:25:07.120 --> 00:25:11.900 to get input from users, to get them to type a word or a number or something 00:25:11.900 --> 00:25:12.400 else. 00:25:12.400 --> 00:25:15.850 Like, C does not make this easy, in part because it's one of the earliest 00:25:15.850 --> 00:25:17.800 languages that wasn't zeros and ones. 00:25:17.800 --> 00:25:20.050 So you have to do a lot of the heavy lifting yourself. 00:25:20.050 --> 00:25:23.200 But we'll put on these training wheels today and for a few weeks 00:25:23.200 --> 00:25:28.150 so that we can focus really on the intellectually interesting ideas of C 00:25:28.150 --> 00:25:30.970 and programming without getting bogged down in certain weeds 00:25:30.970 --> 00:25:33.160 that we will come back to before long. 00:25:33.160 --> 00:25:36.820 So for instance, CS50's own documentation is there at that URL. 00:25:36.820 --> 00:25:40.550 But within the library are these functions, 00:25:40.550 --> 00:25:44.440 a function called get_string to get a string of text. 00:25:44.440 --> 00:25:47.330 "String" is a synonym for just text in a programming language. 00:25:47.330 --> 00:25:50.170 So get_string will prompt the human for a string of text. 00:25:50.170 --> 00:25:52.660 Get_int is shorthand for "get integer," if you 00:25:52.660 --> 00:25:54.890 want to get a number from the user. 00:25:54.890 --> 00:25:58.550 Get_float is a little more arcane-- get a floating point number, 00:25:58.550 --> 00:26:00.780 like a real number with a decimal point in it. 00:26:00.780 --> 00:26:03.690 And dot, dot, dot, there are others, as well. 00:26:03.690 --> 00:26:08.180 So this is to say within CS50, we've got some user-friendly functions via which 00:26:08.180 --> 00:26:09.563 we can actually get some input. 00:26:09.563 --> 00:26:12.230 And let's go ahead and use one of these, for instance get_string 00:26:12.230 --> 00:26:15.950 because recall that last week our second program in Scratch 00:26:15.950 --> 00:26:18.920 was this one here, where we didn't just say "hello, world." 00:26:18.920 --> 00:26:21.110 We said "hello, David," or "hello, Carter," 00:26:21.110 --> 00:26:24.590 "hello, Julia," whoever it was typing their name in. 00:26:24.590 --> 00:26:28.910 But to do that, we needed this Ask block in Scratch. 00:26:28.910 --> 00:26:30.470 And then we used the Say block. 00:26:30.470 --> 00:26:34.050 And then we used the Join block to make all of this work. 00:26:34.050 --> 00:26:36.352 So let's translate this program now into C 00:26:36.352 --> 00:26:39.560 because it's a little more interesting and representative of the kind of code 00:26:39.560 --> 00:26:40.670 we'll start to write. 00:26:40.670 --> 00:26:42.950 But we need a slightly different mental model. 00:26:42.950 --> 00:26:47.450 Still have a function here, which is the implementation in code of an algorithm. 00:26:47.450 --> 00:26:49.910 We still have some inputs called arguments. 00:26:49.910 --> 00:26:53.330 But previously, I said that the Say block and, in turn, 00:26:53.330 --> 00:26:56.870 printf have side effects, which is just something visually, typically, 00:26:56.870 --> 00:26:58.340 that happens on the screen. 00:26:58.340 --> 00:27:02.900 Other functions actually have, what we called last week, return values. 00:27:02.900 --> 00:27:08.540 And this is kind of analogous to a function maybe doing something for you, 00:27:08.540 --> 00:27:11.990 writing down the answer on a slip of paper, and then handing you, 00:27:11.990 --> 00:27:14.180 the programmer, the slip of paper to do whatever 00:27:14.180 --> 00:27:16.430 you want with it without just broadcasting it 00:27:16.430 --> 00:27:19.190 to the world with, like, a speech bubble on the screen. 00:27:19.190 --> 00:27:22.610 So a return value is germane for a program like this 00:27:22.610 --> 00:27:26.960 because recall when we used the Ask block and I typed in my name, 00:27:26.960 --> 00:27:30.650 where did my name end up initially? 00:27:30.650 --> 00:27:32.217 It didn't go on the screen yet. 00:27:32.217 --> 00:27:33.050 Where did it end up? 00:27:33.050 --> 00:27:33.967 STUDENT: In an answer. 00:27:33.967 --> 00:27:35.900 DAVID MALAN: In an "answer" puzzle piece. 00:27:35.900 --> 00:27:39.320 And that special oval puzzle piece I claimed at the time 00:27:39.320 --> 00:27:43.250 represents a return value, so the metaphorical piece of paper 00:27:43.250 --> 00:27:46.410 that the answer is written down on so that I can then use it later. 00:27:46.410 --> 00:27:48.740 So that's what we want to get to now in C, 00:27:48.740 --> 00:27:51.832 a return value that I can then do anything I want, 00:27:51.832 --> 00:27:54.290 whether it's print it to the screen, change it in some way, 00:27:54.290 --> 00:27:56.430 save it in a database, or anything else. 00:27:56.430 --> 00:27:58.670 So here, for instance, is what we did with Scratch, 00:27:58.670 --> 00:28:02.510 the input to the Say block-- or the Ask block was "what's your name," quote, 00:28:02.510 --> 00:28:03.140 unquote. 00:28:03.140 --> 00:28:05.120 The function, of course, is the Ask function. 00:28:05.120 --> 00:28:07.310 And the return value was "answer." 00:28:07.310 --> 00:28:10.880 If we now consider how we might translate this to C, 00:28:10.880 --> 00:28:12.770 it's going to look a little weird at first. 00:28:12.770 --> 00:28:15.680 But it's going to follow a pattern today, next week, the week 00:28:15.680 --> 00:28:18.090 after any time we do code like this. 00:28:18.090 --> 00:28:23.480 So get_string, I claim, is going to be the most analogous function in C 00:28:23.480 --> 00:28:24.650 to the Ask block. 00:28:24.650 --> 00:28:28.400 And to be clear, this is a CS50-specific thing, training wheels of sorts. 00:28:28.400 --> 00:28:31.520 But we'll show you in a few weeks what this function is doing and how you 00:28:31.520 --> 00:28:35.750 cannot use it moving forward once you're comfortable with the language itself. 00:28:35.750 --> 00:28:37.820 Notice I've put parentheses, left and right, 00:28:37.820 --> 00:28:39.950 as sort of a placeholder for user input. 00:28:39.950 --> 00:28:43.118 And that user input is going to be "what's your name?" 00:28:43.118 --> 00:28:45.410 But I can't just put "what's your name" in parentheses. 00:28:45.410 --> 00:28:47.327 What do I minimally need to add in there, too? 00:28:47.327 --> 00:28:48.020 STUDENT: Quotes. 00:28:48.020 --> 00:28:50.353 DAVID MALAN: Yeah, so the double quotes, left and right. 00:28:50.353 --> 00:28:52.250 So let me go ahead and add those in. 00:28:52.250 --> 00:28:55.040 I left a space here, not for a new line. 00:28:55.040 --> 00:28:56.990 I could move the cursor to the next line. 00:28:56.990 --> 00:29:00.440 But I minimally at least want to move the cursor at least one space over 00:29:00.440 --> 00:29:03.140 just so it looks pretty, so that when I'm prompted for my name, 00:29:03.140 --> 00:29:05.810 there's a space between the question and my answer. 00:29:05.810 --> 00:29:07.280 But it could also be backslash n. 00:29:07.280 --> 00:29:09.830 That's just an aesthetic choice on my part. 00:29:09.830 --> 00:29:14.037 But what do I do with the answer that comes back from get_string? 00:29:14.037 --> 00:29:16.370 This is where the text is going to look different today. 00:29:16.370 --> 00:29:21.770 In C, you start to use an equals sign from left to right respectively. 00:29:21.770 --> 00:29:26.540 And on the left, you put the name of the variable in which you 00:29:26.540 --> 00:29:29.730 want to store that return value. 00:29:29.730 --> 00:29:32.030 So a return value is kind of a conceptual thing. 00:29:32.030 --> 00:29:33.900 You can do with it what you want. 00:29:33.900 --> 00:29:36.590 And if I want to store it longer term in a variable, 00:29:36.590 --> 00:29:40.580 like x or y or z in math class, I can just give it a name here-- x 00:29:40.580 --> 00:29:45.410 or y or z or, more reasonably, "answer," or any other English word. 00:29:45.410 --> 00:29:49.850 No spaces, generally lowercase, same heuristics as before, but this means 00:29:49.850 --> 00:29:53.010 now, ask the user, what's their name? 00:29:53.010 --> 00:29:55.620 Whatever they type in, go ahead and store it from right 00:29:55.620 --> 00:29:58.470 to left in this variable called "answer." 00:29:58.470 --> 00:29:59.880 But C's not done with us yet. 00:29:59.880 --> 00:30:02.130 If you've learned Python or certain other languages, 00:30:02.130 --> 00:30:04.470 you'd kind of be done writing code at this point. 00:30:04.470 --> 00:30:09.840 In C, though, you additionally have to tell the compiler what type of variable 00:30:09.840 --> 00:30:11.080 you want to use. 00:30:11.080 --> 00:30:13.590 So if it's a string of text, you say "string." 00:30:13.590 --> 00:30:17.668 If it's an integer, a number, you say "int," as we might have seen before. 00:30:17.668 --> 00:30:18.960 So it's a little more pedantic. 00:30:18.960 --> 00:30:22.320 It's more annoying, frankly, the more onus on you and me, the programmers. 00:30:22.320 --> 00:30:24.120 But this just helps the compiler know how 00:30:24.120 --> 00:30:26.260 to store it in the computer's memory. 00:30:26.260 --> 00:30:29.838 And I'm so close to being done with this line of code, but what's missing? 00:30:29.838 --> 00:30:30.630 STUDENT: Semicolon. 00:30:30.630 --> 00:30:31.713 DAVID MALAN: So semicolon. 00:30:31.713 --> 00:30:34.980 And mark my words, if you've never programmed before, sometime this week, 00:30:34.980 --> 00:30:37.290 this semester, you will forget a semicolon. 00:30:37.290 --> 00:30:38.678 You will raise your hand. 00:30:38.678 --> 00:30:41.970 You'll get frustrated because you can't understand why your code's not working. 00:30:41.970 --> 00:30:44.370 You will run into stupid issues like that. 00:30:44.370 --> 00:30:46.385 But do take faith that they are stupid issues. 00:30:46.385 --> 00:30:49.260 It doesn't mean it's not clicking for you or you're not a programmer. 00:30:49.260 --> 00:30:53.020 It just takes time to see these things if it's a new language to you. 00:30:53.020 --> 00:30:54.960 So there now is my semicolon. 00:30:54.960 --> 00:30:58.110 All right, let's go ahead then and do something 00:30:58.110 --> 00:31:02.100 with that return value using the second of the big puzzle pieces in Scratch. 00:31:02.100 --> 00:31:06.720 So when I wanted to say, "hello, David," or whatever the human's name is, 00:31:06.720 --> 00:31:09.850 I kind of stacked my puzzle pieces like this. 00:31:09.850 --> 00:31:13.350 This is actually similar to Python and maybe some other languages some of you 00:31:13.350 --> 00:31:13.980 have learned. 00:31:13.980 --> 00:31:15.990 But C is a little bit different. 00:31:15.990 --> 00:31:21.750 And the closest analog to this Scratch solution is going to look like this. 00:31:21.750 --> 00:31:25.080 I still use printf because printf is the equivalent of Say. 00:31:25.080 --> 00:31:32.022 Inside of my parentheses, I'm going to go ahead and say, weirdly, "hello, %s." 00:31:32.022 --> 00:31:35.580 So there's no real analog in C of Join. 00:31:35.580 --> 00:31:41.970 Instead, there's a way to specially format text using printf, hence the F 00:31:41.970 --> 00:31:42.900 in "printf." 00:31:42.900 --> 00:31:45.630 And what you do in printf is you type whatever English word 00:31:45.630 --> 00:31:47.280 or human words that you want. 00:31:47.280 --> 00:31:50.110 You then use %s a placeholder. 00:31:50.110 --> 00:31:54.450 If you want a string of text to be added to your own text, 00:31:54.450 --> 00:31:55.935 you literally write "%s." 00:31:55.935 --> 00:31:59.640 And let me anticipate a question from the crowd-- how do you print out %s? 00:31:59.640 --> 00:32:03.690 There's a solution to that, too, if you literally ever want to print out %s. 00:32:03.690 --> 00:32:07.390 But it's deliberately a weird choice of characters 00:32:07.390 --> 00:32:10.140 so that the probability that we ever need to type this ourselves 00:32:10.140 --> 00:32:12.870 is just low that no one really worries too much about it. 00:32:12.870 --> 00:32:14.550 All right, but that's not quite enough. 00:32:14.550 --> 00:32:19.890 In addition to saying "hello", comma, space, placeholder %s-- 00:32:19.890 --> 00:32:23.880 and just for vocabulary sake, that's a format code. 00:32:23.880 --> 00:32:26.250 Again, "format" being the F in printf. 00:32:26.250 --> 00:32:29.010 I still need my double quotes around the whole thing. 00:32:29.010 --> 00:32:31.290 In this case, to match my previous program, 00:32:31.290 --> 00:32:33.270 I am going to go ahead and add the backslash n 00:32:33.270 --> 00:32:35.910 to move the cursor to the next line. 00:32:35.910 --> 00:32:39.840 And now I've left a crazy amount of room here, but that's deliberate. 00:32:39.840 --> 00:32:42.240 Does anyone have an instinct for what I'm probably 00:32:42.240 --> 00:32:47.180 going to want to add after the quotes but still inside of the parentheses? 00:32:47.180 --> 00:32:48.310 STUDENT: The answer. 00:32:48.310 --> 00:32:49.840 DAVID MALAN: So answer itself. 00:32:49.840 --> 00:32:54.010 I need to somehow tell printf with a second input, 00:32:54.010 --> 00:32:58.870 otherwise known as an argument, what I want to substitute for that %s. 00:32:58.870 --> 00:33:02.650 And so I put a comma and then the name of the variable 00:33:02.650 --> 00:33:06.028 that I want printf to figure out how to plug in here. 00:33:06.028 --> 00:33:09.070 So honestly it's a little annoying, and this is kind of a dated approach. 00:33:09.070 --> 00:33:11.620 Newer, more modern languages, like we'll see later 00:33:11.620 --> 00:33:13.630 in the course, Python and JavaScript, actually 00:33:13.630 --> 00:33:15.950 have much more user-friendly ways of doing it. 00:33:15.950 --> 00:33:19.390 But once you wrap your mind around the heuristics, the rules here, 00:33:19.390 --> 00:33:23.470 it's just formatting a string by plugging in whatever you want 00:33:23.470 --> 00:33:26.470 into this format string, so to speak. 00:33:26.470 --> 00:33:28.810 And again, the comma here is important. 00:33:28.810 --> 00:33:33.220 This signifies that it takes one input at left and a second input at right. 00:33:33.220 --> 00:33:34.420 But notice this comma. 00:33:34.420 --> 00:33:35.950 There's technically two commas. 00:33:35.950 --> 00:33:40.480 But I'm not claiming that this function takes three inputs. 00:33:40.480 --> 00:33:41.680 Why? 00:33:41.680 --> 00:33:43.975 This comma I'm pointing out doesn't mean the same. 00:33:43.975 --> 00:33:46.690 STUDENT: It's because that comma's part of the quotation marks 00:33:46.690 --> 00:33:48.070 and it's been part of the string. 00:33:48.070 --> 00:33:48.700 DAVID MALAN: Exactly. 00:33:48.700 --> 00:33:51.867 This comma that I'm pointing to is part of the quotation marks and therefore 00:33:51.867 --> 00:33:53.910 part of my string of English text. 00:33:53.910 --> 00:33:55.400 So this is just English grammar. 00:33:55.400 --> 00:33:57.140 This is sort of C syntax. 00:33:57.140 --> 00:33:59.810 And again, these are the sort of annoying little details 00:33:59.810 --> 00:34:03.795 that we're using the same symbol for different things, but context matters. 00:34:03.795 --> 00:34:06.170 So just stare at your code, look carefully left to right, 00:34:06.170 --> 00:34:10.080 and generally the answer will pop out, no pun intended. 00:34:10.080 --> 00:34:13.244 OK, questions now on this syntax before we actually write it and run it? 00:34:13.244 --> 00:34:13.744 Yeah? 00:34:13.744 --> 00:34:18.290 STUDENT: Why is the backslash n not after the answer? 00:34:18.290 --> 00:34:20.940 DAVID MALAN: Why is the backslash n not after the answer? 00:34:20.940 --> 00:34:24.230 So the way functions work, including printf, 00:34:24.230 --> 00:34:28.310 is that you pass to them one argument inside of the parentheses. 00:34:28.310 --> 00:34:32.690 And then if you have a second argument, you put it after this comma here. 00:34:32.690 --> 00:34:36.920 But the way printf works is that its first argument is always a string 00:34:36.920 --> 00:34:39.330 that you want to be formatted for you. 00:34:39.330 --> 00:34:43.340 So anything you want printed on the screen has to go in those quotes. 00:34:43.340 --> 00:34:45.560 And you can perhaps extrapolate from this. 00:34:45.560 --> 00:34:50.389 If I actually wanted to say multiple things in this sentence, so "hello," 00:34:50.389 --> 00:34:55.670 maybe first name, last name, I could actually do "hello" comma, %s, space, 00:34:55.670 --> 00:34:59.960 %s, if I had two variables, one called First Name, one called Last Name. 00:34:59.960 --> 00:35:04.890 But then I would need another comma for a third input to the function. 00:35:04.890 --> 00:35:07.790 And so it's very general purpose in that sense. 00:35:07.790 --> 00:35:08.720 Questions? 00:35:08.720 --> 00:35:09.702 Yeah? 00:35:09.702 --> 00:35:15.370 STUDENT: Can you abstract this further by [INAUDIBLE] the "hello" [INAUDIBLE]?? 00:35:15.370 --> 00:35:19.870 DAVID MALAN: OK, so can you abstract away the format string itself, "hello," 00:35:19.870 --> 00:35:20.560 comma answer? 00:35:20.560 --> 00:35:23.770 Short answer, yes, but not nearly as easily in C 00:35:23.770 --> 00:35:25.280 as you can in other languages. 00:35:25.280 --> 00:35:26.920 So that's why we're keeping it simple for now. 00:35:26.920 --> 00:35:29.200 But you're going to love something like Python or JavaScript, 00:35:29.200 --> 00:35:31.090 where a lot of this complexity goes away. 00:35:31.090 --> 00:35:34.300 But you'll see also in Python and JavaScript and other languages, 00:35:34.300 --> 00:35:37.610 they still are inspired by syntax like this. 00:35:37.610 --> 00:35:41.350 So just understanding it now will be useful for multiple languages 00:35:41.350 --> 00:35:42.670 down the line. 00:35:42.670 --> 00:35:45.190 All right, so let's actually do something with this code 00:35:45.190 --> 00:35:48.670 rather than just talk about what it might be doing for us. 00:35:48.670 --> 00:35:52.400 Let me go over to, for instance, VS Code again. 00:35:52.400 --> 00:35:56.920 And I'm going to go ahead now and remove this middle line of printf. 00:35:56.920 --> 00:35:59.337 I'm still in my same file called "hello.c." 00:35:59.337 --> 00:36:02.170 I'm going to clear my terminal window just to eliminate distraction. 00:36:02.170 --> 00:36:04.097 And to do that, I can literally type "clear." 00:36:04.097 --> 00:36:05.680 But this is just for aesthetic's sake. 00:36:05.680 --> 00:36:07.240 That's not functionally that useful. 00:36:07.240 --> 00:36:10.363 Or you can hit Control L to achieve the same on your keyboard. 00:36:10.363 --> 00:36:13.030 But I'm going to go back to line 5 here, where I previously just 00:36:13.030 --> 00:36:14.990 said "hello, world." 00:36:14.990 --> 00:36:17.390 And I'm going to do this instead. 00:36:17.390 --> 00:36:20.330 I'm going to give myself a variable called string. 00:36:20.330 --> 00:36:22.760 Sorry, I'm going to give myself a variable called 00:36:22.760 --> 00:36:25.280 answer, the type of which is string. 00:36:25.280 --> 00:36:28.220 I'm going to set it equal to whatever the return 00:36:28.220 --> 00:36:33.290 value is of get_string, asking an English question, "what's your name?" 00:36:33.290 --> 00:36:36.290 with just a single space just to move the cursor over, 00:36:36.290 --> 00:36:38.430 followed by a semicolon. 00:36:38.430 --> 00:36:41.300 Then I'm going to go ahead and say printf, quote, 00:36:41.300 --> 00:36:48.680 unquote, "hello, placeholder, backslash n," 00:36:48.680 --> 00:36:50.900 comma, and then what goes here again? 00:36:50.900 --> 00:36:51.680 STUDENT: Answer. 00:36:51.680 --> 00:36:53.420 DAVID MALAN: This is where answer goes. 00:36:53.420 --> 00:36:56.430 And then I just need a semicolon on the right of that. 00:36:56.430 --> 00:36:58.042 But I think now that I'm done. 00:36:58.042 --> 00:36:59.750 But let me point out a couple of details. 00:36:59.750 --> 00:37:01.940 This got very colorful, very pretty quickly. 00:37:01.940 --> 00:37:05.610 And it's not like the black and white code I had on the screen a moment ago. 00:37:05.610 --> 00:37:10.160 This is because what programs like VS Code do for us is it "pretty" prints, 00:37:10.160 --> 00:37:13.980 or rather it syntax highlights our code for us. 00:37:13.980 --> 00:37:17.060 So syntax highlighting means just add some colors to the code 00:37:17.060 --> 00:37:19.080 so that different ideas pop out. 00:37:19.080 --> 00:37:22.760 So you'll notice, for instance, that printf here, get_string here 00:37:22.760 --> 00:37:26.210 are in purple because they represent functions, just like the Say block. 00:37:26.210 --> 00:37:28.460 Here, "what's your name?", quote, unquote, in VS Code 00:37:28.460 --> 00:37:29.990 is a light blue instead of white. 00:37:29.990 --> 00:37:33.230 But it's still going to be consistent if I use strings of text elsewhere, 00:37:33.230 --> 00:37:33.810 as well. 00:37:33.810 --> 00:37:35.453 So I didn't type anything special. 00:37:35.453 --> 00:37:37.370 This isn't like Microsoft Word or Google Docs, 00:37:37.370 --> 00:37:39.578 where I'm highlighting and changing colors of things. 00:37:39.578 --> 00:37:41.180 This is all happening automatically. 00:37:41.180 --> 00:37:44.060 But it's just unicode text. 00:37:44.060 --> 00:37:46.340 It's just being interpreted automatically 00:37:46.340 --> 00:37:51.080 and having these colors applied so that things pop out more usefully visually. 00:37:51.080 --> 00:37:52.985 Now, I've unfortunately made a mistake. 00:37:52.985 --> 00:37:55.610 But I'm going to deliberately induce this one because you, too, 00:37:55.610 --> 00:37:57.130 will probably make this mistake. 00:37:57.130 --> 00:37:58.880 I'm going to go ahead and run "make hello" 00:37:58.880 --> 00:38:00.380 again, because I've changed my code. 00:38:00.380 --> 00:38:03.740 So I have to regenerate the machine code from the new source code. 00:38:03.740 --> 00:38:06.950 But unfortunately, when I hit Enter now, my God, 00:38:06.950 --> 00:38:08.790 the errors don't even fit on the screen. 00:38:08.790 --> 00:38:09.990 So let me make this bigger. 00:38:09.990 --> 00:38:12.157 I'm going to click the little caret symbol here just 00:38:12.157 --> 00:38:14.360 to make my terminal bigger for just a moment. 00:38:14.360 --> 00:38:17.090 And you'll see that there's more lines of errors 00:38:17.090 --> 00:38:19.370 than there are of code that I actually wrote, 00:38:19.370 --> 00:38:22.730 often which is written pretty arcanely, again, for programmers who've 00:38:22.730 --> 00:38:24.830 been writing code for 10, 20 years. 00:38:24.830 --> 00:38:27.210 But there are some details that pop out. 00:38:27.210 --> 00:38:30.620 So notice the problem is definitely with hello.c. 00:38:30.620 --> 00:38:36.180 So great, it is my fault. This syntax here means that line 5 is the problem. 00:38:36.180 --> 00:38:38.810 And this next 5 means character 5. 00:38:38.810 --> 00:38:42.860 So you can literally triangulate your bug, your mistake by going to line 5 00:38:42.860 --> 00:38:45.440 and then over five, and it's somewhere in that area. 00:38:45.440 --> 00:38:49.280 Specifically, "the area is use of undeclared identifier string. 00:38:49.280 --> 00:38:51.320 Did you mean standard in?" 00:38:51.320 --> 00:38:52.460 I don't think I did. 00:38:52.460 --> 00:38:56.120 Like, I do want string, and then there's some other complexity here. 00:38:56.120 --> 00:39:00.860 But what's important here is not the specifics of this error but really 00:39:00.860 --> 00:39:04.010 the implication that it doesn't recognize the word 00:39:04.010 --> 00:39:06.590 "string" or "get_string." 00:39:06.590 --> 00:39:08.355 Now, why might this be? 00:39:08.355 --> 00:39:08.855 Yeah? 00:39:08.855 --> 00:39:14.195 STUDENT: You said that in order to [INAUDIBLE] 00:39:14.195 --> 00:39:15.070 DAVID MALAN: Exactly. 00:39:15.070 --> 00:39:17.740 Because we are using get_string, which I claimed 00:39:17.740 --> 00:39:19.930 is a CS50 thing that we'll use for a few weeks, 00:39:19.930 --> 00:39:22.910 C does not know about it out of the box, so to speak. 00:39:22.910 --> 00:39:26.080 I have to teach the compiler that get_string exists, 00:39:26.080 --> 00:39:29.620 just like I taught the compiler that printf exists by including 00:39:29.620 --> 00:39:31.010 the appropriate header file. 00:39:31.010 --> 00:39:35.200 And in this case, quite simply, it's called includeCS50.h. 00:39:35.200 --> 00:39:38.890 That now teaches the compiler, oh, someone else 00:39:38.890 --> 00:39:42.220 wrote this function already, get_string, and with it this type of variable 00:39:42.220 --> 00:39:43.190 called "string." 00:39:43.190 --> 00:39:45.430 So now if I go back to my terminal window 00:39:45.430 --> 00:39:49.510 and rerun the exact same command, "make hello"-- maybe crossing my fingers-- 00:39:49.510 --> 00:39:52.060 now nothing in fact goes wrong because the compiler 00:39:52.060 --> 00:39:55.210 has been brought up to speed with all of the functionality it needs. 00:39:55.210 --> 00:39:59.410 And now if I do ./hello, Enter, there it is, what's my name? 00:39:59.410 --> 00:40:01.330 And notice the cursor is one space over just 00:40:01.330 --> 00:40:03.550 because I thought that looked prettier than having the cursor right 00:40:03.550 --> 00:40:05.110 next to the question mark. 00:40:05.110 --> 00:40:07.840 D-A-V-I-D as my input, and Enter. 00:40:07.840 --> 00:40:11.890 And "hello, David." 00:40:11.890 --> 00:40:16.780 Questions on any of this code thus far? 00:40:16.780 --> 00:40:18.630 Questions? 00:40:18.630 --> 00:40:20.800 Any of the code. 00:40:20.800 --> 00:40:21.370 No? 00:40:21.370 --> 00:40:25.630 All right, so let's introduce some other functionality into the mix. 00:40:25.630 --> 00:40:28.570 It turns out that there are other types of data, 00:40:28.570 --> 00:40:31.270 other types of variables in the world, not just strings 00:40:31.270 --> 00:40:33.790 but indeed, per before, we have things called 00:40:33.790 --> 00:40:38.260 integers, "int" for short, floating point values, "float" for short, 00:40:38.260 --> 00:40:39.590 and a few others as well. 00:40:39.590 --> 00:40:41.530 So rather than only focus on string, let's 00:40:41.530 --> 00:40:43.330 get a little more interesting with numbers 00:40:43.330 --> 00:40:46.660 here and see what we can do with something like integers, again 00:40:46.660 --> 00:40:51.130 "int" for short, by taking a look at not get_string, as before, but now 00:40:51.130 --> 00:40:52.630 how about get_int. 00:40:52.630 --> 00:40:56.110 And for this, I'm going to give us a few other tools in our toolkit, 00:40:56.110 --> 00:40:59.986 those format codes to which I alluded earlier, like %s, 00:40:59.986 --> 00:41:01.640 fortunately are pretty straightforward. 00:41:01.640 --> 00:41:04.930 And here is a list of most of the popular format codes 00:41:04.930 --> 00:41:07.510 that you might ever care about with printf. 00:41:07.510 --> 00:41:10.180 In particular, we saw %s for string. 00:41:10.180 --> 00:41:13.060 And you can perhaps guess which one we're going to use for integers. 00:41:13.060 --> 00:41:13.932 STUDENT: %i. 00:41:13.932 --> 00:41:16.640 DAVID MALAN: Yeah, so %i is what we're going to use for integers. 00:41:16.640 --> 00:41:17.710 And this is the kind of thing that you can 00:41:17.710 --> 00:41:20.420 consult in the manual pages or a slide like this. 00:41:20.420 --> 00:41:22.850 There's only a few of them that you might frequently use. 00:41:22.850 --> 00:41:26.480 But let's go ahead and use integers in a more interesting context, not 00:41:26.480 --> 00:41:27.440 just using functions. 00:41:27.440 --> 00:41:29.510 But let's revisit this idea of conditionals. 00:41:29.510 --> 00:41:32.750 And conditionals in Scratch were like these proverbial forks in the road. 00:41:32.750 --> 00:41:36.420 Like, do you want to do this thing or this thing or this other thing? 00:41:36.420 --> 00:41:38.750 It's a way of making decisions in a program, which 00:41:38.750 --> 00:41:42.170 is going to be super useful and pretty much omnipresent in any problems 00:41:42.170 --> 00:41:43.320 that we try to solve. 00:41:43.320 --> 00:41:45.290 So let me give you a few more building blocks 00:41:45.290 --> 00:41:48.140 in C by doing the side-by-side comparison again. 00:41:48.140 --> 00:41:53.750 So here in Scratch is how we might say if two variables, x and y, 00:41:53.750 --> 00:41:57.110 one is less than the other, then go ahead and say, quote, unquote, 00:41:57.110 --> 00:41:58.250 "x is less than y." 00:41:58.250 --> 00:41:59.730 So kind of a stupid program. 00:41:59.730 --> 00:42:02.300 But just to show you the basic syntax for Scratch, 00:42:02.300 --> 00:42:07.160 this is how you would ask the question, if x is less than y, then say this. 00:42:07.160 --> 00:42:08.570 So Say is the function. 00:42:08.570 --> 00:42:09.920 "If" is the conditional. 00:42:09.920 --> 00:42:14.307 And the green thing here we called, what? 00:42:14.307 --> 00:42:15.140 What did we call it? 00:42:15.140 --> 00:42:15.560 Yeah? 00:42:15.560 --> 00:42:16.040 STUDENT: A Boolean. 00:42:16.040 --> 00:42:18.000 DAVID MALAN: A Boolean or a Boolean expression, 00:42:18.000 --> 00:42:20.167 which is just a fancy way of saying a question whose 00:42:20.167 --> 00:42:25.580 answer is true or false, yes or no, 1 or 0, however you want to think about it. 00:42:25.580 --> 00:42:28.560 In C, the code is going to look like this. 00:42:28.560 --> 00:42:32.480 So it'll take a little bit of habit, a little bit of muscle memory to develop. 00:42:32.480 --> 00:42:35.880 But you're going to say "if," then in parentheses, 00:42:35.880 --> 00:42:39.530 you're going to say "x less than y," assuming x and y are variables. 00:42:39.530 --> 00:42:41.690 You're then going to use these curly braces. 00:42:41.690 --> 00:42:45.110 And then if you want to say, quote, unquote, "x is less than y" 00:42:45.110 --> 00:42:50.140 in C, what function should we use here presumably? 00:42:50.140 --> 00:42:51.430 So printf. 00:42:51.430 --> 00:42:54.803 So printf, quote, unquote, "x is less than y." 00:42:54.803 --> 00:42:57.220 So it's a bit of a mouthful, but again notice the pattern. 00:42:57.220 --> 00:42:58.750 Name of the function is printf. 00:42:58.750 --> 00:43:02.320 In the parentheses, left and right, is the argument to printf, 00:43:02.320 --> 00:43:04.750 which is, quote, unquote, "x is less than y." 00:43:04.750 --> 00:43:07.730 And again, just for aesthetics, to move the cursor to the next line, 00:43:07.730 --> 00:43:10.522 which you don't have to worry about in Scratch because everything's 00:43:10.522 --> 00:43:14.000 in speech bubbles, we're adding a backslash n, as well. 00:43:14.000 --> 00:43:16.390 So notice that these curly braces, as they're 00:43:16.390 --> 00:43:18.850 called, much like the orange puzzle piece here, 00:43:18.850 --> 00:43:21.520 are kind of hugging the code like this. 00:43:21.520 --> 00:43:24.760 And I'll note that technically speaking in C, 00:43:24.760 --> 00:43:28.990 If you only have one line of code inside of your conditional, 00:43:28.990 --> 00:43:31.360 you can actually omit the curly braces altogether. 00:43:31.360 --> 00:43:34.190 And the code will still work if you have one single line of code. 00:43:34.190 --> 00:43:34.690 Why? 00:43:34.690 --> 00:43:36.190 Just saves people some keystrokes. 00:43:36.190 --> 00:43:38.470 If you have two lines, three lines, or more in there, 00:43:38.470 --> 00:43:39.670 you need the curly braces. 00:43:39.670 --> 00:43:41.920 But I'll always draw it with the curly braces in class 00:43:41.920 --> 00:43:44.980 so it resembles Scratch as closely as possible. 00:43:44.980 --> 00:43:47.230 As an aside to some of you who have programmed before, 00:43:47.230 --> 00:43:49.340 you might be cringing now because like you really 00:43:49.340 --> 00:43:52.610 like your curly brace to be over here instead of here, that, 00:43:52.610 --> 00:43:53.900 too, is a stylistic choice. 00:43:53.900 --> 00:43:55.790 And we'll talk, too, about this in the class. 00:43:55.790 --> 00:43:58.910 Aesthetically, stylistically there are certain decisions we can make. 00:43:58.910 --> 00:44:03.530 But generally in a class, in a company, you as a student or an employee 00:44:03.530 --> 00:44:07.890 would simply standardize on one set of rules, so to speak. 00:44:07.890 --> 00:44:12.200 So we'll use these rules for formatting our code in class consistently. 00:44:12.200 --> 00:44:16.792 All right, any questions on this snippet of C code? 00:44:16.792 --> 00:44:18.250 All right, a couple of others then. 00:44:18.250 --> 00:44:21.420 So here is how, in Scratch, we might have a two-way fork in the road. 00:44:21.420 --> 00:44:26.340 If x is less than y, say x is less than y, else say x is not less than y. 00:44:26.340 --> 00:44:28.870 In C, It's going to look pretty much the same. 00:44:28.870 --> 00:44:32.697 But notice I'm adding an "else" keyword here with another set of curly braces. 00:44:32.697 --> 00:44:34.530 I'm going to have a couple of more printf's. 00:44:34.530 --> 00:44:37.600 But in C, even though it's clearly keyboard based, 00:44:37.600 --> 00:44:41.500 it's just text, no more puzzle pieces, it's kind of the same shape, 00:44:41.500 --> 00:44:44.440 so to speak, and it's definitely the same idea. 00:44:44.440 --> 00:44:46.150 So it's following a pattern. 00:44:46.150 --> 00:44:49.990 What about a three-way fork in the road, if x is less than y, 00:44:49.990 --> 00:44:53.160 then say x is less than y, else if x is greater 00:44:53.160 --> 00:45:01.012 than y, say x is greater than y, else if x equals y, then say x is equal to y. 00:45:01.012 --> 00:45:02.970 Well, you can probably see where this is going. 00:45:02.970 --> 00:45:06.070 On the right-hand side, it looks almost the same. 00:45:06.070 --> 00:45:09.360 In fact, if I add in the printf's, it's really almost the same, 00:45:09.360 --> 00:45:10.620 at least logically. 00:45:10.620 --> 00:45:16.320 But there is at least one curiosity, seemingly a typo 00:45:16.320 --> 00:45:17.765 but it's not this time. 00:45:17.765 --> 00:45:18.265 Yeah? 00:45:18.265 --> 00:45:19.390 STUDENT: The double equals. 00:45:19.390 --> 00:45:23.860 DAVID MALAN: Yeah, the double equal signs does not match Scratch, 00:45:23.860 --> 00:45:28.150 but it's not in fact a bug or a mistake in C. Anyone 00:45:28.150 --> 00:45:33.610 have an intuition for why I did use two equal signs instead of one here? 00:45:33.610 --> 00:45:34.571 Yeah? 00:45:34.571 --> 00:45:37.460 STUDENT: Because otherwise it could be mistaken for a variable. 00:45:37.460 --> 00:45:38.335 DAVID MALAN: Exactly. 00:45:38.335 --> 00:45:41.180 Well, otherwise it would be mistaken for a variable, specifically 00:45:41.180 --> 00:45:42.990 assignment of a variable. 00:45:42.990 --> 00:45:47.270 So recall that in previous code, when we used the get_string function, 00:45:47.270 --> 00:45:52.465 we used an equals sign to assign, from right to left, the value of a variable. 00:45:52.465 --> 00:45:53.840 And that's a reasonable decision. 00:45:53.840 --> 00:45:56.007 "Equal" kind of means that the two should ultimately 00:45:56.007 --> 00:45:59.660 be equal even though you think about it from going right to left. 00:45:59.660 --> 00:46:03.180 Unfortunately, the authors of C kind of [? painted ?] themselves into a corner. 00:46:03.180 --> 00:46:05.900 And presumably, decades ago when they realized, oh, shoot, 00:46:05.900 --> 00:46:07.910 we've already used a single equal sign, how 00:46:07.910 --> 00:46:12.320 do we represent equality of two values, the answer they came up with was, 00:46:12.320 --> 00:46:14.450 all right, we'll just use two instead. 00:46:14.450 --> 00:46:16.058 And thus was born this decision. 00:46:16.058 --> 00:46:16.850 Is it the best one? 00:46:16.850 --> 00:46:17.690 Who knows? 00:46:17.690 --> 00:46:20.450 Crazy enough, in other languages, like JavaScript, 00:46:20.450 --> 00:46:23.810 you have not just one, but two, but also three equal signs 00:46:23.810 --> 00:46:25.770 in a row to solve yet another problem. 00:46:25.770 --> 00:46:29.100 So reasonable people will disagree as to how good or bad these decisions are. 00:46:29.100 --> 00:46:32.930 But in C, this is what you must do. 00:46:32.930 --> 00:46:38.430 But there's a bad design decision here, too. 00:46:38.430 --> 00:46:40.560 It's still correct, the code, left and right. 00:46:40.560 --> 00:46:45.210 But I bet I could critique the quality of the design of both the Scratch code 00:46:45.210 --> 00:46:47.910 and the C code for reasons, what? 00:46:47.910 --> 00:46:51.788 STUDENT: Do we have to do else if x equals [INAUDIBLE]?? 00:46:51.788 --> 00:46:53.580 DAVID MALAN: OK, no, really good intuition. 00:46:53.580 --> 00:46:57.030 Do we have to ask this third question, "else if x equals y?" 00:46:57.030 --> 00:46:59.610 So short answer, no, logically, right? 00:46:59.610 --> 00:47:05.130 Just based on arithmetic, either x is less than y or x is greater than y 00:47:05.130 --> 00:47:08.220 or, what's the only other possible answer? 00:47:08.220 --> 00:47:10.080 They must be equal, logically. 00:47:10.080 --> 00:47:13.140 So technically, you're just kind of wasting the computer's time 00:47:13.140 --> 00:47:15.270 by asking this question because it already knows, 00:47:15.270 --> 00:47:16.353 at that point, the answer. 00:47:16.353 --> 00:47:18.780 And you're wasting your time as the programmer bothering 00:47:18.780 --> 00:47:20.700 to type out more code or more puzzle pieces 00:47:20.700 --> 00:47:24.010 than you need because logically one stems from the other. 00:47:24.010 --> 00:47:28.080 So I can tighten this up, get rid of the "else, if," just use an "else." 00:47:28.080 --> 00:47:31.110 And I can do the same thing over here in C, thereby avoiding 00:47:31.110 --> 00:47:33.870 the double equal sign altogether, but not because it's wrong 00:47:33.870 --> 00:47:38.340 but because you're wasting time, because now you're potentially asking only two 00:47:38.340 --> 00:47:43.050 questions, two Boolean expressions, instead of 50% more by asking 00:47:43.050 --> 00:47:46.200 a total of three questions at most. 00:47:46.200 --> 00:47:52.900 Other questions then on this kind of code, logically or otherwise? 00:47:52.900 --> 00:47:53.400 No? 00:47:53.400 --> 00:47:58.450 All right, so if we have these puzzle pieces, so to speak, at our disposal, 00:47:58.450 --> 00:48:00.753 how can we go about actually using these? 00:48:00.753 --> 00:48:03.420 Well, suppose that we actually want to do something with values. 00:48:03.420 --> 00:48:06.190 Let's introduce variables in C, as well. 00:48:06.190 --> 00:48:08.197 We saw an example using a string a moment ago. 00:48:08.197 --> 00:48:10.030 But what about with something like integers? 00:48:10.030 --> 00:48:11.947 Well, you might not have used this in Scratch. 00:48:11.947 --> 00:48:13.830 But here's the orange puzzle piece in Scratch 00:48:13.830 --> 00:48:17.100 via which you can create a variable called counter to count things. 00:48:17.100 --> 00:48:19.638 And you can set it equal to some value like 0. 00:48:19.638 --> 00:48:21.930 Now, you can perhaps guess where we're going with this. 00:48:21.930 --> 00:48:27.540 If I want in C a variable called counter and I want to set it equal to 0, 00:48:27.540 --> 00:48:30.210 I use a single equal sign because logically you 00:48:30.210 --> 00:48:32.340 read it from right to left, or technically it's 00:48:32.340 --> 00:48:34.050 executed from right to left. 00:48:34.050 --> 00:48:37.128 But that's not enough in C. What's missing from the screen? 00:48:37.128 --> 00:48:37.920 STUDENT: Data type. 00:48:37.920 --> 00:48:38.760 DAVID MALAN: I need a what? 00:48:38.760 --> 00:48:39.570 STUDENT: You need a data type. 00:48:39.570 --> 00:48:40.860 DAVID MALAN: So we need a data type. 00:48:40.860 --> 00:48:43.110 And if it's going to be an integer, indeed I'm going to use int. 00:48:43.110 --> 00:48:44.943 And now the other mistake I keep making is-- 00:48:44.943 --> 00:48:45.735 STUDENT: Semicolon. 00:48:45.735 --> 00:48:48.070 DAVID MALAN: So a semicolon at the end of the line. 00:48:48.070 --> 00:48:50.153 So it's a little more verbose than some languages. 00:48:50.153 --> 00:48:52.180 But if you read it left to right, this is 00:48:52.180 --> 00:48:56.600 how you tell C to give you a variable called counter of type int 00:48:56.600 --> 00:49:00.010 and initialize it to a value of 0. 00:49:00.010 --> 00:49:00.850 That's all. 00:49:00.850 --> 00:49:04.750 All right, how about, in Scratch, if you want to change that variable by 1, 00:49:04.750 --> 00:49:05.860 by adding 1 to it? 00:49:05.860 --> 00:49:07.280 In Scratch, it's super simple. 00:49:07.280 --> 00:49:09.430 You just change it by 1 or even negative 1 00:49:09.430 --> 00:49:11.830 if you want to go up or down respectively. 00:49:11.830 --> 00:49:14.590 In C, it turns out you have a few different ways to do this. 00:49:14.590 --> 00:49:18.140 And this looks like it's not mathematically possible, 00:49:18.140 --> 00:49:21.820 but that's because equals is assignment, recall. 00:49:21.820 --> 00:49:27.130 So this line of code is not saying that counter equals counter plus 1, 00:49:27.130 --> 00:49:30.160 because that's just not possible using typical numbers. 00:49:30.160 --> 00:49:33.290 But this means take counter's value, add 1 to it, 00:49:33.290 --> 00:49:36.080 and assign it back to the counter variable. 00:49:36.080 --> 00:49:38.450 So it's like incrementing counter in this way. 00:49:38.450 --> 00:49:41.380 But this is such a common thing in C and in programming 00:49:41.380 --> 00:49:43.990 to increase or decrease the values of variables, 00:49:43.990 --> 00:49:46.090 there's a more succinct syntax. 00:49:46.090 --> 00:49:48.460 This is identical. 00:49:48.460 --> 00:49:51.167 And it might take you a little practice to get used to it, 00:49:51.167 --> 00:49:52.750 but it just saves you some keystrokes. 00:49:52.750 --> 00:49:56.050 But it similarly adds 1, or whatever number you use there. 00:49:56.050 --> 00:49:58.720 And this is such a common operation in C especially 00:49:58.720 --> 00:50:02.590 that there's an even tighter way of executing the same idea. 00:50:02.590 --> 00:50:08.240 And you can literally just say counter++ and then semicolon in this case. 00:50:08.240 --> 00:50:09.760 All three are exactly the same. 00:50:09.760 --> 00:50:11.170 All three are perfectly correct. 00:50:11.170 --> 00:50:13.545 But you'll learn over time that typing less on the screen 00:50:13.545 --> 00:50:15.860 is probably going to save you some time. 00:50:15.860 --> 00:50:19.660 Meanwhile, if we wanted to do the opposite and do something like minus 1 00:50:19.660 --> 00:50:24.610 in Scratch, we could similarly do minus minus in C. Or we could do-- 00:50:24.610 --> 00:50:28.450 yeah, we could do minus minus in C here at right. 00:50:28.450 --> 00:50:31.480 All right, so just some additional building blocks, translating 00:50:31.480 --> 00:50:36.790 from scratch to C. Why don't we go ahead and try using this perhaps 00:50:36.790 --> 00:50:38.260 in the following way? 00:50:38.260 --> 00:50:40.750 Let me go ahead and go back to VS Code. 00:50:40.750 --> 00:50:45.910 And let me propose that we do something like this. 00:50:45.910 --> 00:50:48.550 In VS Code, I'm going to go ahead and clear my terminal window. 00:50:48.550 --> 00:50:50.650 I'm going to close "hello.c" by just clicking 00:50:50.650 --> 00:50:54.220 the X. I'm going to go ahead and create a new file called "compare.c" 00:50:54.220 --> 00:50:56.410 because the purpose in life of this program 00:50:56.410 --> 00:50:58.942 is going to be to compare integers on the screen. 00:50:58.942 --> 00:51:00.400 This time I'm not going to mess up. 00:51:00.400 --> 00:51:04.480 I'm going to preemptively include CS50.h. 00:51:04.480 --> 00:51:07.630 I'm going to preemptively include stdio.h. 00:51:07.630 --> 00:51:13.690 And here, too, is a very common mistake in learning C. It is not "studio.h." 00:51:13.690 --> 00:51:16.690 So when you email us asking why "studio.h" is not working, 00:51:16.690 --> 00:51:18.190 that's because that is not the word. 00:51:18.190 --> 00:51:22.420 It is "standard io.h," meaning standard input and output, 00:51:22.420 --> 00:51:24.370 stuff involving the screen and the keyboard. 00:51:24.370 --> 00:51:27.370 Then I'm going to go ahead and, just as before, int main(void), 00:51:27.370 --> 00:51:29.830 but we'll come back to that eventually as to what it means. 00:51:29.830 --> 00:51:35.050 And now inside of "main," which is just where the main part of my program goes, 00:51:35.050 --> 00:51:39.310 again you can think of this as being analogous to "when green flag clicked." 00:51:39.310 --> 00:51:40.870 This just kicks everything off. 00:51:40.870 --> 00:51:42.680 I'm going to go ahead and do two things. 00:51:42.680 --> 00:51:45.100 I'm going to go ahead and get an integer called x, 00:51:45.100 --> 00:51:47.080 and I'm going to prompt the user for that int 00:51:47.080 --> 00:51:50.770 and just say something like, "what's x?", space. 00:51:50.770 --> 00:51:55.540 Then I'm going to do int y equals get_int, quote, unquote, "what's y?", 00:51:55.540 --> 00:51:56.410 space. 00:51:56.410 --> 00:52:00.830 And then let's just do something simple like, if x is less than y, 00:52:00.830 --> 00:52:03.520 then go ahead and print out, quote, unquote, 00:52:03.520 --> 00:52:08.740 "x is less than y backslash n," semicolon. 00:52:08.740 --> 00:52:10.610 So it's not a very deep program. 00:52:10.610 --> 00:52:13.610 It's just going to do what most any human brain could do pretty quickly. 00:52:13.610 --> 00:52:17.080 But it's at least demonstrating how we might use now 00:52:17.080 --> 00:52:19.480 something like a conditional in code. 00:52:19.480 --> 00:52:21.490 So let me go ahead and re-- 00:52:21.490 --> 00:52:25.750 let me compile this code for the first time, make compare, enter. 00:52:25.750 --> 00:52:31.150 Nothing bad happens, which is good. "./compare" is how I run the program. 00:52:31.150 --> 00:52:33.820 And just to tease this apart, dot, as we'll soon see, 00:52:33.820 --> 00:52:36.770 essentially means that the file is in your current folder. 00:52:36.770 --> 00:52:38.620 So dot means in your current folder. 00:52:38.620 --> 00:52:41.440 And we'll eventually see that dot dot means your parent 00:52:41.440 --> 00:52:43.780 folder, like the one that contains wherever 00:52:43.780 --> 00:52:45.820 I am on my computer's hard drive. 00:52:45.820 --> 00:52:47.050 All right. ./compare. 00:52:47.050 --> 00:52:48.264 What's x? 00:52:48.264 --> 00:52:49.210 1. 00:52:49.210 --> 00:52:50.470 2 for y. 00:52:50.470 --> 00:52:54.217 And hopefully it should say that x is less than y. 00:52:54.217 --> 00:52:55.300 So pretty straightforward. 00:52:55.300 --> 00:52:56.290 Proof by example. 00:52:56.290 --> 00:52:58.480 And hopefully this would work in other cases, too. 00:52:58.480 --> 00:53:04.960 But if I flip that around and I rerun it, ./compare, and I do 2 and 1, 00:53:04.960 --> 00:53:06.432 nothing's going to happen. 00:53:06.432 --> 00:53:08.140 But you would expect that because there's 00:53:08.140 --> 00:53:11.860 only one Boolean expression deciding whether or not 00:53:11.860 --> 00:53:13.880 I should actually type this out. 00:53:13.880 --> 00:53:15.160 So what's going on? 00:53:15.160 --> 00:53:17.140 Well, if this helps you, you might find it 00:53:17.140 --> 00:53:20.830 useful to think about the logic of any program, be it in Scratch or C, 00:53:20.830 --> 00:53:22.600 as kind of a flowchart of sorts. 00:53:22.600 --> 00:53:24.910 And we'll put up a few of these over time just in case 00:53:24.910 --> 00:53:26.690 you're a particularly visual thinker. 00:53:26.690 --> 00:53:28.780 And this represents what it is I just did. 00:53:28.780 --> 00:53:32.470 So here in this picture is where the program starts conceptually. 00:53:32.470 --> 00:53:35.860 And any time you see a diamond, think of that as a Boolean expression, 00:53:35.860 --> 00:53:37.330 a question that's being asked. 00:53:37.330 --> 00:53:39.940 And the question being asked is, is x less than y? 00:53:39.940 --> 00:53:44.600 That has two possible answers, true or false, yes or no respectively. 00:53:44.600 --> 00:53:48.400 So let me propose, per the arrow, that if the answer is true, then print out, 00:53:48.400 --> 00:53:52.480 per this rectangle, "x is less than y," just quote, unquote, and then stop. 00:53:52.480 --> 00:53:53.680 That's it for the program. 00:53:53.680 --> 00:53:56.800 But logically, if x is not less than y, that 00:53:56.800 --> 00:54:00.310 is that question's answer is false, we'll just skip right to the end 00:54:00.310 --> 00:54:01.210 and stop. 00:54:01.210 --> 00:54:03.493 So this is a control-flow diagram. 00:54:03.493 --> 00:54:05.410 It's just a pictorial way that you could write 00:54:05.410 --> 00:54:09.490 on a piece of paper that just represents what it is the program is doing. 00:54:09.490 --> 00:54:12.520 And this gets a little more interesting if now we 00:54:12.520 --> 00:54:14.260 do something else with the code. 00:54:14.260 --> 00:54:20.620 For instance, instead of just concluding that it's less than 1 or the other, 00:54:20.620 --> 00:54:22.330 let's go back to the code here. 00:54:22.330 --> 00:54:24.028 Let me clear my terminal window. 00:54:24.028 --> 00:54:25.070 And let me add an "else." 00:54:25.070 --> 00:54:29.950 So else, go ahead and print out "x"-- 00:54:29.950 --> 00:54:34.240 I don't think I want to say this-- "greater than y." 00:54:34.240 --> 00:54:35.480 It's not quite right. 00:54:35.480 --> 00:54:38.208 What would be reasonable to say here? 00:54:38.208 --> 00:54:39.500 STUDENT: "x is not less than y. 00:54:39.500 --> 00:54:43.850 DAVID MALAN: Yeah, subtle, but "x is not less than y" because it could be equal. 00:54:43.850 --> 00:54:48.990 We don't know if we're only checking two scenarios here. 00:54:48.990 --> 00:54:53.030 So if I recompile this, make compare, ./compare. 00:54:53.030 --> 00:54:55.970 Now if I do 1, comma 2, I still get the same answer. 00:54:55.970 --> 00:55:01.532 If I rerun ./compare 2, comma 1, I now get the opposite answer. 00:55:01.532 --> 00:55:02.990 It's not as good as might be ideal. 00:55:02.990 --> 00:55:05.750 It'd be nice to know if it's equal to or greater than. 00:55:05.750 --> 00:55:08.330 But at least that's all of the code that we have here. 00:55:08.330 --> 00:55:10.430 And just to now paint a picture, if I go back 00:55:10.430 --> 00:55:13.340 to my control-flow diagram, my flow chart here, 00:55:13.340 --> 00:55:15.800 this is what it looked like before logically. 00:55:15.800 --> 00:55:21.600 Now that I've added in a second branch, so to speak, 00:55:21.600 --> 00:55:26.420 now, if the answer is false, I first print out x is not less than y, 00:55:26.420 --> 00:55:28.370 and then I stop the program. 00:55:28.370 --> 00:55:31.297 So same idea, but the decision tree, if you will, 00:55:31.297 --> 00:55:34.130 if you've taken a 10 or the like, is getting a little bit bigger now 00:55:34.130 --> 00:55:34.672 conceptually. 00:55:34.672 --> 00:55:36.755 All right, what if we do something more than this? 00:55:36.755 --> 00:55:38.700 Let's actually have that third condition. 00:55:38.700 --> 00:55:40.973 Let me go back into my code here. 00:55:40.973 --> 00:55:43.890 I'm going to hide the terminal window just to make room for more code. 00:55:43.890 --> 00:55:47.730 And I'm going to say, "else if x is greater 00:55:47.730 --> 00:55:51.720 than y," then go ahead and say not "x is not less than y," 00:55:51.720 --> 00:55:55.710 but rather "x is greater than y." 00:55:55.710 --> 00:55:59.950 And then down here, I'll do an "else if x equals equals y," 00:55:59.950 --> 00:56:06.540 then I can go ahead and say printf, "x is equal to y backslash n," 00:56:06.540 --> 00:56:07.990 close quote. 00:56:07.990 --> 00:56:11.160 All right, so now if I run it-- let me open my terminal window again. 00:56:11.160 --> 00:56:13.380 Let me rerun make compare. 00:56:13.380 --> 00:56:15.570 Let me rerun ./compare. 00:56:15.570 --> 00:56:17.400 1 and 2 are the same. 00:56:17.400 --> 00:56:18.600 Let me rerun it. 00:56:18.600 --> 00:56:20.730 2 and 1 are the same. 00:56:20.730 --> 00:56:22.470 Let me rerun it a third time. 00:56:22.470 --> 00:56:26.130 1 and 1 are now in fact equal. 00:56:26.130 --> 00:56:28.080 So this works correctly. 00:56:28.080 --> 00:56:31.920 But why did I make a point of using these "else if"s? 00:56:31.920 --> 00:56:36.660 Put another way, couldn't I just make my life a little simpler 00:56:36.660 --> 00:56:39.180 and just say, if this, then that? 00:56:39.180 --> 00:56:40.200 If this, then that. 00:56:40.200 --> 00:56:41.640 If this, then that. 00:56:41.640 --> 00:56:43.290 Just ask all three questions. 00:56:43.290 --> 00:56:44.340 Keep the code simple. 00:56:44.340 --> 00:56:47.010 Don't bother with these else's. 00:56:47.010 --> 00:56:48.715 Would this work for me? 00:56:48.715 --> 00:56:49.215 Yeah? 00:56:49.215 --> 00:56:52.312 STUDENT: It just seems like [INAUDIBLE] the program 00:56:52.312 --> 00:56:53.520 doesn't have to run the rest. 00:56:53.520 --> 00:56:56.980 DAVID MALAN: Yeah, so it saves a little bit of time because in this case, 00:56:56.980 --> 00:57:00.840 just like in English, this is like asking three separate questions. 00:57:00.840 --> 00:57:05.190 And it's not harnessing any information from previous questions 00:57:05.190 --> 00:57:08.950 in order to decide whether you should bother asking that other question. 00:57:08.950 --> 00:57:11.610 In other words, if x is less than y-- and you already 00:57:11.610 --> 00:57:14.460 figured that out because it's 1 and 2 respectively-- you're 00:57:14.460 --> 00:57:15.420 going to print this. 00:57:15.420 --> 00:57:17.967 Why would you waste time asking this question when 00:57:17.967 --> 00:57:19.050 it's not going to be true? 00:57:19.050 --> 00:57:21.133 Why would you waste time asking this question when 00:57:21.133 --> 00:57:22.240 it's not going to be true? 00:57:22.240 --> 00:57:24.115 And so the point I wanted to make here, which 00:57:24.115 --> 00:57:27.300 is that if we visualize that particular design, 00:57:27.300 --> 00:57:30.000 what the flow chart looks like is actually this. 00:57:30.000 --> 00:57:31.320 And let me zoom in at the top. 00:57:31.320 --> 00:57:34.500 If you ask the question "is x less than y," well, 00:57:34.500 --> 00:57:37.502 you're going to go ahead and say, x less than y. 00:57:37.502 --> 00:57:39.210 Then if you go down to the next question, 00:57:39.210 --> 00:57:41.490 you're still going to ask is x greater than y. 00:57:41.490 --> 00:57:45.060 And then below that, you're still going to ask is x equal equal to y? 00:57:45.060 --> 00:57:50.730 So no matter what x and y are, you're asking one, two, three questions all 00:57:50.730 --> 00:57:51.580 of the time. 00:57:51.580 --> 00:57:54.840 But if we actually go in and do what we did the first time, 00:57:54.840 --> 00:57:59.700 where if I go back to my code and I undo this edit and add back the "else if"s-- 00:57:59.700 --> 00:58:01.990 and now let me go back to the flow chart, 00:58:01.990 --> 00:58:05.440 which I claim is bad because it's one, two, three questions, one 00:58:05.440 --> 00:58:09.630 or two of which might not be necessary-- now if I visualize what I just did, 00:58:09.630 --> 00:58:12.480 the flow chart gets a little more complicated looking, 00:58:12.480 --> 00:58:15.430 but it's going to be better designed, more efficient. 00:58:15.430 --> 00:58:15.930 Why? 00:58:15.930 --> 00:58:19.320 Well, because if I start at the top here, I ask one question, 00:58:19.320 --> 00:58:20.460 is x less than y. 00:58:20.460 --> 00:58:22.050 If the answer is true, OK. 00:58:22.050 --> 00:58:23.220 I say x less than y. 00:58:23.220 --> 00:58:25.680 And then, boom, I sort of cheat and go all the way 00:58:25.680 --> 00:58:29.400 to the end of the program and stop, having asked only one question. 00:58:29.400 --> 00:58:33.600 If, though, x is not less than y, OK, fine, I'll ask you a second question. 00:58:33.600 --> 00:58:37.680 But if the answer is true, boom, I print out x is greater than y, 00:58:37.680 --> 00:58:38.730 and then I stop. 00:58:38.730 --> 00:58:42.000 And only in a perverse case where x actually 00:58:42.000 --> 00:58:46.410 equals y, which I'm going to claim is very unlikely or infrequent, 00:58:46.410 --> 00:58:51.420 only then am I going to ask one, two, three questions to figure out whether 00:58:51.420 --> 00:58:53.950 or not to print something at all. 00:58:53.950 --> 00:58:56.557 So this is what we mean by distinguishing between correctness 00:58:56.557 --> 00:58:58.140 of code-- because it's still correct-- 00:58:58.140 --> 00:59:01.050 but this version is better designed because hopefully you're 00:59:01.050 --> 00:59:04.980 going to go down this branch or this branch rather than the longest one 00:59:04.980 --> 00:59:06.390 frequently. 00:59:06.390 --> 00:59:13.660 Any questions now about this code or this visualization thereof? 00:59:13.660 --> 00:59:14.230 Yeah? 00:59:14.230 --> 00:59:17.597 STUDENT: I don't know if [INAUDIBLE] 00:59:19.332 --> 00:59:20.540 DAVID MALAN: A perfect segue. 00:59:20.540 --> 00:59:23.153 Why did I bother, though, even asking this question? 00:59:23.153 --> 00:59:25.070 Don't need to because when I hit this button-- 00:59:25.070 --> 00:59:27.440 hopefully I have the right slide in place-- 00:59:27.440 --> 00:59:30.287 this would be even better than that design. 00:59:30.287 --> 00:59:31.620 So thank you for teeing that up. 00:59:31.620 --> 00:59:32.662 This is the same picture. 00:59:32.662 --> 00:59:35.630 It sort of got bigger because there's fewer nodes, 00:59:35.630 --> 00:59:37.100 fewer shapes in the picture. 00:59:37.100 --> 00:59:40.400 Notice that if x less than y, boom, we say as much, and we stop. 00:59:40.400 --> 00:59:43.910 If x is not less than y but it's greater than y, boom, we stop. 00:59:43.910 --> 00:59:46.820 Or if it's not greater than, we immediately 00:59:46.820 --> 00:59:49.580 conclude x indeed is equal to y. 00:59:49.580 --> 00:59:50.900 And again, we stop. 00:59:50.900 --> 00:59:54.680 So this picture is about as efficient and as 00:59:54.680 --> 00:59:57.200 well designed as we can make our logic. 00:59:57.200 --> 00:59:59.640 That's about as good as we can solve this problem. 00:59:59.640 --> 01:00:02.690 So if I go back to my code now to make my C code 01:00:02.690 --> 01:00:06.830 match that, the only thing I need to do is stop wasting the computer's time. 01:00:06.830 --> 01:00:08.540 Don't ask that third question. 01:00:08.540 --> 01:00:12.290 Just logically, mathematically conclude that of course it's 01:00:12.290 --> 01:00:16.455 going to be equal at that point in the story. 01:00:16.455 --> 01:00:18.080 All right, any other questions on this? 01:00:18.080 --> 01:00:21.340 STUDENT: [INAUDIBLE] 01:00:21.340 --> 01:00:23.906 DAVID MALAN: Sorry, a little louder? 01:00:23.906 --> 01:00:26.702 STUDENT: [INAUDIBLE] 01:00:28.353 --> 01:00:29.770 DAVID MALAN: Really good question. 01:00:29.770 --> 01:00:31.728 What if I put in something that's not a number? 01:00:31.728 --> 01:00:35.910 So here, too, is where the CS50 library and the implementation of get_int 01:00:35.910 --> 01:00:36.990 will be your friend. 01:00:36.990 --> 01:00:41.400 So for instance, if I run ./compare and I want to compare cats and dogs, 01:00:41.400 --> 01:00:43.905 I could type in "cats," Enter. 01:00:43.905 --> 01:00:45.780 It's just going to prompt me again and again. 01:00:45.780 --> 01:00:47.738 It's not going to let me type in "dogs" either. 01:00:47.738 --> 01:00:49.740 It's going to force me to give it an integer. 01:00:49.740 --> 01:00:51.880 C does not do that by default. 01:00:51.880 --> 01:00:55.110 And in fact, as we'll soon see over the course of CS50, 01:00:55.110 --> 01:00:57.660 C is actually a very dangerous language at the end of the day 01:00:57.660 --> 01:01:00.660 because it just trusts that the human is doing what it wants. 01:01:00.660 --> 01:01:04.890 And as such, a lot of today's software that is hacked in some ways, 01:01:04.890 --> 01:01:07.800 if it's using C or another language called C++, 01:01:07.800 --> 01:01:11.190 are actually very vulnerable to certain types of hacking, 01:01:11.190 --> 01:01:14.880 whereas other languages that we'll get to in the class are less so for reasons 01:01:14.880 --> 01:01:17.170 like this. 01:01:17.170 --> 01:01:21.440 All right, so besides this, let's consider just one other data type. 01:01:21.440 --> 01:01:21.940 how about. 01:01:21.940 --> 01:01:26.710 So besides strings, besides chars, there's some others on this list here. 01:01:26.710 --> 01:01:29.110 Sorry, besides strings, besides integers, 01:01:29.110 --> 01:01:33.410 there's this other data type here in C known as a char for a single character. 01:01:33.410 --> 01:01:35.050 So here, let me just tease this apart. 01:01:35.050 --> 01:01:37.690 A string is indeed a string of text. 01:01:37.690 --> 01:01:40.540 It is zero or more characters together. 01:01:40.540 --> 01:01:45.130 A char is always precisely one character. 01:01:45.130 --> 01:01:48.520 Not all languages bother distinguishing between a single character 01:01:48.520 --> 01:01:49.660 and a string of characters. 01:01:49.660 --> 01:01:53.140 But in C, a string is typically multiple characters, 01:01:53.140 --> 01:01:54.640 but technically can be zero. 01:01:54.640 --> 01:01:56.350 Coincidentally, it could be one. 01:01:56.350 --> 01:01:58.210 But it's capable of being more. 01:01:58.210 --> 01:02:02.290 But a char is literally, as the word implies, a single character. 01:02:02.290 --> 01:02:05.050 All right, given that, notice that in the CS50 library, 01:02:05.050 --> 01:02:08.388 besides get_string, besides get_int, we also have get_char, 01:02:08.388 --> 01:02:10.930 so another handy function for just getting a single character 01:02:10.930 --> 01:02:11.770 from the user. 01:02:11.770 --> 01:02:14.603 Now, why would it be useful to get a single character from the user? 01:02:14.603 --> 01:02:16.312 Well, what if you're just doing something 01:02:16.312 --> 01:02:19.310 that you and I do pretty frequently when you install new software 01:02:19.310 --> 01:02:20.750 or fill out some form? 01:02:20.750 --> 01:02:23.370 You agree to some form of terms and conditions. 01:02:23.370 --> 01:02:25.650 So in fact, let me go back over to VS Code here. 01:02:25.650 --> 01:02:29.540 And let me propose that I create a new program called agree.c, 01:02:29.540 --> 01:02:32.420 so something akin to asking for the user's agreement. 01:02:32.420 --> 01:02:35.698 So in VS Code, I'm going to type "code agree.c." 01:02:35.698 --> 01:02:37.490 And I'm going to do some quick boilerplate. 01:02:37.490 --> 01:02:43.280 So include CS50.h, include stdio.h, int main(void). 01:02:43.280 --> 01:02:46.820 And then inside of main, which is like the "green flag clicked," 01:02:46.820 --> 01:02:47.960 I'm going to do this. 01:02:47.960 --> 01:02:51.290 Go ahead and get a character from the user, 01:02:51.290 --> 01:02:54.500 and ask them something simple like, "Do you agree?," 01:02:54.500 --> 01:02:56.490 expecting a yes/no response. 01:02:56.490 --> 01:03:00.778 But at the beginning of this line, I need to put the return value somewhere. 01:03:00.778 --> 01:03:02.570 So I'm going to put it in a variable called 01:03:02.570 --> 01:03:06.200 C. And in programming, if you're just getting a single value, 01:03:06.200 --> 01:03:11.645 it's OK sometimes to use X and Y or C when you're using-- 01:03:11.645 --> 01:03:15.470 in larger programs, you'll benefit from using actual words like "answer," 01:03:15.470 --> 01:03:16.820 like we did from the get go. 01:03:16.820 --> 01:03:18.870 But C has to be a specific type. 01:03:18.870 --> 01:03:21.020 So I'm going to literally say "char," and then 01:03:21.020 --> 01:03:23.180 I'm going to finish my thought with a semicolon. 01:03:23.180 --> 01:03:26.030 And here's now how I could check if the user agrees or not. 01:03:26.030 --> 01:03:27.480 I could do something like this. 01:03:27.480 --> 01:03:31.580 If the value of C equals equals, quote, unquote, 01:03:31.580 --> 01:03:38.240 lowercase 'y,' then go ahead and print out "Agreed backslash n." 01:03:38.240 --> 01:03:44.420 Else if the variable C has a value equal to lowercase 'n', let's go ahead 01:03:44.420 --> 01:03:48.440 and print out, say, "Not agreed," as though I'm agreeing or not to some 01:03:48.440 --> 01:03:49.670 terms and conditions. 01:03:49.670 --> 01:03:51.590 But notice these are not typos. 01:03:51.590 --> 01:03:56.400 What did I do ever so subtly different from last time I used text? 01:03:56.400 --> 01:03:56.900 Yeah? 01:03:56.900 --> 01:03:58.983 STUDENT: Single quotes instead of double quotes. 01:03:58.983 --> 01:04:01.150 DAVID MALAN: Single quotes instead of double quotes. 01:04:01.150 --> 01:04:02.150 So here's the heuristic. 01:04:02.150 --> 01:04:04.860 When using strings, which are generally multiple characters, 01:04:04.860 --> 01:04:06.240 have to use double quotes. 01:04:06.240 --> 01:04:09.900 When using a single character, you should use single quotes 01:04:09.900 --> 01:04:11.320 around the single character. 01:04:11.320 --> 01:04:13.770 So let me go ahead now and, make agree. 01:04:13.770 --> 01:04:16.890 Nothing went wrong, which is good. ./agree, Enter, 01:04:16.890 --> 01:04:19.080 and let me go ahead and type in y for yes. 01:04:19.080 --> 01:04:20.350 It seems to work. 01:04:20.350 --> 01:04:24.480 Let me run it again. ./agree. n for no, and it seems to work. 01:04:24.480 --> 01:04:27.600 And just if I type in something random like question mark, I don't know, 01:04:27.600 --> 01:04:28.590 it doesn't crash. 01:04:28.590 --> 01:04:32.830 It just ignores me because I only had two Boolean expressions there. 01:04:32.830 --> 01:04:35.610 But notice that it's actually a little buggy arguably. 01:04:35.610 --> 01:04:38.550 Let me run it again. ./agree, Enter. 01:04:38.550 --> 01:04:41.760 How about capital Y because, like, my Caps Lock is down. 01:04:41.760 --> 01:04:43.050 OK, it just ignores me. 01:04:43.050 --> 01:04:46.020 Let me do it again. ./agree, capital N because my-- oops-- 01:04:46.020 --> 01:04:48.540 because my Caps Lock is down. 01:04:48.540 --> 01:04:49.590 OK, it just ignores me. 01:04:49.590 --> 01:04:52.590 But this should make sense because I'm literally checking for lowercase. 01:04:52.590 --> 01:04:55.990 So how could I fix this? 01:04:55.990 --> 01:05:00.347 How could I fix this without just changing lowercase to uppercase, 01:05:00.347 --> 01:05:02.680 because that would then break it in the other direction? 01:05:02.680 --> 01:05:03.220 Yeah? 01:05:03.220 --> 01:05:06.510 STUDENT: [INAUDIBLE] 01:05:09.698 --> 01:05:12.490 DAVID MALAN: Yeah, let's just add another branch here, so to speak. 01:05:12.490 --> 01:05:18.090 So if variable C equals equals capital Y, then I can go ahead here 01:05:18.090 --> 01:05:20.280 and say printf agreed. 01:05:20.280 --> 01:05:23.160 And then let me close my terminal to make more room. 01:05:23.160 --> 01:05:27.690 Otherwise, down here, else if C equals equals capital N, 01:05:27.690 --> 01:05:31.050 let's go ahead and again say printf not agreed. 01:05:31.050 --> 01:05:33.600 And I claim that this would actually now work. 01:05:33.600 --> 01:05:36.180 It's a four-way fork in the road, but I'm at least 01:05:36.180 --> 01:05:40.500 checking for lowercase, uppercase, lowercase, uppercase for y and n 01:05:40.500 --> 01:05:41.580 respectively. 01:05:41.580 --> 01:05:44.910 I claim that this is correct, but this too, 01:05:44.910 --> 01:05:47.490 even if you've never programmed before, should start today 01:05:47.490 --> 01:05:49.290 to rub you the wrong way. 01:05:49.290 --> 01:05:51.420 Like, we can do better. 01:05:51.420 --> 01:05:53.790 This isn't the best design. 01:05:53.790 --> 01:05:54.570 Why might that be? 01:05:54.570 --> 01:05:55.490 Yeah? 01:05:55.490 --> 01:06:00.735 STUDENT: Could you change the character c to be uppercase, like before you even 01:06:00.735 --> 01:06:01.235 [INAUDIBLE]? 01:06:01.235 --> 01:06:02.420 DAVID MALAN: Ah, clever. 01:06:02.420 --> 01:06:07.790 So could we change the variable c to just be forced to uppercase 01:06:07.790 --> 01:06:09.320 or maybe forced to lowercase? 01:06:09.320 --> 01:06:12.650 No matter what the human types, we just do that ourselves so that way 01:06:12.650 --> 01:06:15.380 we can just simplify this again to two possible scenarios. 01:06:15.380 --> 01:06:17.930 I love that, but we haven't seen any functions yet 01:06:17.930 --> 01:06:20.570 in C that would let me change things to uppercase or lowercase. 01:06:20.570 --> 01:06:22.795 So we'll get there, but a good instinct and correct. 01:06:22.795 --> 01:06:23.420 Other thoughts? 01:06:23.420 --> 01:06:24.620 STUDENT: Use "or." 01:06:24.620 --> 01:06:28.550 DAVID MALAN: So we could use "or" in some sense, like a logical "or." 01:06:28.550 --> 01:06:32.760 What I don't like about this, to be clear, is that it's repeating itself. 01:06:32.760 --> 01:06:35.510 And there's this principle in programming, and in life in general, 01:06:35.510 --> 01:06:37.940 like, don't repeat yourself unnecessarily. 01:06:37.940 --> 01:06:41.930 And by that I mean I literally have the same line 10 as 14. 01:06:41.930 --> 01:06:44.760 I have the same line 18 as 22. 01:06:44.760 --> 01:06:48.920 And if anything, one, I literally wasted twice as much time as I needed to. 01:06:48.920 --> 01:06:51.200 Put another way, per our discussion of Scratch, 01:06:51.200 --> 01:06:53.510 what if I go in and just change something like, 01:06:53.510 --> 01:06:55.610 I want to be more excited, like "Agreed!"? 01:06:55.610 --> 01:06:57.818 Well, I might forget to change it in the other place. 01:06:57.818 --> 01:07:00.527 And let's just claim for today's purposes that that looks stupid, 01:07:00.527 --> 01:07:02.580 it's a bug, because I want them to be consistent. 01:07:02.580 --> 01:07:06.090 So don't invite situations where you might change something 01:07:06.090 --> 01:07:07.650 in one place but not another. 01:07:07.650 --> 01:07:10.030 Just only write it in one place total. 01:07:10.030 --> 01:07:12.280 So I like this idea of "or"-ing things together. 01:07:12.280 --> 01:07:14.580 So let me go ahead and delete what I just did. 01:07:14.580 --> 01:07:18.240 And just to be clear, too, while this is on the screen, when you highlight code 01:07:18.240 --> 01:07:21.630 in VS Code based on how we've configured it, these dots just show you 01:07:21.630 --> 01:07:25.230 how much I've indented because in C, stylistically, the convention 01:07:25.230 --> 01:07:29.710 is generally to indent four spaces and maybe four more spaces. 01:07:29.710 --> 01:07:32.100 So those dots just help you count without having 01:07:32.100 --> 01:07:34.560 to manually eyeball things yourself. 01:07:34.560 --> 01:07:36.180 But let me delete those lines. 01:07:36.180 --> 01:07:38.250 Let me delete these lines. 01:07:38.250 --> 01:07:40.090 And this is going to look a little weird, 01:07:40.090 --> 01:07:43.590 but the way you can "or" two thoughts together, so to 01:07:43.590 --> 01:07:46.950 speak, like "or" them together, is you don't say "or," 01:07:46.950 --> 01:07:50.610 but you use two vertical bars, which syntactically 01:07:50.610 --> 01:07:53.070 means the English word "or." 01:07:53.070 --> 01:07:55.650 And you can just ask the other question, if C equals, 01:07:55.650 --> 01:07:57.330 quote, unquote, capital 'Y.' 01:07:57.330 --> 01:08:02.340 And then down here, I can say or C equals equals capital 'N.' 01:08:02.340 --> 01:08:05.170 So it adds a little more code to each of those lines, 01:08:05.170 --> 01:08:09.450 but it doesn't add redundancy, because I've not duplicated my printf. 01:08:09.450 --> 01:08:12.570 I've not added more curly braces unnecessarily. 01:08:12.570 --> 01:08:17.040 Now as an aside, there's the opposite of "or", logically is the word "and." 01:08:17.040 --> 01:08:19.740 Just so you've seen it, I could do this. 01:08:19.740 --> 01:08:24.430 "&&" in C is how you express that the thing on the left must be true 01:08:24.430 --> 01:08:26.319 and the thing on the right must be true. 01:08:26.319 --> 01:08:30.045 But why would this make no sense in this context of line 8? 01:08:30.045 --> 01:08:31.920 STUDENT: It can't be uppercase and lowercase. 01:08:31.920 --> 01:08:33.753 DAVID MALAN: Yeah, at least to my knowledge, 01:08:33.753 --> 01:08:36.300 a character can't be both lowercase and uppercase. 01:08:36.300 --> 01:08:37.720 That just makes no logical sense. 01:08:37.720 --> 01:08:41.250 So indeed "or" is what we want in this case. 01:08:41.250 --> 01:08:43.286 Other questions? 01:08:43.286 --> 01:08:49.245 STUDENT: In CS50.h, is there a way to directly compare strings [INAUDIBLE]?? 01:08:49.245 --> 01:08:50.370 DAVID MALAN: Good question. 01:08:50.370 --> 01:08:53.310 Via CS50.h, is there a way to compare strings. 01:08:53.310 --> 01:08:54.270 Short answer, no. 01:08:54.270 --> 01:08:56.100 But C is going to give us that capability. 01:08:56.100 --> 01:08:59.439 And in fact, next week, among the things we'll do is actually compare strings. 01:08:59.439 --> 01:09:01.439 And if you've programmed before, you'll see in C 01:09:01.439 --> 01:09:04.533 that it actually doesn't work the way that you might expect. 01:09:04.533 --> 01:09:06.450 But that's a problem, too, that we will solve. 01:09:06.450 --> 01:09:08.040 But that transcends CS50. 01:09:08.040 --> 01:09:15.370 That's a question for C. Other questions on this kind of logic? 01:09:15.370 --> 01:09:18.790 Just to make this real then, anytime you click one of those EULAs 01:09:18.790 --> 01:09:22.000 or terms and conditions on a form in a piece of software, 01:09:22.000 --> 01:09:24.850 odds are there is code as simple as this underneath the hood. 01:09:24.850 --> 01:09:25.760 Maybe it's graphical. 01:09:25.760 --> 01:09:27.760 Maybe it's checking for you clicking this button 01:09:27.760 --> 01:09:29.052 or maybe hitting the Enter key. 01:09:29.052 --> 01:09:31.479 But underneath the hood is presumably some kind 01:09:31.479 --> 01:09:35.740 of conditional checking for those kinds of outputs. 01:09:35.740 --> 01:09:37.600 All right, how about another building block 01:09:37.600 --> 01:09:39.558 from last time, which we'll now translate to C, 01:09:39.558 --> 01:09:41.720 namely loops, things that happen again and again? 01:09:41.720 --> 01:09:43.640 And these, too, are everywhere in code. 01:09:43.640 --> 01:09:47.710 So in Scratch, here's how we might meow three times, super simple. 01:09:47.710 --> 01:09:49.430 In C, it's going to look a little weird. 01:09:49.430 --> 01:09:52.810 But you will get used to this over time if you've never programmed before. 01:09:52.810 --> 01:09:55.540 It looks like a mouthful, OK. 01:09:55.540 --> 01:09:57.940 But let's tease it apart line by line. 01:09:57.940 --> 01:10:01.360 And you'll see that you won't have that reaction frequently because it's all 01:10:01.360 --> 01:10:03.500 going to start to look very similar to itself. 01:10:03.500 --> 01:10:04.900 But what are we doing here? 01:10:04.900 --> 01:10:09.400 In C, you don't have the luxury of these cute and fun puzzle pieces 01:10:09.400 --> 01:10:12.430 that just do the work for you, repeat three times. 01:10:12.430 --> 01:10:16.250 In fact, in C and programming in general, sometimes 01:10:16.250 --> 01:10:18.870 the work is on us to actually figure out, OK, 01:10:18.870 --> 01:10:21.830 how can I use functions, variables, conditionals, and loops 01:10:21.830 --> 01:10:25.580 and implement some idea like repetition, like looping? 01:10:25.580 --> 01:10:27.680 And in C, here's how this might work. 01:10:27.680 --> 01:10:31.850 How can I go about doing something like printing "meow" three times? 01:10:31.850 --> 01:10:33.620 Well, I know about variables now. 01:10:33.620 --> 01:10:35.270 We're about to see loops. 01:10:35.270 --> 01:10:39.110 And I've seen how I can update variables by plussing or minusing 01:10:39.110 --> 01:10:40.280 some value to them. 01:10:40.280 --> 01:10:41.850 Let's combine those ideas. 01:10:41.850 --> 01:10:46.375 So first, I'm doing what with this highlighted line in English? 01:10:46.375 --> 01:10:49.250 If a friend cared to ask you, like, 'what is this line of code doing' 01:10:49.250 --> 01:10:51.012 later today, what would you say? 01:10:51.012 --> 01:10:54.250 STUDENT: It's creating a variable called "counter" and setting it equal to 3. 01:10:54.250 --> 01:10:56.750 DAVID MALAN: Good, it's creating a variable called "counter" 01:10:56.750 --> 01:10:58.400 and setting it equal to 3. 01:10:58.400 --> 01:11:01.040 I'll use slightly new jargon. 01:11:01.040 --> 01:11:04.157 I'm defining a variable, would be the term of our "called counter" 01:11:04.157 --> 01:11:05.240 and setting it equal to 3. 01:11:05.240 --> 01:11:07.152 So I'll use my hand to represent the counter. 01:11:07.152 --> 01:11:08.360 And that's all a variable is. 01:11:08.360 --> 01:11:11.870 It's like storage in some case that I'm representing information, using 01:11:11.870 --> 01:11:14.480 my hand in this case or the computer's memory here. 01:11:14.480 --> 01:11:17.575 Now what happens when using a loop in C? 01:11:17.575 --> 01:11:20.700 There's different types of loops, one of which is called a for loop-- oop-- 01:11:20.700 --> 01:11:22.790 one of which is called a while loop-- spoiler. 01:11:22.790 --> 01:11:24.770 A while loop works like this. 01:11:24.770 --> 01:11:28.910 Inside of parentheses is a Boolean expression just like inside 01:11:28.910 --> 01:11:30.770 of a conditional that asks a question. 01:11:30.770 --> 01:11:33.330 But this time the question is going to determine, 01:11:33.330 --> 01:11:37.080 do you keep going through the loop again and again and again? 01:11:37.080 --> 01:11:38.810 So it's not a one-time thing potentially. 01:11:38.810 --> 01:11:41.210 It is checked again and again and again to decide 01:11:41.210 --> 01:11:44.810 when it is time to stop looping, to stop cycling. 01:11:44.810 --> 01:11:46.970 All right, so it's asking this question first. 01:11:46.970 --> 01:11:49.713 Is counter greater than 0? 01:11:49.713 --> 01:11:52.880 OK, obviously the answer is true because I'm still holding up three fingers. 01:11:52.880 --> 01:11:54.140 So what happens? 01:11:54.140 --> 01:11:58.070 C goes inside of the curly braces per the indentation 01:11:58.070 --> 01:12:02.340 and executes printf of "meow," which prints out a "meow" on the screen. 01:12:02.340 --> 01:12:04.640 The next line of code executes, which, recall, 01:12:04.640 --> 01:12:07.250 is the same as just subtracting 1 from counter. 01:12:07.250 --> 01:12:10.790 So I think I take down one finger, so I'm left with two. 01:12:10.790 --> 01:12:12.035 And what happens next? 01:12:12.035 --> 01:12:13.910 Well, this you just kind of have to memorize. 01:12:13.910 --> 01:12:16.580 Once you get to the end of the inside of a loop, 01:12:16.580 --> 01:12:19.460 you go back to the beginning of a loop here 01:12:19.460 --> 01:12:22.770 and ask the same question, the same Boolean expression. 01:12:22.770 --> 01:12:24.680 So is 2 greater than 0? 01:12:24.680 --> 01:12:25.700 OK, obviously so. 01:12:25.700 --> 01:12:27.890 So you go into it, you print a "meow." 01:12:27.890 --> 01:12:31.400 You go into it and decrement counter further by one. 01:12:31.400 --> 01:12:33.470 So now my hand is holding up one. 01:12:33.470 --> 01:12:35.900 Now we wrap back around to the Boolean expression. 01:12:35.900 --> 01:12:37.790 Is 1 greater than 0? 01:12:37.790 --> 01:12:38.480 Obviously. 01:12:38.480 --> 01:12:40.340 We print out a third "meow." 01:12:40.340 --> 01:12:43.850 We then decrement counter again, and my hand goes to zero. 01:12:43.850 --> 01:12:45.680 We go back around once more. 01:12:45.680 --> 01:12:47.600 Is 0 greater than 0? 01:12:47.600 --> 01:12:48.350 No. 01:12:48.350 --> 01:12:49.970 And now the program just terminates. 01:12:49.970 --> 01:12:51.980 Or if there were more code here, it would just 01:12:51.980 --> 01:12:56.240 jump outside of the curly braces and keep going lower on the screen. 01:12:56.240 --> 01:12:57.810 So that's all that's happening. 01:12:57.810 --> 01:13:00.740 And so this is what MIT has the luxury of doing with pictures. 01:13:00.740 --> 01:13:03.440 But at MIT, someone probably essentially wrote 01:13:03.440 --> 01:13:09.030 code that looks like this to give us the illusion, the abstraction of this. 01:13:09.030 --> 01:13:12.710 So what we're learning today is how they invented these puzzle pieces 01:13:12.710 --> 01:13:17.370 by just using lower-level plumbing, if you will, like this here. 01:13:17.370 --> 01:13:17.870 Yeah? 01:13:17.870 --> 01:13:21.900 STUDENT: What would happen if you created the variable "counter" 01:13:21.900 --> 01:13:23.330 inside of the curly braces? 01:13:23.330 --> 01:13:24.830 DAVID MALAN: A really good question. 01:13:24.830 --> 01:13:28.430 What would happen if you created the variable inside of the curly braces? 01:13:28.430 --> 01:13:30.650 Short answer, it just wouldn't work in C, 01:13:30.650 --> 01:13:33.560 because if I were to try with my slide here, 01:13:33.560 --> 01:13:39.650 for instance, to move this line of code here down inside of this, for instance, 01:13:39.650 --> 01:13:44.700 now the very top line is trying to use counter before it even exists. 01:13:44.700 --> 01:13:46.160 So C is very literal it. 01:13:46.160 --> 01:13:48.000 Reads top to bottom, left to right. 01:13:48.000 --> 01:13:50.870 And if it hasn't seen you define or create a variable yet, 01:13:50.870 --> 01:13:55.550 you're going to get some scary error message on the screen instead. 01:13:55.550 --> 01:13:59.010 All right, other questions on this here code? 01:13:59.010 --> 01:13:59.510 No? 01:13:59.510 --> 01:14:03.110 All right, so if we want to then maybe tighten this up a bit, 01:14:03.110 --> 01:14:05.130 let me propose that we could do this instead. 01:14:05.130 --> 01:14:07.850 So besides this version of the code, let me just 01:14:07.850 --> 01:14:10.070 do something more canonical, more conventional. 01:14:10.070 --> 01:14:13.280 So you're totally fine with using a variable like counter . 01:14:13.280 --> 01:14:15.500 It's what Scratch uses by default. It's very verbose. 01:14:15.500 --> 01:14:16.520 It does what it says. 01:14:16.520 --> 01:14:18.410 Frankly, once you get comfy with programming, 01:14:18.410 --> 01:14:20.480 like most typical programmers, whenever they 01:14:20.480 --> 01:14:24.210 have a single integer in a program whose sole purpose in life is to count, 01:14:24.210 --> 01:14:27.810 they'll just use "i" for integer just like I used "c" for character. 01:14:27.810 --> 01:14:29.820 When you have larger programs, you don't want 01:14:29.820 --> 01:14:35.070 to start using A and B and C and D and E and F and so forth for your variables 01:14:35.070 --> 01:14:36.880 because nothing's going to make any sense. 01:14:36.880 --> 01:14:40.980 But when you're doing something super simple like counting with an integer, 01:14:40.980 --> 01:14:44.670 using a short-named variable is totally stylistically reasonable. 01:14:44.670 --> 01:14:48.195 But I can tighten this up further, not just renaming counter to i. 01:14:48.195 --> 01:14:50.580 What else can I do, if you recall? 01:14:50.580 --> 01:14:51.300 Over here? 01:14:51.300 --> 01:14:52.800 STUDENT: [INAUDIBLE] 01:14:52.800 --> 01:14:53.550 DAVID MALAN: Sure. 01:14:53.550 --> 01:14:55.150 STUDENT: A for loop? 01:14:55.150 --> 01:14:56.400 DAVID MALAN: Oh, OK, for loop. 01:14:56.400 --> 01:14:57.442 Yes, that was my spoiler. 01:14:57.442 --> 01:15:00.300 But while in a while loop, I can tighten this up slightly more. 01:15:00.300 --> 01:15:01.460 Over here? 01:15:01.460 --> 01:15:03.660 STUDENT: Instead of i equals i minus 1. 01:15:03.660 --> 01:15:06.420 DAVID MALAN: Yeah, instead of i equals i minus 1, 01:15:06.420 --> 01:15:08.310 I can actually tighten this up this way. 01:15:08.310 --> 01:15:10.143 And we didn't see the minus before, but it's 01:15:10.143 --> 01:15:15.120 the same idea-- i minus equals 1, or even more succinctly, i minus minus. 01:15:15.120 --> 01:15:18.210 So when you get comfortable with programming, any of these approaches 01:15:18.210 --> 01:15:19.230 are correct. 01:15:19.230 --> 01:15:21.875 This would be more conventional at this point. 01:15:21.875 --> 01:15:24.000 So if you want to write code like most other people 01:15:24.000 --> 01:15:28.410 write code, adopt ultimately these kinds of conventions. 01:15:28.410 --> 01:15:31.170 All right, so that just does the exact same thing, though. 01:15:31.170 --> 01:15:33.780 But let's now put this into practice. 01:15:33.780 --> 01:15:36.460 Let me go back to VS Code here. 01:15:36.460 --> 01:15:40.590 Let me go ahead and clear my terminal and close agree.c from before. 01:15:40.590 --> 01:15:43.200 And let me go ahead and create a file called "meow." 01:15:43.200 --> 01:15:45.540 So code meow.c. 01:15:45.540 --> 01:15:47.530 And let me do this the sort of wrong way. 01:15:47.530 --> 01:15:49.320 Let me include stdio.h. 01:15:49.320 --> 01:15:52.860 at the top, int main(void) thereafter. 01:15:52.860 --> 01:15:56.282 Inside of there, let me do printf "meow." 01:15:56.282 --> 01:15:57.240 And then you know what? 01:15:57.240 --> 01:15:58.020 I don't want to keep typing that. 01:15:58.020 --> 01:16:00.460 Let me just go ahead and copy/paste two more times. 01:16:00.460 --> 01:16:04.140 So I claim this is correct, make meow. 01:16:04.140 --> 01:16:05.520 ./meow, done. 01:16:05.520 --> 01:16:07.980 I've got code that prints "meow" three times. 01:16:07.980 --> 01:16:11.790 But this, again, should already rub you the wrong way. 01:16:11.790 --> 01:16:13.290 Why? 01:16:13.290 --> 01:16:14.040 Yeah? 01:16:14.040 --> 01:16:15.267 STUDENT: There's duplication. 01:16:15.267 --> 01:16:16.350 DAVID MALAN: Because what? 01:16:16.350 --> 01:16:17.030 STUDENT: There's duplication. 01:16:17.030 --> 01:16:18.690 DAVID MALAN: Because I have duplication. 01:16:18.690 --> 01:16:20.250 I mean, I literally copied and pasted it. 01:16:20.250 --> 01:16:21.510 And that's kind of a good rule of thumb. 01:16:21.510 --> 01:16:24.690 If you, in the future, start finding yourself copying and pasting code 01:16:24.690 --> 01:16:27.570 within the same program, you're probably doing something wrong. 01:16:27.570 --> 01:16:30.100 There's a better way to design it even if it's correct. 01:16:30.100 --> 01:16:32.513 So this is clearly a candidate for a loop. 01:16:32.513 --> 01:16:34.180 So let me go ahead and actually do that. 01:16:34.180 --> 01:16:37.380 Let me just go ahead and remove all of this duplication. 01:16:37.380 --> 01:16:42.630 Let me give myself a variable called i, set it equal to 3. 01:16:42.630 --> 01:16:44.580 Let me go ahead and give myself a while loop 01:16:44.580 --> 01:16:47.550 and check that i is greater than 0. 01:16:47.550 --> 01:16:50.640 Inside of this loop, let me print out just "meow" once. 01:16:50.640 --> 01:16:54.060 But I'll reuse that code again and again because here I'm 01:16:54.060 --> 01:16:56.100 going to do i minus minus. 01:16:56.100 --> 01:16:59.820 So that's the exact same code, the tight version of it that we saw a moment ago. 01:16:59.820 --> 01:17:04.900 Let me go ahead and "make meow" again, ./meow, and it still works. 01:17:04.900 --> 01:17:06.270 Why is this version better? 01:17:06.270 --> 01:17:10.320 Because if you want the cat to meow five times, you change it in one place. 01:17:10.320 --> 01:17:15.630 If you want to make the cat a dog, you change the meow to a woof in one place, 01:17:15.630 --> 01:17:18.210 albeit changing the file name eventually, but changing it 01:17:18.210 --> 01:17:22.950 in one place, not worrying about changing it again and again and again. 01:17:22.950 --> 01:17:25.810 But there are other ways to do this. 01:17:25.810 --> 01:17:30.300 For instance, let me propose that. 01:17:30.300 --> 01:17:34.540 And actually, let's see, let me propose that instead of just doing it this way, 01:17:34.540 --> 01:17:36.870 just to be clear-- 01:17:36.870 --> 01:17:39.660 yeah, let's go ahead and propose that instead of doing this, 01:17:39.660 --> 01:17:41.670 we can actually count in different directions. 01:17:41.670 --> 01:17:44.820 I'm kind of forcing this idea of starting at 3, going down to 0. 01:17:44.820 --> 01:17:47.610 But when normal humans in this room, if you ever count something, 01:17:47.610 --> 01:17:49.530 you probably do 1, 2, 3, and done. 01:17:49.530 --> 01:17:51.640 Like, that's how we would count in the real world. 01:17:51.640 --> 01:17:54.480 Well, we can do that, too, here code-wise. 01:17:54.480 --> 01:17:56.670 We could initialize i to 1. 01:17:56.670 --> 01:18:00.870 We could check that i is less than or equal to 3. 01:18:00.870 --> 01:18:03.000 And we've not seen this syntax before, but there's 01:18:03.000 --> 01:18:06.060 no easy way on a typical keyboard to type a less than or equal sign 01:18:06.060 --> 01:18:07.020 like in a math book. 01:18:07.020 --> 01:18:11.100 So we use two characters, a less-than sign and then an equal sign 01:18:11.100 --> 01:18:11.940 back to back. 01:18:11.940 --> 01:18:13.620 And that means less than or equal to. 01:18:13.620 --> 01:18:18.030 And this is the same idea so long as I plus plus i inside of it 01:18:18.030 --> 01:18:22.080 because that'll start at 1, then 2, but it won't stop then. 01:18:22.080 --> 01:18:25.440 It will go up to until i is equal to 3. 01:18:25.440 --> 01:18:29.500 Once i becomes 4, then that Boolean expression isn't going to be true. 01:18:29.500 --> 01:18:32.430 So it stops after three "meow"s total. 01:18:32.430 --> 01:18:34.710 But there's another way, too, and this is probably 01:18:34.710 --> 01:18:37.560 the most conventional and the way you should do it 01:18:37.560 --> 01:18:39.360 even though it's just as correct. 01:18:39.360 --> 01:18:43.030 In CS, if you've seen already last week, we almost always start counting from 0. 01:18:43.030 --> 01:18:43.530 Why? 01:18:43.530 --> 01:18:46.380 Just because, so we're not wasting a pattern of bits. 01:18:46.380 --> 01:18:49.480 So generally when you start writing code that counts, 01:18:49.480 --> 01:18:52.770 you should, quote, unquote, "almost always" start at 0, 01:18:52.770 --> 01:18:56.070 count up to but not through the total you 01:18:56.070 --> 01:18:59.200 care about so you don't get one extra by accident. 01:18:59.200 --> 01:19:01.710 And so this would be the most conventional way 01:19:01.710 --> 01:19:04.090 of doing what we just described. 01:19:04.090 --> 01:19:05.130 But they're all correct. 01:19:05.130 --> 01:19:07.620 You can make an argument that all of them are equally good. 01:19:07.620 --> 01:19:10.740 This is what most people, quote, unquote, "would do." 01:19:10.740 --> 01:19:15.255 OK, other questions on this here syntax or logic? 01:19:18.440 --> 01:19:19.220 No? 01:19:19.220 --> 01:19:21.530 All right, how about-- 01:19:21.530 --> 01:19:23.120 we got some cookies on the horizon. 01:19:23.120 --> 01:19:26.240 But before we get there, let's meow a few more times, if we may. 01:19:26.240 --> 01:19:31.373 So how about doing a little bit differently versus the while loop. 01:19:31.373 --> 01:19:32.790 And I think we heard it over here. 01:19:32.790 --> 01:19:35.850 Turns out there's another type of loop altogether. 01:19:35.850 --> 01:19:37.850 So this one here. 01:19:37.850 --> 01:19:40.940 And this one, if you can believe it, is probably even more conventional 01:19:40.940 --> 01:19:41.940 than the other way. 01:19:41.940 --> 01:19:43.940 And this is going to be thematic in programming. 01:19:43.940 --> 01:19:46.463 There's rarely one way, one right way to do things. 01:19:46.463 --> 01:19:49.130 You're going to have bunches of different tools in your toolkit. 01:19:49.130 --> 01:19:52.213 And your code might look different from someone else's because each of you 01:19:52.213 --> 01:19:54.470 tends to reach for a different tool in that toolkit. 01:19:54.470 --> 01:19:55.650 And here's another tool-- 01:19:55.650 --> 01:19:57.350 and as you proposed earlier-- 01:19:57.350 --> 01:19:58.370 a for loop. 01:19:58.370 --> 01:20:02.960 A for loop is just another way of achieving the exact same idea 01:20:02.960 --> 01:20:04.800 using slightly different syntax. 01:20:04.800 --> 01:20:08.360 And it's appealing, frankly in general, because it's a little more succinct. 01:20:08.360 --> 01:20:11.540 It just saves some keystrokes even though you have to memorize 01:20:11.540 --> 01:20:12.980 the order in which it works. 01:20:12.980 --> 01:20:18.628 This code is identical to this code here functionally. 01:20:18.628 --> 01:20:20.670 But aesthetically, of course, it looks different. 01:20:20.670 --> 01:20:21.630 How does it work? 01:20:21.630 --> 01:20:24.330 In a for loop, notice that in the parentheses 01:20:24.330 --> 01:20:26.790 is not a single simple Boolean expression. 01:20:26.790 --> 01:20:28.480 There are three things. 01:20:28.480 --> 01:20:33.060 One, before a semicolon, is a place to initialize a variable 01:20:33.060 --> 01:20:34.710 to do your counting typically. 01:20:34.710 --> 01:20:36.617 Second is the Boolean expression. 01:20:36.617 --> 01:20:37.450 So it's still there. 01:20:37.450 --> 01:20:40.242 It's just surrounded on the left and the right by two other things. 01:20:40.242 --> 01:20:41.610 Lastly is the update. 01:20:41.610 --> 01:20:45.917 What do you want to do at the end of every loop through this block of code? 01:20:45.917 --> 01:20:48.250 So you can probably imagine where we're going with this. 01:20:48.250 --> 01:20:49.300 How does this work? 01:20:49.300 --> 01:20:51.570 The first thing that happens is that a variable 01:20:51.570 --> 01:20:54.360 called i is defined and initialized to the value of 0. 01:20:54.360 --> 01:20:56.400 That happens once and only once. 01:20:56.400 --> 01:20:58.020 Then we check the condition. 01:20:58.020 --> 01:21:00.570 Is 0 less than 3? 01:21:00.570 --> 01:21:01.470 Obviously yes. 01:21:01.470 --> 01:21:03.690 So now we don't do the plus plus yet. 01:21:03.690 --> 01:21:04.810 We go into the loop. 01:21:04.810 --> 01:21:07.352 And this is where the for loop's a little confusing at first. 01:21:07.352 --> 01:21:08.460 We print out "meow." 01:21:08.460 --> 01:21:09.540 Then what happens? 01:21:09.540 --> 01:21:10.480 There's no more lines. 01:21:10.480 --> 01:21:14.740 So we go back to the for loop, and we increment i at that point. 01:21:14.740 --> 01:21:16.200 So now i is 1. 01:21:16.200 --> 01:21:19.290 Then we check the condition. i is less than 3? 01:21:19.290 --> 01:21:20.640 Yes, because 1 is less than 3. 01:21:20.640 --> 01:21:23.040 We go back into the loop and print "meow." 01:21:23.040 --> 01:21:26.250 Now we go back to the plus plus, so i is now 2. 01:21:26.250 --> 01:21:27.390 We check the condition. 01:21:27.390 --> 01:21:28.890 2 is less than 3 obviously. 01:21:28.890 --> 01:21:31.200 So we go back into the loop and print "meow." 01:21:31.200 --> 01:21:34.590 Then we do the increment. i is now 3. 01:21:34.590 --> 01:21:37.380 Is 3 less than 3? 01:21:37.380 --> 01:21:41.070 No, so we exit the loop, and we're done, or we keep 01:21:41.070 --> 01:21:42.960 going down here if there's more code. 01:21:42.960 --> 01:21:45.240 But how many times did I say "meow?" 01:21:45.240 --> 01:21:52.280 1, 2, 3 total, when my hand was 0, 1, and 2. 01:21:52.280 --> 01:21:54.410 Questions on this alternative syntax? 01:21:54.410 --> 01:21:56.540 It takes some getting used to, but most people 01:21:56.540 --> 01:21:58.910 would write loops using a for loop, I would say. 01:21:58.910 --> 01:22:02.150 STUDENT: Could you now in the curly braces, use just one line of code? 01:22:02.150 --> 01:22:02.870 DAVID MALAN: Yes. 01:22:02.870 --> 01:22:05.540 If you really want to be cool and save syntax, 01:22:05.540 --> 01:22:11.390 yes, it is correct and common to eliminate the curly braces if you only 01:22:11.390 --> 01:22:13.400 have one line of code therein. 01:22:13.400 --> 01:22:16.150 We in class will always put the curly braces there 01:22:16.150 --> 01:22:19.400 because this is the kind of thing where, if you get forgetful, you go in later 01:22:19.400 --> 01:22:20.360 and add a second line. 01:22:20.360 --> 01:22:22.360 Like, darn it, like you forgot the curly braces, 01:22:22.360 --> 01:22:24.150 things will not work as expected. 01:22:24.150 --> 01:22:27.950 So in general, use the curly braces, but you do not have to strictly. 01:22:27.950 --> 01:22:30.000 Other questions on 6? 01:22:30.000 --> 01:22:30.500 Yes? 01:22:30.500 --> 01:22:33.665 STUDENT: [INAUDIBLE] 01:22:33.665 --> 01:22:35.290 DAVID MALAN: Can be used without, what? 01:22:35.290 --> 01:22:37.168 STUDENT: [INAUDIBLE] 01:22:37.168 --> 01:22:39.460 DAVID MALAN: Oh, could you do it without the condition? 01:22:39.460 --> 01:22:43.570 Yes, there are very fancy things you can do that we won't focus on today. 01:22:43.570 --> 01:22:48.160 But yes, if you want to get rid of the condition, you could get rid of this 01:22:48.160 --> 01:22:48.820 here. 01:22:48.820 --> 01:22:51.370 And that would actually make the loop go forever, 01:22:51.370 --> 01:22:53.290 which may be a good thing if it's like a clock 01:22:53.290 --> 01:22:57.010 that you want to tick forever, but often not a good thing in code. 01:22:57.010 --> 01:22:58.600 Good question, though. 01:22:58.600 --> 01:23:03.023 All right, so beyond that, let's just go ahead and put this into context. 01:23:03.023 --> 01:23:04.940 Just in case it helps you to think about this, 01:23:04.940 --> 01:23:07.360 this is just another flow chart, if you're 01:23:07.360 --> 01:23:09.520 more of a visual thinker, that represents 01:23:09.520 --> 01:23:11.590 what it is this loop is now doing. 01:23:11.590 --> 01:23:14.630 Previously, all of our arrows went from top to bottom and stopped. 01:23:14.630 --> 01:23:16.960 But now there's an arrow going back, up, and around 01:23:16.960 --> 01:23:18.740 because of this loop, this cycle. 01:23:18.740 --> 01:23:21.550 So when we start this program, we set i equal to 0. 01:23:21.550 --> 01:23:23.920 We then check, is i less than 3? 01:23:23.920 --> 01:23:25.990 Obviously it is, so we print "meow." 01:23:25.990 --> 01:23:29.860 We increment i, and then we go back to that same condition. 01:23:29.860 --> 01:23:31.930 We check the condition. 01:23:31.930 --> 01:23:33.040 We print "meow." 01:23:33.040 --> 01:23:36.190 i plus plus, go back, go back. 01:23:36.190 --> 01:23:40.440 Now, if i equals 3, 3 is not less than 3, so the answer is false. 01:23:40.440 --> 01:23:41.248 And we stop. 01:23:41.248 --> 01:23:43.040 So again, it's just another way of thinking 01:23:43.040 --> 01:23:46.460 about how the code in Scratch, how the code in C 01:23:46.460 --> 01:23:50.660 might alternatively work in each of these contexts. 01:23:50.660 --> 01:23:53.750 But there's this one other puzzle piece in Scratch, 01:23:53.750 --> 01:23:55.700 recall, that's not the repeat block, which 01:23:55.700 --> 01:23:59.210 is for finite numbers of repetitions, but forever. 01:23:59.210 --> 01:24:02.240 And in C, there is a way to do this, but it's a little weird looking. 01:24:02.240 --> 01:24:03.860 There's no forever keyword. 01:24:03.860 --> 01:24:08.300 But you can use the while loop or, as you inferred, 01:24:08.300 --> 01:24:12.000 you can actually use the for loop without a condition in the middle. 01:24:12.000 --> 01:24:14.720 So here, I can actually say this. 01:24:14.720 --> 01:24:17.690 If I want to do something forever, I want 01:24:17.690 --> 01:24:20.600 to make sure that the answer to my question, the Boolean expression, 01:24:20.600 --> 01:24:23.570 is always true, always true, always true, 01:24:23.570 --> 01:24:27.680 the easiest way to achieve that goal is just literally write "true" there 01:24:27.680 --> 01:24:29.670 because true is true no matter what. 01:24:29.670 --> 01:24:31.970 And it's a trick for making the loop forever 01:24:31.970 --> 01:24:33.740 go around and around, as you might if you 01:24:33.740 --> 01:24:36.740 want the cat to live forever and meow incessantly 01:24:36.740 --> 01:24:39.690 or if it is a clock that you want to tick forever or the like. 01:24:39.690 --> 01:24:44.720 So here, for instance, is how we might have a cat meow endlessly, 01:24:44.720 --> 01:24:47.420 using this so-called for loop instead. 01:24:47.420 --> 01:24:50.330 But recall that in Scratch, we also had this ability 01:24:50.330 --> 01:24:52.700 to create some of our own puzzle pieces. 01:24:52.700 --> 01:24:55.700 And this, too, is something that we're going to be able to do here in C. 01:24:55.700 --> 01:24:59.570 And let me propose that we do exactly that 01:24:59.570 --> 01:25:03.090 by introducing the C analog of this. 01:25:03.090 --> 01:25:08.023 So here, for instance, is, in Scratch, our definition 01:25:08.023 --> 01:25:10.190 of a function called meow whose sole purpose in life 01:25:10.190 --> 01:25:12.740 was to just play the sound "meow" until it's done. 01:25:12.740 --> 01:25:15.000 This is going to look a little weird at first. 01:25:15.000 --> 01:25:17.540 But you'll notice some similarities with main. 01:25:17.540 --> 01:25:21.230 So recall this thing I keep typing with main, int main(void), int main(void). 01:25:21.230 --> 01:25:25.080 That's just the "when green flag clicked" equivalent for today. 01:25:25.080 --> 01:25:28.940 But if you want to create your own puzzle piece or your own function in C, 01:25:28.940 --> 01:25:31.190 you, for now, literally do this. 01:25:31.190 --> 01:25:34.760 You say, void, the name of the function you want to create, and then 01:25:34.760 --> 01:25:35.870 void in parentheses. 01:25:35.870 --> 01:25:39.920 And technically what this means is that this function has no return value. 01:25:39.920 --> 01:25:42.800 It doesn't hand you anything back like get_string or get_int. 01:25:42.800 --> 01:25:45.500 And the "void" in parentheses means it takes no inputs. 01:25:45.500 --> 01:25:46.437 It only meows. 01:25:46.437 --> 01:25:48.020 You don't have to tell it how to meow. 01:25:48.020 --> 01:25:49.220 It's just going to meow. 01:25:49.220 --> 01:25:51.740 So no arguments, so to speak. 01:25:51.740 --> 01:25:53.990 This literally just prints out "meow." 01:25:53.990 --> 01:25:56.990 But what this does for me is it abstracts away the idea of meowing. 01:25:56.990 --> 01:25:59.360 I don't need to know how to use printf or that you're 01:25:59.360 --> 01:26:01.370 using printf to make the cat meow. 01:26:01.370 --> 01:26:05.300 I now have a function in life called meow because in Scratch, recall, 01:26:05.300 --> 01:26:06.470 I used it like this. 01:26:06.470 --> 01:26:10.640 When the green flag is clicked, I could repeat three times this new custom 01:26:10.640 --> 01:26:11.450 puzzle piece. 01:26:11.450 --> 01:26:13.940 But in C, I could now do this. 01:26:13.940 --> 01:26:18.920 In my main program, I can use a for loop just like we saw a moment ago, 01:26:18.920 --> 01:26:20.480 copy/pasted from earlier. 01:26:20.480 --> 01:26:25.310 But now I can call my own C function called meow. 01:26:25.310 --> 01:26:28.040 And let me go ahead now and do this. 01:26:28.040 --> 01:26:33.560 If I go over to my C code here, back in VS Code, let me go ahead 01:26:33.560 --> 01:26:35.480 and delete everything inside main. 01:26:35.480 --> 01:26:42.260 Let me go ahead and do for int i equals 0, i is less than 3, i++. 01:26:42.260 --> 01:26:45.980 Inside of my curly braces, let me go ahead and say "meow." 01:26:45.980 --> 01:26:49.460 But I now need this meow function to exist because if I 01:26:49.460 --> 01:26:52.280 do "make meow" again, notice error. 01:26:52.280 --> 01:26:56.660 "Implicit declaration of function meow is invalid in C99"-- 01:26:56.660 --> 01:26:59.970 the 1999 version of C. What does that mean? 01:26:59.970 --> 01:27:02.510 Well, it doesn't know what the meow function is. 01:27:02.510 --> 01:27:04.820 And the meow function is not in CS50.h. 01:27:04.820 --> 01:27:06.710 It's not in stdio.h. 01:27:06.710 --> 01:27:08.070 I have to create it. 01:27:08.070 --> 01:27:12.020 So let me type out or really copy/paste what I had on the screen a moment ago-- 01:27:12.020 --> 01:27:13.370 "void meow meow"-- 01:27:13.370 --> 01:27:20.210 [CHUCKLES] "void meow(void)" printf, quote, unquote, "meow," close quote, 01:27:20.210 --> 01:27:21.440 semicolon. 01:27:21.440 --> 01:27:24.350 But here, too, let me scooch this down a bit 01:27:24.350 --> 01:27:26.010 so you can see all the code at once. 01:27:26.010 --> 01:27:27.620 Let me now do make meow. 01:27:27.620 --> 01:27:30.860 And unfortunately, I still have an error. 01:27:30.860 --> 01:27:36.680 If I scroll up, still on line 7 of meow.c, 01:27:36.680 --> 01:27:42.300 my compiler thinks that meow is invalid, that it does not exist. 01:27:42.300 --> 01:27:44.150 This too is a common mistake. 01:27:44.150 --> 01:27:50.240 And as simple as this code might be in spirit, where did I screw up? 01:27:50.240 --> 01:27:51.655 Yeah, in the middle. 01:27:51.655 --> 01:27:54.530 STUDENT: You need to define the function like above where you use it. 01:27:54.530 --> 01:27:57.238 DAVID MALAN: Yeah, I need to define the function before I use it. 01:27:57.238 --> 01:27:59.120 So again, C is going to take you literally. 01:27:59.120 --> 01:28:03.230 If you try to call meow on line 7, you better not define it on line 11. 01:28:03.230 --> 01:28:05.120 You better define it higher up. 01:28:05.120 --> 01:28:09.290 So the simplest fix is going to be just to do this. 01:28:09.290 --> 01:28:10.610 Let me clear my terminal. 01:28:10.610 --> 01:28:13.970 Let me highlight and just delete the meow function. 01:28:13.970 --> 01:28:15.770 And let me just paste it up here. 01:28:15.770 --> 01:28:18.000 And this will actually solve the problem. 01:28:18.000 --> 01:28:19.950 Make meow now works. 01:28:19.950 --> 01:28:22.550 And if I do ./meow, that, too, works. 01:28:22.550 --> 01:28:26.090 But this isn't really the best solution because if your solution is constantly, 01:28:26.090 --> 01:28:28.798 oh, well, just put it up there, put it up there, put it up there, 01:28:28.798 --> 01:28:30.530 I bet we could contrive a situation where 01:28:30.530 --> 01:28:32.450 one function needs to be above the other, 01:28:32.450 --> 01:28:33.620 but it needs to be above the other. 01:28:33.620 --> 01:28:35.495 And that's just not going to work in general. 01:28:35.495 --> 01:28:40.110 And more importantly, it just pushes main lower and lower and lower 01:28:40.110 --> 01:28:40.712 in your file. 01:28:40.712 --> 01:28:42.420 But the whole point of your main function 01:28:42.420 --> 01:28:43.890 is like, that's the entry point. 01:28:43.890 --> 01:28:46.540 That is what happens when the green flag is clicked. 01:28:46.540 --> 01:28:50.340 And so just in terms of user conventions, it's just useful for main 01:28:50.340 --> 01:28:53.400 to always be at the top of a file because then you can find it fast. 01:28:53.400 --> 01:28:56.910 Your friends can, your TFs can find it quickly if it's at the top. 01:28:56.910 --> 01:29:01.290 So the other solution here would be to leave meow at the bottom 01:29:01.290 --> 01:29:02.880 and leave main at the top. 01:29:02.880 --> 01:29:07.080 But this is the only time, if I may, that copy/paste is OK. 01:29:07.080 --> 01:29:11.560 What I've highlighted here in line 11 is what's called the function's prototype. 01:29:11.560 --> 01:29:16.860 It is enough information to give you the return type, the name of the function, 01:29:16.860 --> 01:29:18.630 and the return value-- 01:29:18.630 --> 01:29:20.820 and any arguments. 01:29:20.820 --> 01:29:25.590 And so if you just copy/paste that one line and end it with a semicolon 01:29:25.590 --> 01:29:29.850 up there, that's enough of a hint to the compiler 01:29:29.850 --> 01:29:32.370 that, OK, it doesn't exist yet, but it will. 01:29:32.370 --> 01:29:34.650 And it will look like that. 01:29:34.650 --> 01:29:37.110 That's the only time it's OK to copy/paste 01:29:37.110 --> 01:29:39.630 the very first line of a function you've written 01:29:39.630 --> 01:29:42.000 to the top of the file with a semicolon so 01:29:42.000 --> 01:29:45.270 that you can make the compiler happy. 01:29:45.270 --> 01:29:51.390 So if I do make meow now, still no errors. ./meow, and it now works. 01:29:51.390 --> 01:29:55.800 But let me add one final feature, coming back to Scratch here. 01:29:55.800 --> 01:29:57.480 And then it's time for a snack. 01:29:57.480 --> 01:30:01.920 So here, recall, was sort of the last fancy thing we did in Scratch, where 01:30:01.920 --> 01:30:04.380 we created not only our own custom puzzle piece, 01:30:04.380 --> 01:30:08.370 but it took an input so that we didn't need to keep using the loop ourself. 01:30:08.370 --> 01:30:11.250 We could just let the meow function be told how many times 01:30:11.250 --> 01:30:12.570 do you want the cat to meow. 01:30:12.570 --> 01:30:16.980 So in C, we don't have to make that many changes except this. 01:30:16.980 --> 01:30:21.670 We change the prototype to take an argument inside of parentheses. 01:30:21.670 --> 01:30:23.190 And this is the syntax for that. 01:30:23.190 --> 01:30:26.850 If you want your own function in C to take one or more arguments, 01:30:26.850 --> 01:30:30.330 you give the arguments a name, n, or whatever you want to call it. 01:30:30.330 --> 01:30:33.060 But you have to tell C what the type of that input is. 01:30:33.060 --> 01:30:34.650 So it's an int n. 01:30:34.650 --> 01:30:36.240 So it knows it's a number. 01:30:36.240 --> 01:30:38.290 And then you can just use n in your program. 01:30:38.290 --> 01:30:41.460 So instead of hard coding, typing manually the number 3, 01:30:41.460 --> 01:30:43.090 I'm just using n here. 01:30:43.090 --> 01:30:46.590 So this is equivalent to what I did with Scratch, by just dragging and dropping 01:30:46.590 --> 01:30:48.720 the n variable there. 01:30:48.720 --> 01:30:51.240 And then "meow" will get printed that many times. 01:30:51.240 --> 01:30:54.780 If I want to then use this-- notice, this is the last version of the cat 01:30:54.780 --> 01:30:58.330 that we did last week-- you just say "meow" this many times. 01:30:58.330 --> 01:31:03.060 So in C, this is where now the code gets very succinct 01:31:03.060 --> 01:31:06.653 because all the main part of the program does is meow three times. 01:31:06.653 --> 01:31:08.070 So this, again, is an abstraction. 01:31:08.070 --> 01:31:11.730 I don't need to know, care, or remember how meow is implemented. 01:31:11.730 --> 01:31:16.230 I just need to know what its return value, its name, and any arguments 01:31:16.230 --> 01:31:17.560 thereto are. 01:31:17.560 --> 01:31:21.600 So if I make this change, I think we can get the cat 01:31:21.600 --> 01:31:23.490 to meow any number of times. 01:31:23.490 --> 01:31:25.920 Let me go back over to my C code here. 01:31:25.920 --> 01:31:31.710 Let me go back into the file and change "void" here to be int n, 01:31:31.710 --> 01:31:33.390 where n just means number. 01:31:33.390 --> 01:31:36.960 I could use i, but n tends to be a quantity instead of a counter. 01:31:36.960 --> 01:31:40.320 I then, inside of this function, am going to do a for loop-- 01:31:40.320 --> 01:31:43.620 for int i get 0; i less than n-- 01:31:43.620 --> 01:31:46.110 instead of 3-- i++. 01:31:46.110 --> 01:31:49.050 And then inside of here, I'll paste that "meow" again. 01:31:49.050 --> 01:31:52.950 I need to change my prototype to be identical, so another copy/paste, 01:31:52.950 --> 01:31:54.240 or just manually edit it. 01:31:54.240 --> 01:31:56.940 But now notice what's cool about main, is 01:31:56.940 --> 01:32:00.090 that now I can meow maybe three times. 01:32:00.090 --> 01:32:04.260 Make meow, Enter, ./meow. 01:32:04.260 --> 01:32:09.870 OK, or if I really want to be cool, I can change this to 30,000 times. 01:32:09.870 --> 01:32:11.940 Go back here, make meow. 01:32:11.940 --> 01:32:16.500 Increase the size of my terminal window for a dramatic pre-break flourish. 01:32:16.500 --> 01:32:18.390 And there are 30-- that was a fast cat. 01:32:18.390 --> 01:32:19.950 There are 30,000 meows. 01:32:19.950 --> 01:32:22.990 I think now let's go ahead and take-- that's a lot-- a 10-minute break. 01:32:22.990 --> 01:32:23.940 We'll see you in 10. 01:32:23.940 --> 01:32:26.400 Cookies are now served outside. 01:32:26.400 --> 01:32:29.490 All right, so we are back. 01:32:29.490 --> 01:32:31.920 And I realize this has been a lot so far, right? 01:32:31.920 --> 01:32:33.630 So there's a lot of new syntax. 01:32:33.630 --> 01:32:36.100 There's a lot of translation of Scratch over to C. 01:32:36.100 --> 01:32:39.790 But among the goals of having spent last week in Scratch 01:32:39.790 --> 01:32:44.830 and having spent problems at 0 in Scratch is that none of today's ideas 01:32:44.830 --> 01:32:46.430 are really all that new. 01:32:46.430 --> 01:32:49.780 It's just a lot of syntax that will get more comfortable and more 01:32:49.780 --> 01:32:52.480 in your muscle memory as time passes. 01:32:52.480 --> 01:32:56.170 Up until now, though, we've focused largely on these side effects, 01:32:56.170 --> 01:32:58.100 like things happening on the screen. 01:32:58.100 --> 01:33:01.450 And that was akin to the speech bubble appearing in the world of Scratch. 01:33:01.450 --> 01:33:05.170 But let's focus for just a bit-- before we then explore things 01:33:05.170 --> 01:33:07.930 we can't do very well in code-- on return 01:33:07.930 --> 01:33:10.870 values instead in C. We've seen them already. 01:33:10.870 --> 01:33:12.880 Like, get_string returns a value. 01:33:12.880 --> 01:33:16.400 Get_int returns a value, a string and an int respectively. 01:33:16.400 --> 01:33:19.000 But what if we want to make our own functions that don't just 01:33:19.000 --> 01:33:21.910 meow and visually have this side effect of meowing on the screen 01:33:21.910 --> 01:33:24.310 but actually hand us back some value? 01:33:24.310 --> 01:33:26.950 Well, I bet we can do this in C, as well. 01:33:26.950 --> 01:33:30.488 Well, let me propose that to go that route-- 01:33:30.488 --> 01:33:31.780 let me go back to VS Code here. 01:33:31.780 --> 01:33:33.940 And let's make our very simple calculator 01:33:33.940 --> 01:33:35.668 that just adds some numbers together. 01:33:35.668 --> 01:33:37.460 But the same calculator, we'll soon see, is 01:33:37.460 --> 01:33:40.790 going to get us into trouble if you don't understand what the computer is 01:33:40.790 --> 01:33:42.770 doing underneath the hood. 01:33:42.770 --> 01:33:47.690 Let me go ahead and run code of, say, calculator.c. 01:33:47.690 --> 01:33:49.910 And in here, let me go ahead and give myself 01:33:49.910 --> 01:33:56.660 access to the CS50 library with CS50.h, the stdio.h library with stdio.h, 01:33:56.660 --> 01:34:01.370 int main(void), which, again, we'll just take for granted today that we have 01:34:01.370 --> 01:34:03.290 to include atop any of these programs. 01:34:03.290 --> 01:34:06.420 And let's just add two numbers together-- super simple calculator. 01:34:06.420 --> 01:34:08.420 So it gives me a variable called x. 01:34:08.420 --> 01:34:10.640 Assign it the return value of get_int. 01:34:10.640 --> 01:34:13.520 And I'll ask the user to give us x. 01:34:13.520 --> 01:34:15.530 Give me another variable called y. 01:34:15.530 --> 01:34:18.470 Assign it the return value of get_int again. 01:34:18.470 --> 01:34:20.900 But this time, ask the user for y. 01:34:20.900 --> 01:34:26.600 And then, lastly, let's just go ahead and print out the value of x plus y. 01:34:26.600 --> 01:34:29.540 But I don't think I can get away with something 01:34:29.540 --> 01:34:33.230 like this, x plus y semicolon, because if I 01:34:33.230 --> 01:34:36.080 do this, based on what we've seen before, 01:34:36.080 --> 01:34:37.790 what's actually going to get printed out? 01:34:37.790 --> 01:34:38.390 STUDENT: x plus y. 01:34:38.390 --> 01:34:40.250 DAVID MALAN: Right, literally like x plus y. 01:34:40.250 --> 01:34:43.700 So I think this is where I need the F in "printf" for formatting. 01:34:43.700 --> 01:34:48.470 What I think I really want to do is print out the value of some placeholder 01:34:48.470 --> 01:34:51.140 because, what do I want to substitute for percent i 01:34:51.140 --> 01:34:55.280 maybe as a second argument to printf intuitively? 01:34:55.280 --> 01:34:56.990 Maybe just x plus y. 01:34:56.990 --> 01:34:59.630 So indeed, I can get away with this because it turns out in C, 01:34:59.630 --> 01:35:03.290 there's a bunch of arithmetic operators, all of the ones that you might expect, 01:35:03.290 --> 01:35:07.010 including addition, subtraction, multiplication, division, 01:35:07.010 --> 01:35:09.570 and even this one, the so-called modulo operator, 01:35:09.570 --> 01:35:12.470 which generally gives us the ability to calculate a remainder when 01:35:12.470 --> 01:35:13.977 you divide one number by another. 01:35:13.977 --> 01:35:15.560 But I'll keep it simple with addition. 01:35:15.560 --> 01:35:20.480 And indeed, with printf, if I want to print out the value of x plus y, 01:35:20.480 --> 01:35:21.480 I can do that. 01:35:21.480 --> 01:35:25.940 But I have to tell printf what kind of value to expect, an integer, 01:35:25.940 --> 01:35:29.010 thus the percent i instead of %s for string. 01:35:29.010 --> 01:35:30.630 And I think this should do the job. 01:35:30.630 --> 01:35:32.090 So let me go back to my terminal. 01:35:32.090 --> 01:35:34.370 Make calculator, Enter. 01:35:34.370 --> 01:35:37.430 All is well so far. ./calculator, and let's keep it simple-- 01:35:37.430 --> 01:35:39.230 1 for x, 2 for y. 01:35:39.230 --> 01:35:42.140 And indeed, I get 3 as the output. 01:35:42.140 --> 01:35:43.170 It's not very dynamic. 01:35:43.170 --> 01:35:46.170 It can't do a subtraction or multiplication or much more. 01:35:46.170 --> 01:35:49.370 But it does at least do those kinds of calculations. 01:35:49.370 --> 01:35:54.085 But let me propose now that we maybe make a reusable addition 01:35:54.085 --> 01:35:56.960 function, right, because addition is something I'm going to do a lot. 01:35:56.960 --> 01:35:59.750 And maybe it should be abstracted away with a function 01:35:59.750 --> 01:36:02.310 just like meowing was abstracted away a moment ago. 01:36:02.310 --> 01:36:05.060 So let me go ahead and instead of doing this, 01:36:05.060 --> 01:36:08.360 let me go ahead and give myself a function called add, 01:36:08.360 --> 01:36:11.870 but instead of last time where I had a meow function, 01:36:11.870 --> 01:36:14.420 I'm obviously going to call this "add" instead. 01:36:14.420 --> 01:36:19.040 And instead of last time, taking in no arguments, 01:36:19.040 --> 01:36:21.600 I think I want add to work a little differently. 01:36:21.600 --> 01:36:24.920 I don't want add necessarily to take an argument yet, 01:36:24.920 --> 01:36:27.320 but I do want add to return some type of value. 01:36:27.320 --> 01:36:31.347 And just intuitively, what type of value should an addition function return? 01:36:31.347 --> 01:36:32.180 STUDENT: An integer. 01:36:32.180 --> 01:36:33.680 DAVID MALAN: An integer, so an int. 01:36:33.680 --> 01:36:37.250 So I'm going to change void, which means the absence of a return value-- 01:36:37.250 --> 01:36:39.860 nothing's coming back-- to literally "int." 01:36:39.860 --> 01:36:43.250 But I'm not going to change the thing inside parentheses yet. 01:36:43.250 --> 01:36:47.090 I'm going to go ahead and copy my prototype up here. 01:36:47.090 --> 01:36:51.590 And I'm going to make this change, return x plus y. 01:36:51.590 --> 01:36:57.438 And then here, instead of printing out x plus y, let's go ahead and do this. 01:36:57.438 --> 01:36:59.480 Let me give myself a third variable just for now. 01:36:59.480 --> 01:37:02.540 z equals the return value of this brand-new 01:37:02.540 --> 01:37:05.660 add function that's going to add x plus y for me. 01:37:05.660 --> 01:37:07.520 And then let me print out the value of z. 01:37:07.520 --> 01:37:10.860 Instead of x plus y, I'm outsourcing now to this add function 01:37:10.860 --> 01:37:14.690 so it will do the addition of x plus y. 01:37:14.690 --> 01:37:19.160 So similar in spirit to meowing, but the return values, I claim, 01:37:19.160 --> 01:37:20.400 are about to create an issue. 01:37:20.400 --> 01:37:22.640 So let me make calculator again. 01:37:22.640 --> 01:37:24.270 And there's definitely some errors. 01:37:24.270 --> 01:37:28.580 So here we have, "use of undeclared identifier x." 01:37:28.580 --> 01:37:30.390 And that's on line 17. 01:37:30.390 --> 01:37:32.300 So that's pretty far down in the file. 01:37:32.300 --> 01:37:37.350 So specifically, my compiler does not like my use of x on line 17. 01:37:37.350 --> 01:37:42.510 But wait a minute, x is clearly defined on line 8. 01:37:42.510 --> 01:37:46.555 What intuitively might explain this issue 01:37:46.555 --> 01:37:48.180 even if you've never programmed before? 01:37:48.180 --> 01:37:48.750 Yeah? 01:37:48.750 --> 01:37:52.245 STUDENT: Well, because x and y are defined in the main function, not 01:37:52.245 --> 01:37:53.277 the add function. 01:37:53.277 --> 01:37:56.110 DAVID MALAN: Yeah, because x and y are defined in the main function, 01:37:56.110 --> 01:37:57.412 not in the add function. 01:37:57.412 --> 01:37:59.620 So the term of art here that we're about to introduce 01:37:59.620 --> 01:38:00.820 is something called "scope." 01:38:00.820 --> 01:38:05.920 So "scope" just refers to the context in which variables exist-- 01:38:05.920 --> 01:38:08.030 the context in which variables exist. 01:38:08.030 --> 01:38:09.580 So by that, I mean this. 01:38:09.580 --> 01:38:11.200 On line 8, I've declared x. 01:38:11.200 --> 01:38:12.595 On line y, I've declared-- 01:38:12.595 --> 01:38:14.830 [CHUCKLES] on line 9, I've declared y. 01:38:14.830 --> 01:38:18.100 But the catch is-- and here's where the curly braces are helpful-- 01:38:18.100 --> 01:38:25.000 those variables only exist in the context of the outer curly braces 01:38:25.000 --> 01:38:26.950 that are nearest to them, like this. 01:38:26.950 --> 01:38:31.690 So I can use x and y on lines 10, 11, 12, and even up to 13, 01:38:31.690 --> 01:38:33.170 but not thereafter. 01:38:33.170 --> 01:38:35.920 So I certainly can't use x down here on line 7. 01:38:35.920 --> 01:38:39.400 But this is a problem, because if add's purpose in life is to add x and y 01:38:39.400 --> 01:38:43.540 but add can't access x plus y, well, we have an issue of scope. 01:38:43.540 --> 01:38:46.840 Like, x and y are not in scope for this add function. 01:38:46.840 --> 01:38:50.650 But that's OK because remember that every function we've seen thus far 01:38:50.650 --> 01:38:53.790 can have maybe a return value or a side effect, 01:38:53.790 --> 01:38:59.220 but it can also take 0 or one or two or more inputs, known as arguments. 01:38:59.220 --> 01:39:00.740 So what if I instead do this? 01:39:00.740 --> 01:39:02.460 Let me clear my terminal window. 01:39:02.460 --> 01:39:05.630 And let me update add to not take nothing 01:39:05.630 --> 01:39:07.550 as input but maybe two integers. 01:39:07.550 --> 01:39:10.130 And I'll call them arbitrarily a and b. 01:39:10.130 --> 01:39:12.920 But I have to tell the compiler what type of arguments 01:39:12.920 --> 01:39:16.040 they are-- two integers, one after the other. 01:39:16.040 --> 01:39:18.720 And now what I can do is this. 01:39:18.720 --> 01:39:21.380 Let me change this up here, too-- int a, int b-- 01:39:21.380 --> 01:39:23.840 just so that the prototype is exactly the same. 01:39:23.840 --> 01:39:27.800 And the only purpose of this prototype is just to avoid the previous error, 01:39:27.800 --> 01:39:30.440 where the compiler didn't realize add was going to exist 01:39:30.440 --> 01:39:32.790 because it came later in the file. 01:39:32.790 --> 01:39:37.580 So here on line 11 now, if I want to add two values, x and y, 01:39:37.580 --> 01:39:39.650 this is now the syntax. 01:39:39.650 --> 01:39:42.530 We saw syntax in Scratch for passing in inputs 01:39:42.530 --> 01:39:44.360 to tell it how many times to meow. 01:39:44.360 --> 01:39:50.160 So this is just telling add what two numbers to add together. 01:39:50.160 --> 01:39:54.787 So now I have to change this to a plus b, for reasons we'll soon see. 01:39:54.787 --> 01:39:56.120 And let me see if this is right. 01:39:56.120 --> 01:39:57.060 Make calculator. 01:39:57.060 --> 01:39:59.000 So far so good. ./calculator. 01:39:59.000 --> 01:40:02.120 Let's do 1 and 2 for x and y respectively. 01:40:02.120 --> 01:40:05.630 And hopefully we should, again, see 3. 01:40:05.630 --> 01:40:07.020 Now, what's going on? 01:40:07.020 --> 01:40:11.990 So here, again, if I zoom in on my add function, this "int" here on the left, 01:40:11.990 --> 01:40:15.476 on line 15, means what about add? 01:40:15.476 --> 01:40:16.700 STUDENT: [INAUDIBLE] 01:40:16.700 --> 01:40:18.980 DAVID MALAN: This means that it has a return value, that it's an int. 01:40:18.980 --> 01:40:21.563 So it's going to hand me back, metaphorically, a slip of paper 01:40:21.563 --> 01:40:24.080 with an answer on it that is of type integer. 01:40:24.080 --> 01:40:25.400 It's not a word, like my name. 01:40:25.400 --> 01:40:26.750 It's a number instead. 01:40:26.750 --> 01:40:33.290 These mentions of int here and here are inside the parentheses, which means 01:40:33.290 --> 01:40:36.390 this function, add, takes two inputs. 01:40:36.390 --> 01:40:37.460 The first is an int. 01:40:37.460 --> 01:40:38.540 The second is an int. 01:40:38.540 --> 01:40:42.930 And just so we have something to call them, I call them a and b respectively. 01:40:42.930 --> 01:40:49.010 So what happens essentially when I call the add function now on line 11, 01:40:49.010 --> 01:40:51.050 I'm kind of passing in x. 01:40:51.050 --> 01:40:52.610 I'm passing in y. 01:40:52.610 --> 01:40:56.210 But the add function is going to think of them as a and b respectively. 01:40:56.210 --> 01:40:57.770 It could call them anything I want. 01:40:57.770 --> 01:41:00.710 I could change this to the word "first" and "second." 01:41:00.710 --> 01:41:03.500 And then I could literally change this to "first + second." 01:41:03.500 --> 01:41:07.220 Those are perfectly acceptable as argument or variable names. 01:41:07.220 --> 01:41:08.210 But who really cares? 01:41:08.210 --> 01:41:12.500 Like, a and b for such a simple function is perfectly reasonable, too. 01:41:12.500 --> 01:41:14.540 Technically, if your mind is going there, 01:41:14.540 --> 01:41:18.365 I could even call them the exact same thing. 01:41:18.365 --> 01:41:21.240 But let me propose for today, certainly don't do that because it just 01:41:21.240 --> 01:41:24.210 confuses things if you've got x's and y's here, x's and y's here, 01:41:24.210 --> 01:41:25.470 but they're clearly different. 01:41:25.470 --> 01:41:26.310 Just don't do that. 01:41:26.310 --> 01:41:29.640 Try to come up with different variables just to keep yourself sane. 01:41:29.640 --> 01:41:33.930 But here, I have a function that takes now two integers, a and b respectively. 01:41:33.930 --> 01:41:37.920 It just returns the sum of them so that I can now store the return 01:41:37.920 --> 01:41:40.680 value of add in a variable called z. 01:41:40.680 --> 01:41:45.180 And then, quite simply, print it out. 01:41:45.180 --> 01:41:47.520 But there's one other thing I can do here. 01:41:47.520 --> 01:41:51.690 Now, if we think about design, even if you've never programmed before, 01:41:51.690 --> 01:41:55.350 do I really need the variable z? 01:41:55.350 --> 01:41:58.890 Because I'm defining it on line 11, and then I'm quickly using it on line 12, 01:41:58.890 --> 01:41:59.672 and that's it? 01:41:59.672 --> 01:42:01.380 Like, sometimes you don't need variables. 01:42:01.380 --> 01:42:03.213 And they might make your code more readable. 01:42:03.213 --> 01:42:06.840 But strictly speaking-- and this is just kind of like substitution in math-- 01:42:06.840 --> 01:42:10.980 if z is the same thing as "add (x, y)," well, let me go ahead 01:42:10.980 --> 01:42:12.870 and just delete line 11 altogether. 01:42:12.870 --> 01:42:14.520 Let me get rid of mention of z. 01:42:14.520 --> 01:42:16.800 You can actually get away with doing this. 01:42:16.800 --> 01:42:20.340 And much like the Join block in Scratch, where I kind of overlaid it 01:42:20.340 --> 01:42:24.390 on the Say block, kind of stacking them, you can stack functions in C, 01:42:24.390 --> 01:42:26.640 or nest them really, kind of mathematically. 01:42:26.640 --> 01:42:28.530 Honestly, it makes it a little harder to read 01:42:28.530 --> 01:42:31.320 because your mind has to dive in conceptually deeper and deeper 01:42:31.320 --> 01:42:33.010 into this second argument. 01:42:33.010 --> 01:42:35.310 But it's perfectly acceptable, too. 01:42:35.310 --> 01:42:38.100 And just to connect the dots to maybe something from high school, 01:42:38.100 --> 01:42:40.890 this is kind of analogous to a function in math class 01:42:40.890 --> 01:42:43.260 being like f of x, where f is some function name, 01:42:43.260 --> 01:42:45.700 x is some arbitrary input to that function. 01:42:45.700 --> 01:42:49.120 And when you start to put functions inside of functions 01:42:49.120 --> 01:42:51.570 so that the output of one becomes the input to the next, 01:42:51.570 --> 01:42:54.313 it's like using this syntax, f of g of x and so forth. 01:42:54.313 --> 01:42:56.230 If you've never seen that before, don't worry. 01:42:56.230 --> 01:42:59.730 But if you have, it's a way to connect some of these dots. 01:42:59.730 --> 01:43:02.880 Any questions, though, on just this idea of now 01:43:02.880 --> 01:43:05.580 having a function that doesn't just have a side effect 01:43:05.580 --> 01:43:10.500 but instead has a return value? 01:43:10.500 --> 01:43:11.790 Yeah, in back? 01:43:11.790 --> 01:43:14.031 STUDENT: In our declaration of main, why did we 01:43:14.031 --> 01:43:16.622 show it as returning an integer instead of void? 01:43:16.622 --> 01:43:19.080 DAVID MALAN: In our definition of main, why did I do, what? 01:43:19.080 --> 01:43:21.445 STUDENT: Why do we show it as returning an integer 01:43:21.445 --> 01:43:22.870 instead of returning as void? 01:43:22.870 --> 01:43:24.820 DAVID MALAN: Oh, a really good question that I was trying 01:43:24.820 --> 01:43:26.195 to sweep under the rug for today. 01:43:26.195 --> 01:43:28.240 But in every one of our programs thus far, 01:43:28.240 --> 01:43:31.330 I have indeed said "int main(void)." 01:43:31.330 --> 01:43:34.940 Technically speaking, whenever you write a program and it finishes running, 01:43:34.940 --> 01:43:37.750 it actually returns a value somewhat secretly. 01:43:37.750 --> 01:43:41.200 It returns the number 0 by convention, which means all is well. 01:43:41.200 --> 01:43:44.420 And it can return any other integer if something goes wrong. 01:43:44.420 --> 01:43:46.960 In fact, on your Mac, PC, or even phone, if you've ever 01:43:46.960 --> 01:43:50.030 gotten like a weird message on the screen, like something went wrong 01:43:50.030 --> 01:43:53.710 and it's like a weird numeric code, like error negative 129, or something 01:43:53.710 --> 01:43:57.340 arbitrary like that, that tends to mean that some program running 01:43:57.340 --> 01:44:01.660 on your Mac, PC, or phone had something go wrong with the main function. 01:44:01.660 --> 01:44:03.608 And that is the number that was returned. 01:44:03.608 --> 01:44:05.650 But that's more than we want to talk about today. 01:44:05.650 --> 01:44:07.060 But we'll come back to this. 01:44:07.060 --> 01:44:08.890 But main always returns a number. 01:44:08.890 --> 01:44:10.930 By default, it is 0. 01:44:10.930 --> 01:44:12.640 More on that soon. 01:44:12.640 --> 01:44:15.790 All right, so with that said, let's actually tease 01:44:15.790 --> 01:44:18.100 apart what it is we've been using underneath the hood 01:44:18.100 --> 01:44:21.743 here a little bit by returning to VS Code's interface itself. 01:44:21.743 --> 01:44:23.660 It turns out that all this time, even though I 01:44:23.660 --> 01:44:27.050 keep alluding to macOS and Windows, which like 99% of us 01:44:27.050 --> 01:44:29.540 are probably running on our laptops or desktops, 01:44:29.540 --> 01:44:32.390 there's actually other very popular operating systems in the world, 01:44:32.390 --> 01:44:33.620 among which is Linux. 01:44:33.620 --> 01:44:36.960 So Linux is a very popular operating system, 01:44:36.960 --> 01:44:39.380 the thing that turns on-- the thing that boots up 01:44:39.380 --> 01:44:40.880 when you first turn on a computer. 01:44:40.880 --> 01:44:44.690 And it's very commonly used for servers nowadays. 01:44:44.690 --> 01:44:48.860 All of CS50's own servers run some version of Linux. 01:44:48.860 --> 01:44:51.080 Those students more comfortable sometimes 01:44:51.080 --> 01:44:54.410 run Linux on their own Macs or PCs even. 01:44:54.410 --> 01:44:56.720 So Linux is a very popular operating system. 01:44:56.720 --> 01:45:00.110 And it's particularly characterized by its textual interface, 01:45:00.110 --> 01:45:03.770 its command-line interface, even though it also comes with graphical ones, 01:45:03.770 --> 01:45:04.410 as well. 01:45:04.410 --> 01:45:07.490 So again, this term we started today with, a graphical user interface 01:45:07.490 --> 01:45:09.230 is a thing with menus and buttons. 01:45:09.230 --> 01:45:11.850 It's literally what you and I use every day on our devices, 01:45:11.850 --> 01:45:13.220 otherwise known as a GUI. 01:45:13.220 --> 01:45:15.440 But today onward, you'll get more comfortable 01:45:15.440 --> 01:45:18.380 with and more practice with this terminal window 01:45:18.380 --> 01:45:22.430 down here, which represents a command-line interface, or CLI. 01:45:22.430 --> 01:45:26.270 And just so you have a mental model of what's going on in the cloud here, 01:45:26.270 --> 01:45:31.460 when you access cs50.dev, you are accessing this version of VS Code 01:45:31.460 --> 01:45:34.290 in the cloud, a piece of software just running in a browser. 01:45:34.290 --> 01:45:36.680 But that piece of software is automatically 01:45:36.680 --> 01:45:41.600 connected to your very own personal server in the cloud, so to speak. 01:45:41.600 --> 01:45:43.860 Technically speaking, it's a "docker container." 01:45:43.860 --> 01:45:47.930 But it means that you have essentially your own mini server in the cloud 01:45:47.930 --> 01:45:50.640 that only you have access to. 01:45:50.640 --> 01:45:55.460 And that server or container is running an operating system called Linux. 01:45:55.460 --> 01:45:58.370 And in fact, every time I've been running a command down here, 01:45:58.370 --> 01:46:02.750 whether it's code or make or ./hello or anything else, 01:46:02.750 --> 01:46:06.740 I've been running commands from here in Sanders Theatre on a server somewhere 01:46:06.740 --> 01:46:10.280 in the cloud, my own Linux container or server. 01:46:10.280 --> 01:46:12.050 And you'll have the same yourself. 01:46:12.050 --> 01:46:14.270 This is the thing that we have pre-configured 01:46:14.270 --> 01:46:18.320 for you by installing the compiler in so many other pieces of software 01:46:18.320 --> 01:46:20.180 you'll soon see in the class. 01:46:20.180 --> 01:46:24.920 But underneath the hood, then, of Linux is a soon-to-be familiar environment 01:46:24.920 --> 01:46:27.530 that allows you to run different types of commands. 01:46:27.530 --> 01:46:29.542 And those commands include things like this. 01:46:29.542 --> 01:46:32.250 And this is something you'll develop muscle memory for over time. 01:46:32.250 --> 01:46:36.710 But I wanted to give you a sense of some of the most popular textual commands 01:46:36.710 --> 01:46:38.690 because we're essentially about to take away 01:46:38.690 --> 01:46:42.740 muscle memory you have from a GUI world and have you type out words that 01:46:42.740 --> 01:46:46.280 represent double-clicking on things, dragging on other things, 01:46:46.280 --> 01:46:48.680 and other such commands that you and I take for granted. 01:46:48.680 --> 01:46:51.830 It'll be a little painful at first in the first days or weeks, 01:46:51.830 --> 01:46:56.150 but it will make you far more productive long term so that even after CS50, 01:46:56.150 --> 01:46:59.390 if you start using your programming skills in some other domain, class, 01:46:59.390 --> 01:47:02.660 or real-world job, you'll just be a lot faster at the keyboard 01:47:02.660 --> 01:47:04.980 and able to do more work more quickly. 01:47:04.980 --> 01:47:08.660 So with that said, let me go back to VS Code over here. 01:47:08.660 --> 01:47:11.360 I'm going to go ahead and open up my File Explorer over here. 01:47:11.360 --> 01:47:14.180 And you'll see at left all of the files that I've 01:47:14.180 --> 01:47:17.210 created thus far in class and all of the programs 01:47:17.210 --> 01:47:19.250 that I've compiled thus far in class. 01:47:19.250 --> 01:47:21.620 I also have this source 1 directory, which 01:47:21.620 --> 01:47:25.070 you can download from the course's website, which has all of today's code 01:47:25.070 --> 01:47:27.740 pre-written in advance, so you don't have to type everything 01:47:27.740 --> 01:47:28.910 that I literally type. 01:47:28.910 --> 01:47:31.560 But all of these files are things that I've created. 01:47:31.560 --> 01:47:34.070 And you'll see that in white are the C files. 01:47:34.070 --> 01:47:38.180 And grayed out are actually the binary files, the machine code 01:47:38.180 --> 01:47:40.160 that I created that I was running. 01:47:40.160 --> 01:47:45.080 So you can click on any of these files in VS Code to open them. 01:47:45.080 --> 01:47:47.330 For instance, here is hello.c. 01:47:47.330 --> 01:47:49.860 And voila, it opens in the text editor. 01:47:49.860 --> 01:47:52.520 But if I try to open "hello," that's not going to work, 01:47:52.520 --> 01:47:53.870 because that's zeros and ones. 01:47:53.870 --> 01:47:57.098 And frankly, the computer could show me all those zeros and ones, 01:47:57.098 --> 01:47:58.640 but it's just not going to be useful. 01:47:58.640 --> 01:48:01.800 And honestly, it's too easy to make one mistake and break the whole thing. 01:48:01.800 --> 01:48:05.690 So instead, VS Code says that it can't display the text, because it's binary 01:48:05.690 --> 01:48:07.860 or maybe unsupported more generally. 01:48:07.860 --> 01:48:12.470 So know that you want to only click on the .c files when writing C code. 01:48:12.470 --> 01:48:14.240 But let me go ahead and do something else. 01:48:14.240 --> 01:48:18.650 Suppose that I decide that, wait a minute, we're nearing the end of class. 01:48:18.650 --> 01:48:23.180 And we're not done yet, but what if I want to change hello.c to goodbye.c 01:48:23.180 --> 01:48:26.990 or if I want to change meow.c to woof.c and turn it into a dog? 01:48:26.990 --> 01:48:28.310 Well, let's actually do that. 01:48:28.310 --> 01:48:32.450 I could go over here and right click or Control click on the file, 01:48:32.450 --> 01:48:33.650 just like on a Mac or PC. 01:48:33.650 --> 01:48:35.520 I can find the Rename option. 01:48:35.520 --> 01:48:37.460 And I can do it all via the GUI. 01:48:37.460 --> 01:48:41.120 But you should get more comfortable using commands like these here. 01:48:41.120 --> 01:48:45.410 And among the commands on this list are "mv" for move, a.k.a. 01:48:45.410 --> 01:48:46.430 rename. 01:48:46.430 --> 01:48:52.430 So for instance, if I want to change meow.c to be woof.c instead, 01:48:52.430 --> 01:48:56.960 I literally type "mv" space, the original file name, space, 01:48:56.960 --> 01:48:58.140 and the new file name. 01:48:58.140 --> 01:49:00.050 So this is very similar to what I've already 01:49:00.050 --> 01:49:03.260 been doing with the code program or the make program. 01:49:03.260 --> 01:49:06.200 I not only type the name of the command but also the thing 01:49:06.200 --> 01:49:08.690 that I want to code or the thing that I want to make. 01:49:08.690 --> 01:49:12.140 In this case, I type the thing that I want to move from old to new. 01:49:12.140 --> 01:49:15.230 Now, if I hit Enter in a moment, watch on the left-hand side, 01:49:15.230 --> 01:49:18.200 meow.c in the GUI should automatically change 01:49:18.200 --> 01:49:23.800 even though I'm doing this all via the command-line keyboard interface. 01:49:23.800 --> 01:49:25.282 And now it becomes woof.c. 01:49:25.282 --> 01:49:26.740 I mean, it's not all that exciting. 01:49:26.740 --> 01:49:29.380 But this is just to say that they are one and the same. 01:49:29.380 --> 01:49:33.260 One is a GUI, one is a CLI, but it's the same exact thing. 01:49:33.260 --> 01:49:35.530 Moreover, let me go ahead and close now the GUI 01:49:35.530 --> 01:49:37.510 at left, the so-called explorer. 01:49:37.510 --> 01:49:41.327 And in my terminal window alone, now I'm kind of out of my element, 01:49:41.327 --> 01:49:43.660 like wait a minute, what was the file I created earlier? 01:49:43.660 --> 01:49:45.550 Well, there's other commands as well. 01:49:45.550 --> 01:49:50.500 On this list is, coincidentally, "ls," which lists 01:49:50.500 --> 01:49:52.940 the file in your current folder. 01:49:52.940 --> 01:49:56.770 And as you might have gleaned here, "mv" for move, "ls" for list, 01:49:56.770 --> 01:49:59.560 CS people like to be succinct, terse, and type 01:49:59.560 --> 01:50:01.150 the minimal number of keystrokes. 01:50:01.150 --> 01:50:04.180 That's why these are all abbreviated commands instead of full words. 01:50:04.180 --> 01:50:07.480 But if I go back to my terminal window and type "ls," voila, 01:50:07.480 --> 01:50:13.540 there is exactly the same contents of my server but displayed textually. 01:50:13.540 --> 01:50:14.920 And there's some heuristics here. 01:50:14.920 --> 01:50:18.040 In green with an asterisk is all of the programs 01:50:18.040 --> 01:50:21.110 that I made with make that are executable. 01:50:21.110 --> 01:50:24.150 So the asterisks just means this is executable with dot-slash. 01:50:24.150 --> 01:50:27.860 Meanwhile, the source 1 directory, which only I have because I downloaded it 01:50:27.860 --> 01:50:31.520 in advance, has a slash to indicate that it's a folder instead of a file. 01:50:31.520 --> 01:50:36.570 But all of these white files ending in .c we created together here today. 01:50:36.570 --> 01:50:42.020 Now, what if I really am embarrassed by my very first program, hello.c? 01:50:42.020 --> 01:50:48.020 Well, I can very destructively go and use the rm command for remove. 01:50:48.020 --> 01:50:52.370 And rm hello.c is going to prompt me, a little cryptically, 01:50:52.370 --> 01:50:54.740 "remove regular file 'hello.c'?" 01:50:54.740 --> 01:51:01.580 And amazingly, this rm program has code just like we wrote earlier for agree.c, 01:51:01.580 --> 01:51:03.560 where I can type 'y' to delete it. 01:51:03.560 --> 01:51:05.060 I can type 'n' not to delete it. 01:51:05.060 --> 01:51:06.180 But let's delete it. 01:51:06.180 --> 01:51:08.210 Let's go ahead and hit y, enter. 01:51:08.210 --> 01:51:09.840 Nothing seems to happen. 01:51:09.840 --> 01:51:11.370 But in general, that's a good thing. 01:51:11.370 --> 01:51:14.170 But if I type "ls" again, notice what is now missing? 01:51:14.170 --> 01:51:15.920 And in fact, the list is a little shorter. 01:51:15.920 --> 01:51:18.110 So it's one line instead of two. 01:51:18.110 --> 01:51:20.370 "hello.c" is now gone. 01:51:20.370 --> 01:51:24.300 Now, if you do that, there are not easy ways to get the file back. 01:51:24.300 --> 01:51:26.750 So don't do that unless you really want to. 01:51:26.750 --> 01:51:29.910 But there are backups maintained of these files, as well. 01:51:29.910 --> 01:51:31.160 Well, what else is there, too? 01:51:31.160 --> 01:51:32.510 Well, there's all of these other commands. 01:51:32.510 --> 01:51:34.052 And you'll experience them over time. 01:51:34.052 --> 01:51:35.540 Like, "cp" is copy. 01:51:35.540 --> 01:51:40.190 "mkdir" is make directory. "rmdir" is remove directory. 01:51:40.190 --> 01:51:43.070 And for instance, let me just show you one folder. 01:51:43.070 --> 01:51:45.770 If I type "ls," there's that source 1 folder 01:51:45.770 --> 01:51:47.510 that I claimed I downloaded in advance. 01:51:47.510 --> 01:51:50.120 If you want to see what's there, you can type "cd" 01:51:50.120 --> 01:51:53.810 for change directory, source 1, enter. 01:51:53.810 --> 01:51:56.970 And voila, notice that your prompt has now changed. 01:51:56.970 --> 01:51:58.310 And let me clear the screen. 01:51:58.310 --> 01:52:03.320 Just as a visual reminder of where you are, you can see before the dollar sign 01:52:03.320 --> 01:52:05.370 now the name of the folder that you're inside of. 01:52:05.370 --> 01:52:08.090 So in Mac or Windows, you'd see obviously a graphical folder. 01:52:08.090 --> 01:52:11.360 Here, you just see a little textual reminder of where you now are. 01:52:11.360 --> 01:52:14.840 And if I type "ls," you'll see that I wrote a crazy number of files 01:52:14.840 --> 01:52:15.770 before class. 01:52:15.770 --> 01:52:18.380 And each of these represents different versions of the files 01:52:18.380 --> 01:52:20.540 that we've been coding here in real time that I usually 01:52:20.540 --> 01:52:22.748 have printouts of just to go through things in series 01:52:22.748 --> 01:52:25.135 so you have copies online, as well. 01:52:25.135 --> 01:52:28.010 So in short, all of these commands, if you've never used them before, 01:52:28.010 --> 01:52:29.780 they will soon become like muscle memory. 01:52:29.780 --> 01:52:31.760 And they do the most basic of operations. 01:52:31.760 --> 01:52:33.927 But there will be other commands that we'll see over 01:52:33.927 --> 01:52:36.470 time that do even much more than that. 01:52:36.470 --> 01:52:39.050 But let's go ahead now and solve some actual problems. 01:52:39.050 --> 01:52:41.990 And it's no coincidence that we keep showing or alluding 01:52:41.990 --> 01:52:44.300 to Super Mario Brothers in some form, an older game 01:52:44.300 --> 01:52:47.660 from the Nintendo Entertainment System, that allows you ultimately 01:52:47.660 --> 01:52:50.720 to have this two-dimensional world, where Mario moves up and down 01:52:50.720 --> 01:52:52.730 and side scrolls from left to right. 01:52:52.730 --> 01:52:55.940 But you'll see we can distill even some aspects of "Mario" 01:52:55.940 --> 01:53:00.260 into some fairly representative programming problems. 01:53:00.260 --> 01:53:02.835 And in fact, let me propose that we consider this screen 01:53:02.835 --> 01:53:04.460 from the original Super Mario Brothers. 01:53:04.460 --> 01:53:09.810 So there's these four blocks in the sky, each with a question mark. 01:53:09.810 --> 01:53:12.800 And if you click on one of these-- or if Mario jumps up 01:53:12.800 --> 01:53:15.800 underneath each of these question marks, he 01:53:15.800 --> 01:53:18.140 gets like a coin or something else that pops out. 01:53:18.140 --> 01:53:22.550 Let's distill this, though, into its essence and consider in C, how can 01:53:22.550 --> 01:53:26.310 we make, not a blue sky yet, not a green grassy hill, and so forth, 01:53:26.310 --> 01:53:28.910 but how can we just make four question marks in a row, 01:53:28.910 --> 01:53:32.790 because I dare say that we do have the building blocks via which to do this. 01:53:32.790 --> 01:53:38.180 Well, the simplest way might be to go over here and run code of mario.c. 01:53:38.180 --> 01:53:42.560 And then in mario.c, let's include some stdio.h so we have printf. 01:53:42.560 --> 01:53:45.200 Let's do int main(void), as we keep doing. 01:53:45.200 --> 01:53:47.960 And inside of main, let's keep it super simple-- 01:53:47.960 --> 01:53:51.360 1, 2, 3, 4, backslash n. 01:53:51.360 --> 01:53:52.880 Doesn't get much simpler than that. 01:53:52.880 --> 01:53:54.838 This is not going to be the prettiest of games. 01:53:54.838 --> 01:54:00.947 But if I make Mario now, ./mario, I get my four question marks in the sky. 01:54:00.947 --> 01:54:02.780 All right, so it's not all that interesting. 01:54:02.780 --> 01:54:07.287 But this is clearly a candidate for what type of programming feature. 01:54:07.287 --> 01:54:08.565 STUDENT: Scratch. 01:54:08.565 --> 01:54:11.690 DAVID MALAN: Not to Scratch, though Scratch would make it more interesting. 01:54:11.690 --> 01:54:12.005 yeah? 01:54:12.005 --> 01:54:12.320 STUDENT: A loop. 01:54:12.320 --> 01:54:14.028 DAVID MALAN: So some kind of loop, right? 01:54:14.028 --> 01:54:15.980 So print the thing out iteratively instead. 01:54:15.980 --> 01:54:16.730 So let me do that. 01:54:16.730 --> 01:54:19.620 Instead of just printing this out all at once, 01:54:19.620 --> 01:54:25.106 let me go ahead and remove this and do for int i gets zero; i less than 4; 01:54:25.106 --> 01:54:26.280 i++. 01:54:26.280 --> 01:54:29.390 And then in here, let me go ahead and print out just one question mark 01:54:29.390 --> 01:54:30.420 instead. 01:54:30.420 --> 01:54:31.800 And now let's run this. 01:54:31.800 --> 01:54:35.210 So "make mario" to recompile it, ./mario. 01:54:35.210 --> 01:54:37.910 And does anyone not want me to hit Enter yet? 01:54:37.910 --> 01:54:38.855 Why? 01:54:38.855 --> 01:54:40.730 STUDENT: Because it's gonna print a new line. 01:54:40.730 --> 01:54:43.860 DAVID MALAN: Yeah, it's going to print out a new line every time. 01:54:43.860 --> 01:54:48.205 So notice it's four question marks, but there each on its own line. 01:54:48.205 --> 01:54:49.580 All right, well, let me fix this. 01:54:49.580 --> 01:54:51.590 It's obviously because of the backslash n. 01:54:51.590 --> 01:54:52.940 So let me remove that. 01:54:52.940 --> 01:54:55.850 Let me rerun make mario, ./mario. 01:54:55.850 --> 01:54:59.960 And it's better in one way but worse in another. 01:54:59.960 --> 01:55:01.910 So wait, but now the dollar sign is doing 01:55:01.910 --> 01:55:03.785 that thing where it's on the same line, which 01:55:03.785 --> 01:55:05.550 just looks stupid if nothing else. 01:55:05.550 --> 01:55:07.830 So how can I fix that? 01:55:07.830 --> 01:55:08.400 Yeah? 01:55:08.400 --> 01:55:11.070 STUDENT: [INAUDIBLE] 01:55:11.070 --> 01:55:14.070 DAVID MALAN: Yeah, so logically, we don't have that many building blocks 01:55:14.070 --> 01:55:14.570 today. 01:55:14.570 --> 01:55:17.200 It's a lot of new syntax, but it's not that many new ideas. 01:55:17.200 --> 01:55:21.330 Let's just use printf to print out literally one and only 01:55:21.330 --> 01:55:24.690 one of these backslash n's, but outside of the loop so 01:55:24.690 --> 01:55:27.750 it happens after all four of those have been printed. 01:55:27.750 --> 01:55:30.510 All right, let me do make mario again, ./mario. 01:55:30.510 --> 01:55:32.680 And OK, now we're back in business. 01:55:32.680 --> 01:55:35.760 So sort of silly syntactical details, but if you 01:55:35.760 --> 01:55:39.750 reduce the problem to its essence, it should hopefully, logically, 01:55:39.750 --> 01:55:41.225 become clear over time. 01:55:41.225 --> 01:55:44.100 All right, well, how about not just something like that but vertical? 01:55:44.100 --> 01:55:45.720 Well, we've done something vertical already. 01:55:45.720 --> 01:55:47.720 And so I can imagine we could change the program 01:55:47.720 --> 01:55:51.540 to very simply print out three bricks instead of four question marks. 01:55:51.540 --> 01:55:53.890 But what if we consider a two-dimensional world? 01:55:53.890 --> 01:55:55.890 And later on in this game if you go underground, 01:55:55.890 --> 01:55:57.720 everything looks like this with lots of bricks. 01:55:57.720 --> 01:55:59.678 And let me propose, for the sake of discussion, 01:55:59.678 --> 01:56:03.947 that this big wall here is like a 3-by-3 grid of bricks. 01:56:03.947 --> 01:56:05.280 So it's not just a single brick. 01:56:05.280 --> 01:56:07.530 It's like three by three, or nine total. 01:56:07.530 --> 01:56:09.450 Now things get interesting. 01:56:09.450 --> 01:56:11.820 And let me go back to mario.c. 01:56:11.820 --> 01:56:15.150 I could take the easy road out and just say, all right, well, 01:56:15.150 --> 01:56:21.270 let's printf, how about 1, 2, 3, backslash n, close quote. 01:56:21.270 --> 01:56:23.490 And then, OK, let me just copy/paste. 01:56:23.490 --> 01:56:26.520 And I'm using hashes instead of the actual bricks. 01:56:26.520 --> 01:56:28.860 But aesthetically, it's pretty close. 01:56:28.860 --> 01:56:33.073 Let me now go ahead and "make mario" again, ./mario. 01:56:33.073 --> 01:56:34.740 And it doesn't quite look like a square. 01:56:34.740 --> 01:56:37.823 But that's just because the hashes are a little taller than they are wide. 01:56:37.823 --> 01:56:40.140 But it is correct, but not well designed. 01:56:40.140 --> 01:56:44.430 So here, too, what would be better designed than just hardcoding, typing 01:56:44.430 --> 01:56:48.280 literally all of these hashes? 01:56:48.280 --> 01:56:49.876 Yeah? 01:56:49.876 --> 01:56:51.540 STUDENT: We could use maybe two loops. 01:56:51.540 --> 01:56:53.040 DAVID MALAN: Interesting, two loops. 01:56:53.040 --> 01:56:56.080 And why two loops instead of one? 01:56:56.080 --> 01:56:57.580 STUDENT: Oh, wait, nevermind. 01:56:57.580 --> 01:57:00.545 Well, I was going to say you could do it one for vertical and one 01:57:00.545 --> 01:57:01.170 for horizontal. 01:57:01.170 --> 01:57:02.280 DAVID MALAN: OK, it's the right instinct. 01:57:02.280 --> 01:57:04.170 So one for vertical, one for horizontal. 01:57:04.170 --> 01:57:06.060 And even though these predate most of us, 01:57:06.060 --> 01:57:08.220 old-school typewriters you might know or might 01:57:08.220 --> 01:57:12.180 recall that if you feed a piece of paper into it, you can print like line, 01:57:12.180 --> 01:57:16.180 then it scrolls, line, then it scrolls, line, then it scrolls. 01:57:16.180 --> 01:57:18.390 This is kind of how the terminal window works, too. 01:57:18.390 --> 01:57:20.970 You can print rows and columns, but you have 01:57:20.970 --> 01:57:24.540 to print one row at a time, one row at a time, one row at a time. 01:57:24.540 --> 01:57:28.810 It's not easy, but it is possible to go backwards and go up and down. 01:57:28.810 --> 01:57:31.960 But just going row by row by row is more typical. 01:57:31.960 --> 01:57:33.010 So how can I do this? 01:57:33.010 --> 01:57:36.370 Well, I could use at least one and maybe even indeed two loops. 01:57:36.370 --> 01:57:39.270 And this is where we're just now composing different ideas 01:57:39.270 --> 01:57:40.990 from today and even last week. 01:57:40.990 --> 01:57:45.900 So let me go ahead and say, for int i gets 0; i less than 3-- 01:57:45.900 --> 01:57:47.370 for a 3-by-3 grid-- 01:57:47.370 --> 01:57:48.810 i++. 01:57:48.810 --> 01:57:51.180 And now let me cheat slightly. 01:57:51.180 --> 01:57:55.790 Let me print out just three of these here, and that's it. 01:57:55.790 --> 01:57:56.790 So I'm kind of cheating. 01:57:56.790 --> 01:58:01.360 I'm printing out rows dynamically, but I'm still printing three columns all 01:58:01.360 --> 01:58:02.170 in one breath. 01:58:02.170 --> 01:58:03.430 But let's see what happens. 01:58:03.430 --> 01:58:07.840 Make mario, ./mario, and it does work. 01:58:07.840 --> 01:58:12.610 But what if you said, no, I want 4 by 4 or 5 by 5 or 6 by 6? 01:58:12.610 --> 01:58:17.590 Now I have to change the 3 to a 6, and I have to add another three hashes here. 01:58:17.590 --> 01:58:20.180 Things get messy if we don't do this mathematically. 01:58:20.180 --> 01:58:22.120 So let me now do this instead. 01:58:22.120 --> 01:58:26.440 Why don't I go ahead and print out every row at a time. 01:58:26.440 --> 01:58:30.340 But for each row, let me use another loop to decide, like, rat-a-tat-tat, 01:58:30.340 --> 01:58:33.010 from left to right, how many do I want to print. 01:58:33.010 --> 01:58:35.890 So to do this, I could do another for loop. 01:58:35.890 --> 01:58:39.050 I could call this variable something different. j is pretty common. 01:58:39.050 --> 01:58:40.480 We start at i, we go to j. 01:58:40.480 --> 01:58:43.720 If you go past k, maybe l, you're probably doing something wrong. 01:58:43.720 --> 01:58:46.990 You don't want nested, nested, nested loops, but two is OK. 01:58:46.990 --> 01:58:52.480 j equals 0; j is less than 3; j++. 01:58:52.480 --> 01:58:57.178 And then here, I can print out a single one of these and no new line. 01:58:57.178 --> 01:58:58.970 I don't want to screw up like I did before. 01:58:58.970 --> 01:59:00.340 So I'll just do one. 01:59:00.340 --> 01:59:03.970 Let me go ahead and do make mario now, ./mario. 01:59:03.970 --> 01:59:06.482 But when I hit Enter, this is not correct yet. 01:59:06.482 --> 01:59:07.690 What's it going to look like? 01:59:07.690 --> 01:59:09.130 STUDENT: A single line? 01:59:09.130 --> 01:59:12.040 DAVID MALAN: A single line of nine hashes, I think, 01:59:12.040 --> 01:59:14.980 because I never used a single backslash n. 01:59:14.980 --> 01:59:16.220 So that looks wrong. 01:59:16.220 --> 01:59:23.620 So between what line number should I insert a printf of backslash n? 01:59:23.620 --> 01:59:25.660 Let me look a little farther back if I can. 01:59:25.660 --> 01:59:26.920 How about over here? 01:59:26.920 --> 01:59:27.520 Yeah? 01:59:27.520 --> 01:59:28.720 STUDENT: 10 and 11. 01:59:28.720 --> 01:59:30.280 DAVID MALAN: Between 10 and 11. 01:59:30.280 --> 01:59:31.580 So I'm going to go in here. 01:59:31.580 --> 01:59:34.930 I'm going to add printf, quote, unquote, "backslash n" semicolon. 01:59:34.930 --> 01:59:37.380 Let me go back and recompile mario-- 01:59:37.380 --> 01:59:38.290 ./mario. 01:59:38.290 --> 01:59:41.320 And crossing fingers-- voila, perfect. 01:59:41.320 --> 01:59:43.210 I printed out now a 3-by-3. 01:59:43.210 --> 01:59:44.440 Now, it's correct. 01:59:44.440 --> 01:59:48.130 It's not, if we want to be really nitpicky, maybe still not 01:59:48.130 --> 01:59:49.240 the best design. 01:59:49.240 --> 01:59:51.310 Where am I perhaps repeating myself? 01:59:53.840 --> 01:59:54.627 Yeah? 01:59:54.627 --> 01:59:55.770 STUDENT: [INAUDIBLE] 01:59:55.770 --> 01:59:57.770 DAVID MALAN: Yeah, I mean, it's not a huge deal. 01:59:57.770 --> 02:00:00.247 But now I have two, people would call these magic numbers. 02:00:00.247 --> 02:00:02.330 "Magic" in the sense of, where did that come from? 02:00:02.330 --> 02:00:05.100 You just randomly put it in the middle of your code. 02:00:05.100 --> 02:00:06.878 And you also put the same thing here. 02:00:06.878 --> 02:00:10.170 Now I have to make sure I don't screw up and make one change but not the other. 02:00:10.170 --> 02:00:11.837 So it turns out we can factor these out. 02:00:11.837 --> 02:00:15.050 I can actually do something like this, int n equals 3. 02:00:15.050 --> 02:00:17.690 And then I can just change this to n and this 02:00:17.690 --> 02:00:19.730 to n, which is marginally better because now 02:00:19.730 --> 02:00:22.160 I only have to change n in one place if I want 02:00:22.160 --> 02:00:24.113 to make this thing bigger or smaller. 02:00:24.113 --> 02:00:25.530 It's still going to work the same. 02:00:25.530 --> 02:00:27.830 So make mario, ./mario. 02:00:27.830 --> 02:00:28.880 There's our 3-by-3. 02:00:28.880 --> 02:00:35.120 But if I want to make a 5-by-5, let me change the n to 5, rerun make mario, 02:00:35.120 --> 02:00:35.900 ./mario. 02:00:35.900 --> 02:00:38.480 And now it's a bigger grid, 5-by-5. 02:00:38.480 --> 02:00:40.162 But this is a little fragile. 02:00:40.162 --> 02:00:42.620 And it turns out there's another trick we should introduce. 02:00:42.620 --> 02:00:45.590 It turns out that C supports what are called constants, 02:00:45.590 --> 02:00:48.920 whereby if you have a variable that you want to exist because it's useful 02:00:48.920 --> 02:00:50.857 but you don't want to accidentally change it, 02:00:50.857 --> 02:00:53.690 or if you're working with a partner in class or a colleague at work, 02:00:53.690 --> 02:00:57.140 you don't want your partner or colleague to accidentally change 02:00:57.140 --> 02:01:01.250 that value with their own code, you can go into your code and tell C, 02:01:01.250 --> 02:01:05.790 this is actually a constant integer, a const, so to speak. 02:01:05.790 --> 02:01:07.790 And this will just prevent you or someone else 02:01:07.790 --> 02:01:11.430 from doing something stupid by accidentally changing it elsewhere. 02:01:11.430 --> 02:01:14.510 The code is still going to work the same, ./mario, 02:01:14.510 --> 02:01:18.690 but you won't be accidentally able to change it very easily to something 02:01:18.690 --> 02:01:19.190 else. 02:01:19.190 --> 02:01:22.160 And honestly, what we've now done, too, is set ourselves 02:01:22.160 --> 02:01:23.420 up to make this more dynamic. 02:01:23.420 --> 02:01:27.920 Let me go up here, and let me add the CS50 library so that we have access 02:01:27.920 --> 02:01:30.050 to get_int because now we could do something 02:01:30.050 --> 02:01:36.920 fancy like ask the get_int function for the size of this brick wall. 02:01:36.920 --> 02:01:39.150 And then we can use n dynamically. 02:01:39.150 --> 02:01:42.300 So for instance, let me increase the size of my terminal, make mario, 02:01:42.300 --> 02:01:45.140 ./mario, size 3. 02:01:45.140 --> 02:01:47.150 Gives me a 3-by-3. 02:01:47.150 --> 02:01:50.000 ./mario size 5 gives me a 5-by-5. 02:01:50.000 --> 02:01:54.600 ./mario, how about 50, gives me a crazy big one, but it's all dynamic. 02:01:54.600 --> 02:01:56.760 And now I don't have to even change the code. 02:01:56.760 --> 02:01:58.980 It just now works. 02:01:58.980 --> 02:02:01.500 As an aside, if you're wondering how I type so darn fast, 02:02:01.500 --> 02:02:03.900 sometimes it's just because I'm hitting the up arrow. 02:02:03.900 --> 02:02:06.600 It turns out that Linux will remember, if you 02:02:06.600 --> 02:02:08.860 configure it this way, all of your previous commands. 02:02:08.860 --> 02:02:12.480 So if you hit up, up, up, I can go through the past couple of hours 02:02:12.480 --> 02:02:14.820 of commands that I've typed, which is useful sometimes-- 02:02:14.820 --> 02:02:16.950 not for hours of commands but the past few-- 02:02:16.950 --> 02:02:18.810 just to save yourself some keystrokes. 02:02:18.810 --> 02:02:22.110 And another trick in a terminal window is to do this. 02:02:22.110 --> 02:02:28.050 If I do ./ma and I get bored and I don't want to type out "rio," 02:02:28.050 --> 02:02:31.800 I can also just hit Tab, and it will autocomplete based on the characters 02:02:31.800 --> 02:02:32.470 that do match. 02:02:32.470 --> 02:02:36.990 So those kinds of tricks, too, will save you time over time. 02:02:36.990 --> 02:02:38.070 But let's do this. 02:02:38.070 --> 02:02:41.880 It's kind of broken, arguably, if I do this. 02:02:41.880 --> 02:02:44.400 How about "cat?" 02:02:44.400 --> 02:02:45.900 All right, well, that works. 02:02:45.900 --> 02:02:48.480 That prevents me from doing something stupid 02:02:48.480 --> 02:02:51.120 because get_int only accepts integers. 02:02:51.120 --> 02:02:54.000 But it will accept 0, which does nothing. 02:02:54.000 --> 02:02:56.370 It will accept negative 1, which does nothing. 02:02:56.370 --> 02:02:57.600 And that's not bad. 02:02:57.600 --> 02:02:59.040 It's not doing something weird. 02:02:59.040 --> 02:03:01.890 But it would be nice to catch that and force the user 02:03:01.890 --> 02:03:04.410 to give us a positive integer instead so we at least 02:03:04.410 --> 02:03:05.732 see something on the screen. 02:03:05.732 --> 02:03:08.190 So let me go back into my code, and let me propose that now 02:03:08.190 --> 02:03:12.018 that we have the CS50 library, why don't we do something like this? 02:03:12.018 --> 02:03:13.060 I'm going to change this. 02:03:13.060 --> 02:03:14.640 I'm going to get rid of the constant just in case 02:03:14.640 --> 02:03:16.080 the user needs to type it again. 02:03:16.080 --> 02:03:17.250 And what if I do this? 02:03:17.250 --> 02:03:20.070 While n is less than 1-- 02:03:20.070 --> 02:03:23.610 so if it's 0, negative 1, negative 2, or whatever, let's go ahead 02:03:23.610 --> 02:03:28.860 and again ask the user for an int, and ask them for the size again. 02:03:28.860 --> 02:03:33.780 And therefore, only once n is not less than 1 will 02:03:33.780 --> 02:03:36.670 this loop break out and will proceed with the rest of the code. 02:03:36.670 --> 02:03:37.770 So now let me try this. 02:03:37.770 --> 02:03:42.120 Make mario, ./mario 0-- 02:03:42.120 --> 02:03:42.960 didn't like that. 02:03:42.960 --> 02:03:44.370 Negative 1-- didn't like that. 02:03:44.370 --> 02:03:45.810 Negative 2-- didn't like that. 02:03:45.810 --> 02:03:48.640 3-- it did like that. 02:03:48.640 --> 02:03:52.950 So using a loop now, I can ensure that the human is providing me 02:03:52.950 --> 02:03:55.810 with input that I actually want. 02:03:55.810 --> 02:03:57.180 So this is correct. 02:03:57.180 --> 02:04:01.140 But I dare say 6 through 10 could be done better. 02:04:01.140 --> 02:04:06.580 Why is this poorly designed instinctively? 02:04:06.580 --> 02:04:07.080 Yeah? 02:04:07.080 --> 02:04:07.930 STUDENT: There's repetition. 02:04:07.930 --> 02:04:10.600 DAVID MALAN: What's the repetition, to be clear, what lines? 02:04:10.600 --> 02:04:12.145 STUDENT: Lines 6 and 9. 02:04:12.145 --> 02:04:13.240 DAVID MALAN: 6 and 9. 02:04:13.240 --> 02:04:16.400 OK, so they're literally the same, and that's generally not a good thing. 02:04:16.400 --> 02:04:19.390 And maybe I could change this one to remind the user like, hey, 02:04:19.390 --> 02:04:20.688 that's not a positive number. 02:04:20.688 --> 02:04:22.480 So you might want to customize the message. 02:04:22.480 --> 02:04:26.390 But just having copy/paste here for the most part is not a good thing. 02:04:26.390 --> 02:04:29.770 So it turns out-- and there's just one feature of C we wanted to introduce you 02:04:29.770 --> 02:04:33.400 to today-- it turns out there's one other way that would actually help us 02:04:33.400 --> 02:04:37.450 eliminate this redundancy of using get_int twice and particularly asking 02:04:37.450 --> 02:04:39.670 literally the same question-- size-- 02:04:39.670 --> 02:04:40.990 twice in duplicate. 02:04:40.990 --> 02:04:42.937 So I'm actually going to go into my code here, 02:04:42.937 --> 02:04:45.520 and I'm going to delete the loop as we've written it thus far. 02:04:45.520 --> 02:04:47.750 And instead of using a while loop, I'm going 02:04:47.750 --> 02:04:49.750 to introduce instead something that we typically 02:04:49.750 --> 02:04:52.960 call a do while loop, which is a little bit different. 02:04:52.960 --> 02:04:55.360 Indeed, we begin with the keyword "do," and then 02:04:55.360 --> 02:04:57.850 inside of the curly braces, what I'm going to do here 02:04:57.850 --> 02:05:02.690 is that thing I might want to do once and more times thereafter. 02:05:02.690 --> 02:05:08.690 So for instance, I'm going to say n equals get_int quote, unquote, "size." 02:05:08.690 --> 02:05:12.110 And then at the bottom of this block of code, then 02:05:12.110 --> 02:05:15.380 I'm going to use the keyword "while," as well as parentheses as always 02:05:15.380 --> 02:05:16.740 for a Boolean expression. 02:05:16.740 --> 02:05:17.280 And here. 02:05:17.280 --> 02:05:21.500 I'm going to ask the question, do this while n is less than 1. 02:05:21.500 --> 02:05:25.250 But there's one fix I still need to do here because notice on the current line 02:05:25.250 --> 02:05:28.280 8, I actually haven't given n a type. 02:05:28.280 --> 02:05:29.990 I haven't declared n yet. 02:05:29.990 --> 02:05:37.100 But it would not be correct to declare n here, inside of that do block. 02:05:37.100 --> 02:05:39.060 But why might that be? 02:05:39.060 --> 02:05:44.780 Why would it not be a good thing to declare n inside of these curly braces? 02:05:44.780 --> 02:05:47.240 Yeah, so recall that this is an issue of scope. 02:05:47.240 --> 02:05:49.820 Recall that the scope of a variable is generally 02:05:49.820 --> 02:05:53.690 confined to the most recently opened curly braces in which that variable is 02:05:53.690 --> 02:05:54.230 declared. 02:05:54.230 --> 02:05:56.690 And so if I declare this variable on line 8, 02:05:56.690 --> 02:05:58.845 I'm not going to be able to use it on line 10. 02:05:58.845 --> 02:06:01.470 But there is a fix, even though it might look a little strange. 02:06:01.470 --> 02:06:04.020 I'm going to go above my do block here. 02:06:04.020 --> 02:06:06.290 And before I go into this loop, I'm actually 02:06:06.290 --> 02:06:10.183 going to declare n to be an integer, but semicolon, end of thought. 02:06:10.183 --> 02:06:12.350 I'm not going to bother giving it a value, because I 02:06:12.350 --> 02:06:17.000 know logically I'm going to end up giving it a value anyway now on line 9. 02:06:17.000 --> 02:06:19.400 And so what's different about this version of the code 02:06:19.400 --> 02:06:24.200 is that the do while loop ensures that we prompt the user for input at least 02:06:24.200 --> 02:06:24.740 once. 02:06:24.740 --> 02:06:30.140 And then while that input is not what we expect, for instance less than 1, then 02:06:30.140 --> 02:06:32.583 it's going to execute again, again, again. 02:06:32.583 --> 02:06:34.250 And indeed, the semantics are just that. 02:06:34.250 --> 02:06:38.460 Do the following while this Boolean expression is true. 02:06:38.460 --> 02:06:44.180 So if I go ahead now and rerun make mario, compiles OK-- ./mario. 02:06:44.180 --> 02:06:48.140 And now I'll go ahead and input something that's not correct, like 0. 02:06:48.140 --> 02:06:49.340 But I'm prompted again. 02:06:49.340 --> 02:06:52.250 I'll input something like negative 1, and I'm prompted again. 02:06:52.250 --> 02:06:54.920 But if I go ahead and input, for instance, 10, 02:06:54.920 --> 02:07:02.060 now, because that's a positive integer, I indeed get a 10-by-10 grid of bricks. 02:07:02.060 --> 02:07:05.110 And there's one other thing we should introduce here, too, in C, too. 02:07:05.110 --> 02:07:06.022 C supports comments. 02:07:06.022 --> 02:07:07.730 And a couple of you have asked about this 02:07:07.730 --> 02:07:09.740 if you come from other programming languages. 02:07:09.740 --> 02:07:13.070 Suppose I want to remember what it is I just did with this program. 02:07:13.070 --> 02:07:20.120 Let me go in between lines 5 and 6 here and do "// prompt user for positive 02:07:20.120 --> 02:07:20.713 integer." 02:07:20.713 --> 02:07:22.130 This is what's known as a comment. 02:07:22.130 --> 02:07:25.378 And it's grayed out only in the sense that the compiler is not 02:07:25.378 --> 02:07:26.420 going to care about this. 02:07:26.420 --> 02:07:28.295 The computer is not going to care about this. 02:07:28.295 --> 02:07:31.430 This is a note to self, like a sticky note in the context of Scratch. 02:07:31.430 --> 02:07:35.000 And it starts with "//," which essentially tells the compiler ignore 02:07:35.000 --> 02:07:37.490 this, this is for the human, not for the computer. 02:07:37.490 --> 02:07:41.270 But this comment, so to speak, is a way of just reminding yourself, reminding 02:07:41.270 --> 02:07:43.520 your colleague, reminding your TF what it 02:07:43.520 --> 02:07:46.460 is a few lines of code are meant to do. 02:07:46.460 --> 02:07:53.930 And now this comment might be print, and how about n-by-n grid of bricks? 02:07:53.930 --> 02:07:57.890 And what's nice about comments is that theoretically you can get away with, 02:07:57.890 --> 02:08:00.440 or someone else can get away with, just reading this comment 02:08:00.440 --> 02:08:02.787 and then not even have to look at the rest of the code. 02:08:02.787 --> 02:08:05.870 They can look at this comment and not have to look at the rest of the code 02:08:05.870 --> 02:08:09.195 because you've described for them what it's meant to do. 02:08:09.195 --> 02:08:09.695 Yeah? 02:08:09.695 --> 02:08:13.020 STUDENT: I just had a question about the hashtag [INAUDIBLE] 02:08:13.020 --> 02:08:14.790 DAVID MALAN: Sure. 02:08:14.790 --> 02:08:16.440 STUDENT: That's for [INAUDIBLE] 02:08:16.440 --> 02:08:19.080 DAVID MALAN: Correct, the hash sign in Python is a comment, 02:08:19.080 --> 02:08:24.360 is not the same thing in C. In C, hash include means to include the library's 02:08:24.360 --> 02:08:26.320 header files in that way. 02:08:26.320 --> 02:08:28.290 Other questions on these here tricks? 02:08:31.060 --> 02:08:31.600 No? 02:08:31.600 --> 02:08:37.810 All right, so as promised, what is maybe C not actually good at? 02:08:37.810 --> 02:08:40.840 Well, let me propose that we consider what's 02:08:40.840 --> 02:08:42.280 actually inside of your computer. 02:08:42.280 --> 02:08:45.340 At the end of the day, whether it's a Mac, PC, iPhone, Android, phone, 02:08:45.340 --> 02:08:48.257 or some other computer device, there's something that looks like this. 02:08:48.257 --> 02:08:51.423 And this is memory, otherwise known as RAM, or random access memory, 02:08:51.423 --> 02:08:53.090 for reasons we'll get to in a few weeks. 02:08:53.090 --> 02:08:54.770 But this is where data is stored. 02:08:54.770 --> 02:08:56.570 This is where "hello, world" is stored. 02:08:56.570 --> 02:08:59.200 This is where 1 and 2 and all of those numbers are stored. 02:08:59.200 --> 02:09:03.590 Any data in your program is stored ultimately in the computer's memory. 02:09:03.590 --> 02:09:06.460 And the most important takeaway for today is that all of us 02:09:06.460 --> 02:09:10.090 only have a finite amount of memory in our devices. 02:09:10.090 --> 02:09:12.970 You might have a high-end device which has a lot of memory, 02:09:12.970 --> 02:09:15.970 but it's still finite, which means you can only 02:09:15.970 --> 02:09:17.650 count so high with that device. 02:09:17.650 --> 02:09:20.150 You can only store so many files with that device. 02:09:20.150 --> 02:09:24.730 There are fundamental physical limitations even though mathematically, 02:09:24.730 --> 02:09:27.617 theoretically, we should be able to count toward infinity. 02:09:27.617 --> 02:09:29.200 So what are the implications for this? 02:09:29.200 --> 02:09:30.530 Well, consider this. 02:09:30.530 --> 02:09:34.677 In the world of numbers, as per week 0, if you're only using three digits-- 02:09:34.677 --> 02:09:37.760 and I've grayed out the fourth one just to make the point-- if you're only 02:09:37.760 --> 02:09:43.750 using three digits, we can count from 0 to 1 in decimal, to 2, to3, to 4, 02:09:43.750 --> 02:09:47.030 to 5, to 6, to 7. 02:09:47.030 --> 02:09:50.180 And as soon as you count to 8, you technically, per last week, 02:09:50.180 --> 02:09:51.600 need a fourth bit. 02:09:51.600 --> 02:09:55.970 But if you don't have it, the number 7 might seem 02:09:55.970 --> 02:09:58.770 to be followed by what number instead? 02:09:58.770 --> 02:09:59.450 STUDENT: 0. 02:09:59.450 --> 02:10:00.380 DAVID MALAN: 0. 02:10:00.380 --> 02:10:03.260 The number overflows, so to speak, right? 02:10:03.260 --> 02:10:04.155 You carry the 1. 02:10:04.155 --> 02:10:07.280 But if there's no place to put the 1, because there's no fourth light bulb, 02:10:07.280 --> 02:10:09.740 if there's no fourth transistor, if there's no fourth bit, 02:10:09.740 --> 02:10:14.180 the lower bits, the zeros, are going to be mistaken for the number you 02:10:14.180 --> 02:10:15.080 and I know is 0. 02:10:15.080 --> 02:10:18.410 So integer overflow is a thing in computers 02:10:18.410 --> 02:10:21.560 whereby if you don't have enough memory, if you count high enough, 02:10:21.560 --> 02:10:23.690 the number will wrap around back to 0. 02:10:23.690 --> 02:10:26.210 Or sometimes it will wrap around to a negative number, 02:10:26.210 --> 02:10:30.350 depending on whether the code supports negative and positive numbers and 0 02:10:30.350 --> 02:10:30.950 alike. 02:10:30.950 --> 02:10:33.080 So that has some very real world implications 02:10:33.080 --> 02:10:36.590 in integer overflow that's sort of a fundamental limitation of how 02:10:36.590 --> 02:10:37.850 numbers are typically stored. 02:10:37.850 --> 02:10:39.980 Now, thankfully, we typically don't store things 02:10:39.980 --> 02:10:42.590 based on number of digits but number of bits. 02:10:42.590 --> 02:10:44.270 And a bit is just a 0 or 1. 02:10:44.270 --> 02:10:46.820 And recall from last week that a common unit of measure 02:10:46.820 --> 02:10:51.080 is minimally eight bits, or a byte, but even more commonly is 32. 02:10:51.080 --> 02:10:54.263 So for instance, here are 32 bits, all zeros. 02:10:54.263 --> 02:10:56.180 And if you do out the math, this is the number 02:10:56.180 --> 02:10:58.760 you and I know in decimal is of course 0. 02:10:58.760 --> 02:11:03.410 But if I change all 32 zeros to ones, this is a really big number now. 02:11:03.410 --> 02:11:05.810 If we're only using positive numbers, not negatives, 02:11:05.810 --> 02:11:10.680 what number roughly is this, 32 ones? 02:11:10.680 --> 02:11:15.520 It's roughly 4 billion in total-- roughly 4 billion in total. 02:11:15.520 --> 02:11:16.020 Why? 02:11:16.020 --> 02:11:19.770 Well, if you've got 32 bits, each can be two possible values, 0 or 1, that's 02:11:19.770 --> 02:11:22.260 2 to the 32nd power, which is roughly-- 02:11:22.260 --> 02:11:26.490 I'll stipulate-- roughly 4 billion total. 02:11:26.490 --> 02:11:29.883 The problem is, what if you want to count to 4,000,000,001? 02:11:29.883 --> 02:11:31.050 That's a bit of a white lie. 02:11:31.050 --> 02:11:32.290 It's not precisely that. 02:11:32.290 --> 02:11:34.457 But what if you want to count just higher than that? 02:11:34.457 --> 02:11:36.780 You'd need a 33rd bit because all of the others 02:11:36.780 --> 02:11:40.860 are going to go to 0 at that point, and you might count from 1 to 2 02:11:40.860 --> 02:11:45.690 to 3 to 4 billion back to 0, or worse if you're dealing with negative numbers, 02:11:45.690 --> 02:11:46.300 too. 02:11:46.300 --> 02:11:51.540 So the fact that there are finitely many bits used in computers is a problem. 02:11:51.540 --> 02:11:55.050 And negative numbers do add a complexity because this is specifically 02:11:55.050 --> 02:11:56.460 the 4 billion in question-- 02:11:56.460 --> 02:12:00.300 4,294,968,295. 02:12:00.300 --> 02:12:03.480 That is as high as you can count with 32 bits 02:12:03.480 --> 02:12:05.033 if you don't bother with negatives. 02:12:05.033 --> 02:12:07.200 But if you want negative numbers, you've got to half 02:12:07.200 --> 02:12:10.350 that because you've got to save half of them for negative, half of them 02:12:10.350 --> 02:12:11.770 for positive, give or take. 02:12:11.770 --> 02:12:14.640 And so if you're supporting negative numbers, as you probably 02:12:14.640 --> 02:12:17.850 should for a calculator, for Microsoft Excel, Google Spreadsheets, 02:12:17.850 --> 02:12:21.060 you can only count as high up as 2 billion roughly, 02:12:21.060 --> 02:12:24.640 or negative 2 billion roughly instead. 02:12:24.640 --> 02:12:29.340 So it turns out that when you are using data types in C, 02:12:29.340 --> 02:12:32.760 you have some control over how many bits are actually used. 02:12:32.760 --> 02:12:34.980 And this list is longer than we've covered today, 02:12:34.980 --> 02:12:37.800 but we did talk about integers for a while. 02:12:37.800 --> 02:12:40.680 Those are, by convention nowadays, 32 bits. 02:12:40.680 --> 02:12:44.760 If that's not enough, you can upgrade your variables to longs, which 02:12:44.760 --> 02:12:49.290 tend to be 64 bits instead, which isn't just twice as big as an integer, 02:12:49.290 --> 02:12:52.500 it's actually 64 bits, which is exponentially more. 02:12:52.500 --> 02:12:54.510 It's an unpronounceable number, at least for me. 02:12:54.510 --> 02:12:58.240 That's a crazy big number, but it's available to you. 02:12:58.240 --> 02:13:02.700 Moreover, we can see this if we actually are a little reckless with how 02:13:02.700 --> 02:13:03.428 we're using code. 02:13:03.428 --> 02:13:05.220 And just so you know too, though, there are 02:13:05.220 --> 02:13:07.140 functions even in CS50's library that let 02:13:07.140 --> 02:13:10.930 you use these larger values, get long of course, will get you a long. 02:13:10.930 --> 02:13:16.240 And this one's a little non-obvious, but "%li" is the format code for printf, 02:13:16.240 --> 02:13:20.720 just so you know, for printing a long integer and not just an integer. 02:13:20.720 --> 02:13:22.330 So it's two characters instead of one. 02:13:22.330 --> 02:13:26.860 Suppose, though, we actually want to use code involving some large numbers. 02:13:26.860 --> 02:13:29.208 It turns out that certain bad things can happen. 02:13:29.208 --> 02:13:30.500 So let me go ahead and do this. 02:13:30.500 --> 02:13:32.200 I'm going to go back over to VS Code here, 02:13:32.200 --> 02:13:35.408 and I'm going to modify my calculator to do something that, at glance, should 02:13:35.408 --> 02:13:36.880 be perfectly reasonable. 02:13:36.880 --> 02:13:40.030 Let me go ahead and open up calculator.c, as before. 02:13:40.030 --> 02:13:42.220 And where we left off, we had this add function. 02:13:42.220 --> 02:13:42.970 And you know what? 02:13:42.970 --> 02:13:45.502 I'm going to simplify it back to its very original version. 02:13:45.502 --> 02:13:47.710 I'm going to go ahead and get rid of the add function 02:13:47.710 --> 02:13:50.845 and just distill it to its essence, which is not to add any more. 02:13:50.845 --> 02:13:51.970 But let's just do division. 02:13:51.970 --> 02:13:55.120 I want to print out this time maybe x divided by y. 02:13:55.120 --> 02:13:59.770 So here we go. x divided by y is a nice simple program in my calculator. 02:13:59.770 --> 02:14:03.250 Let me do make calculator again, ./calculator. 02:14:03.250 --> 02:14:07.170 And let's divide something like 1 divided by 3, which should-- 02:14:07.170 --> 02:14:08.860 hm, OK, weird. 02:14:08.860 --> 02:14:13.360 It gave me 0 instead of probably 0.3333333, 02:14:13.360 --> 02:14:16.540 as you might have expected for 1/3. 02:14:16.540 --> 02:14:19.990 So what might the takeaway there be? 02:14:19.990 --> 02:14:22.090 Why am I seeing zero perhaps? 02:14:22.090 --> 02:14:22.600 Yeah? 02:14:22.600 --> 02:14:27.060 STUDENT: If 0's the integer [INAUDIBLE],, then if you want decimals [INAUDIBLE].. 02:14:27.060 --> 02:14:29.178 DAVID MALAN: Yeah, so 0 is an integer. 02:14:29.178 --> 02:14:31.470 And indeed, that's what I'm telling the thing to print. 02:14:31.470 --> 02:14:34.980 And in fact, if we go over to my little cheat sheet here of format codes, 02:14:34.980 --> 02:14:36.525 I'm currently using %i. 02:14:36.525 --> 02:14:41.460 I should actually, when I do division of numbers that might have floating point 02:14:41.460 --> 02:14:43.560 values, a decimal point that floats left to right, 02:14:43.560 --> 02:14:47.698 otherwise known as a real number, I want to use %f for float instead. 02:14:47.698 --> 02:14:49.740 So I'm actually going to go back to my code here. 02:14:49.740 --> 02:14:52.920 And let's try this-- %f instead of %i. 02:14:52.920 --> 02:14:55.560 And let me go ahead and "make calculator." 02:14:55.560 --> 02:14:56.370 Huh, all right. 02:14:56.370 --> 02:14:57.930 Well, this didn't work then. 02:14:57.930 --> 02:15:01.830 "Format specifies type 'double,' but the argument has type 'int.' 02:15:01.830 --> 02:15:05.260 All right, so that, too, is not quite working. 02:15:05.260 --> 02:15:09.150 So I think I actually need to make a change here further. 02:15:09.150 --> 02:15:10.870 Let me actually go ahead and do this. 02:15:10.870 --> 02:15:13.230 It turns out that besides integers, there 02:15:13.230 --> 02:15:15.750 are these things called floats, and also doubles. 02:15:15.750 --> 02:15:19.082 A float uses 32 bits, and a double uses 64 bits. 02:15:19.082 --> 02:15:20.790 And that doesn't necessarily mean you can 02:15:20.790 --> 02:15:22.860 count higher as much as it means you can have 02:15:22.860 --> 02:15:24.820 more numbers after the decimal point. 02:15:24.820 --> 02:15:27.610 So if you want a more precise value, you throw memory at it 02:15:27.610 --> 02:15:30.363 by using a double and 64 bits instead of a float. 02:15:30.363 --> 02:15:32.780 But we'll keep it simple, and let me go ahead and do this. 02:15:32.780 --> 02:15:37.250 Let me just do the math using the type of variable that I should be here. 02:15:37.250 --> 02:15:43.240 Let me do not int, but float z equals x divided by y. 02:15:43.240 --> 02:15:45.730 And now let me go ahead and print out the value of z. 02:15:45.730 --> 02:15:47.605 Strictly speaking, I don't need the variable. 02:15:47.605 --> 02:15:50.830 But I'm trying to be pedantic and actually use a float explicitly 02:15:50.830 --> 02:15:52.900 this time so we see a real number. 02:15:52.900 --> 02:15:57.760 All right, let me go ahead and do make calculator, ./calculator. 02:15:57.760 --> 02:16:00.610 1 divided by 3 equals-- 02:16:00.610 --> 02:16:04.420 damn, now it's just showing me more zeros, which clearly isn't the case. 02:16:04.420 --> 02:16:08.750 Well, this is because of an issue that we'll generally call truncation. 02:16:08.750 --> 02:16:12.320 So truncation is just a term of art that means if you take an integer 02:16:12.320 --> 02:16:15.760 and you divide it by an integer, even if you get a fractional value, 02:16:15.760 --> 02:16:18.880 the fraction just gets thrown away because you're only 02:16:18.880 --> 02:16:21.062 doing integer-based math. 02:16:21.062 --> 02:16:23.020 So if there's anything after the decimal point, 02:16:23.020 --> 02:16:25.280 it just gets truncated, literally discarded. 02:16:25.280 --> 02:16:27.460 So what should 1 divided by 3 be? 02:16:27.460 --> 02:16:31.810 Obviously, 0.33333333-- ad nauseum. 02:16:31.810 --> 02:16:34.670 Fortunately, you throw away everything after the decimal point, 02:16:34.670 --> 02:16:37.000 which leaves you still with just 0. 02:16:37.000 --> 02:16:40.510 And even though I'm seeing more zeros, that's because we threw away all 02:16:40.510 --> 02:16:41.049 of the 3's. 02:16:41.049 --> 02:16:44.200 That is just what happens when you use integers and do 02:16:44.200 --> 02:16:46.090 any kind of division like that. 02:16:46.090 --> 02:16:47.959 But there is a solution. 02:16:47.959 --> 02:16:53.320 We can actually convert, or cast, integers to floating point values. 02:16:53.320 --> 02:16:56.230 So we can tell C, I know this is an integer now. 02:16:56.230 --> 02:16:59.290 But go ahead and treat it as though it has a decimal point, even 02:16:59.290 --> 02:17:01.690 if it's .0 At the end of the number. 02:17:01.690 --> 02:17:06.100 So I can go into this, and I can use parentheses and literally write 02:17:06.100 --> 02:17:07.750 "float" in parentheses. 02:17:07.750 --> 02:17:12.700 And over here for y, I can literally use parentheses and convert y to a float. 02:17:12.700 --> 02:17:15.129 The term of art here is type casting. 02:17:15.129 --> 02:17:19.330 You're converting one type to another effectively, or technically treating 02:17:19.330 --> 02:17:23.080 one type as though it's another even if it doesn't necessarily 02:17:23.080 --> 02:17:24.430 have a mathematical impact. 02:17:24.430 --> 02:17:28.959 But what it means now is that z will be defined 02:17:28.959 --> 02:17:31.219 by dividing one float by another. 02:17:31.219 --> 02:17:33.700 So truncation will not now happen. 02:17:33.700 --> 02:17:36.580 So let me do make calculator, ./calculator. 02:17:36.580 --> 02:17:39.100 And now 1 divided by 3, there it is. 02:17:39.100 --> 02:17:41.480 Now the math is actually correct. 02:17:41.480 --> 02:17:45.770 But my God, we had to jump through hoops just to get this to work. 02:17:45.770 --> 02:17:48.610 So to be clear, the two issues we-- well, the issue we encountered 02:17:48.610 --> 02:17:49.480 was truncation. 02:17:49.480 --> 02:17:52.389 If you divide an int by an int, you will get an int no matter 02:17:52.389 --> 02:17:54.070 what it should be mathematically. 02:17:54.070 --> 02:17:59.020 But if you instead type cast the values, the variables to a floating point 02:17:59.020 --> 02:18:03.610 value, or a double for that matter, then a float divided by a float will give 02:18:03.610 --> 02:18:06.520 you a float and preserve all of those 3's. 02:18:06.520 --> 02:18:10.870 But here's another catch, or at least a limitation potentially with computers. 02:18:10.870 --> 02:18:14.379 What if I go ahead here and do-- 02:18:14.379 --> 02:18:15.559 let me do this. 02:18:15.559 --> 02:18:18.820 Let me show you one trick here, even though the syntax is a bit weird. 02:18:18.820 --> 02:18:25.750 Instead of printing out %f alone, let me print out % dot, 02:18:25.750 --> 02:18:30.080 maybe 5f So this is weird syntax. 02:18:30.080 --> 02:18:32.350 And it's only specific to printf. 02:18:32.350 --> 02:18:36.770 "%.5f" means 'show me five decimal places specifically.' 02:18:36.770 --> 02:18:40.480 So if I do make calculator, ./calculator, 1, 3, voila, 02:18:40.480 --> 02:18:43.010 I get five decimal places. 02:18:43.010 --> 02:18:44.469 If I want six, let's do this. 02:18:44.469 --> 02:18:45.969 I'll change the code to 6. 02:18:45.969 --> 02:18:52.337 Make calculator, ./calculator, 1, 3, and now I get six 3's instead. 02:18:52.337 --> 02:18:54.879 All right, well, wouldn't it be nice to be even more precise? 02:18:54.879 --> 02:18:59.209 Let's give me 20 significant digits after the decimal point. 02:18:59.209 --> 02:19:04.420 So make calculator, ./calculator, 1 divided by 3, and-- woo. 02:19:04.420 --> 02:19:09.481 So your middle school teacher seems to have lied to you at this point. 02:19:09.481 --> 02:19:14.620 1 divided by 3 is apparently not 0.33333 with a line over it, 02:19:14.620 --> 02:19:17.350 or just infinite number of 3's. 02:19:17.350 --> 02:19:19.690 OK, that's not quite the right conclusion, though. 02:19:19.690 --> 02:19:20.230 Oops. 02:19:20.230 --> 02:19:24.820 Why might I be seeing these weird numbers instead 02:19:24.820 --> 02:19:28.200 of just lots of 3's, intuitively? 02:19:31.340 --> 02:19:32.999 Why this rounding error? 02:19:32.999 --> 02:19:33.499 Yeah? 02:19:33.499 --> 02:19:36.307 STUDENT: The computer just has a [? limited ?] [? memory. ?] So 02:19:36.307 --> 02:19:37.665 there's [INAUDIBLE] 02:19:37.665 --> 02:19:38.540 DAVID MALAN: Exactly. 02:19:38.540 --> 02:19:41.270 The computer only has limited memory, finite memory. 02:19:41.270 --> 02:19:44.840 So it just can't represent every possible number in the universe 02:19:44.840 --> 02:19:48.240 because we know from grade school there are infinitely many of those numbers. 02:19:48.240 --> 02:19:52.520 So what you're essentially seeing is the closest it can actually get. 02:19:52.520 --> 02:19:56.120 It's rounding to the nearest floating point value, if you will. 02:19:56.120 --> 02:19:58.850 And it also relates to how the numbers themselves are represented 02:19:58.850 --> 02:20:00.145 in memory underneath the hood. 02:20:00.145 --> 02:20:01.520 I can do a little better, though. 02:20:01.520 --> 02:20:02.330 Let me zoom out. 02:20:02.330 --> 02:20:06.530 And let me upgrade, so to speak, from 32 bits to 64 bits and use 02:20:06.530 --> 02:20:07.400 doubles instead. 02:20:07.400 --> 02:20:09.410 I can still use %f. 02:20:09.410 --> 02:20:11.030 You don't use %d for double. 02:20:11.030 --> 02:20:14.750 Let me do make calculator again, ./calculator, 1, 3. 02:20:14.750 --> 02:20:17.490 I get more 3's but still some rounding. 02:20:17.490 --> 02:20:21.842 It's more precise, but it's not 100% accurate, 02:20:21.842 --> 02:20:24.050 because that's just not going to be possible in terms 02:20:24.050 --> 02:20:25.320 of the computer's memory. 02:20:25.320 --> 02:20:29.450 So this is a whole other issue known as floating point imprecision, which 02:20:29.450 --> 02:20:31.910 is another type of limitation. 02:20:31.910 --> 02:20:34.640 We saw integer overflow, if integers can only 02:20:34.640 --> 02:20:37.860 count so high before you run out of bits and things wrap around. 02:20:37.860 --> 02:20:40.350 Floating point imprecision means that you can't possibly 02:20:40.350 --> 02:20:43.470 represent the infinite number of real numbers that exist in the universe 02:20:43.470 --> 02:20:46.830 if you only have a finite amount of memory. 02:20:46.830 --> 02:20:49.710 You would need an infinite number of bits, it would seem. 02:20:49.710 --> 02:20:51.902 So these are two issues that actually fundamentally 02:20:51.902 --> 02:20:53.610 can influence the correctness not only of 02:20:53.610 --> 02:20:55.260 your code but code in the real world. 02:20:55.260 --> 02:20:56.820 And case in point, back in my day-- 02:20:56.820 --> 02:20:59.310 I graduated in 1999-- and a lot of the world 02:20:59.310 --> 02:21:01.350 thought the world was going to end around then 02:21:01.350 --> 02:21:06.180 because around the time the years rolled over from 1999 to 2000, 02:21:06.180 --> 02:21:08.850 there was a lot of old software still running in the world. 02:21:08.850 --> 02:21:12.450 And in fact, that old software, reasonably so, 02:21:12.450 --> 02:21:14.740 only used two digits to represent years. 02:21:14.740 --> 02:21:15.240 Why? 02:21:15.240 --> 02:21:17.200 Memory was very expensive early on. 02:21:17.200 --> 02:21:20.910 And if you could use half as much memory to store a year, that was a win. 02:21:20.910 --> 02:21:21.870 That saved you money. 02:21:21.870 --> 02:21:23.310 That saved you memory. 02:21:23.310 --> 02:21:25.350 The problem though, of course, is that a lot 02:21:25.350 --> 02:21:29.970 of old software from the '70s and prior was still running in 1999. 02:21:29.970 --> 02:21:32.970 And unless companies or individuals updated that software, 02:21:32.970 --> 02:21:39.112 1999 might be mistaken for the year 1900 instead of 2000, 02:21:39.112 --> 02:21:41.320 because all of the code just assumed that, of course, 02:21:41.320 --> 02:21:42.850 we're talking about the 1900s. 02:21:42.850 --> 02:21:45.120 This code is not going to be running 50 years later, 02:21:45.120 --> 02:21:46.762 but it was still in that case. 02:21:46.762 --> 02:21:48.720 So people had to scramble, and they essentially 02:21:48.720 --> 02:21:53.310 had to solve this by using more digits, so upgrading from two to four. 02:21:53.310 --> 02:21:55.590 Nowadays, and really since the '70s too, we've 02:21:55.590 --> 02:21:59.190 used 32-bit integers to keep track of time, 02:21:59.190 --> 02:22:03.120 specifically keeping track of the number of seconds 02:22:03.120 --> 02:22:08.400 using an integer from January 1, 1970, the so-called epoch whereby 02:22:08.400 --> 02:22:11.800 that's just an arbitrary date early on where we just started counting time. 02:22:11.800 --> 02:22:14.430 So all of the clocks in your Macs, PCs, and phones pretty much 02:22:14.430 --> 02:22:17.280 just have a single integer that gets updated every second, 02:22:17.280 --> 02:22:20.080 but it's just keeping track not of absolute time per se, 02:22:20.080 --> 02:22:23.460 but how many seconds have passed since January 1, 1970, 02:22:23.460 --> 02:22:25.710 just because that's the date humans chose. 02:22:25.710 --> 02:22:28.650 The problem is you can only count as high as 4 billion, 02:22:28.650 --> 02:22:31.950 give or take, with 32 bits and actually 2 billion, give or take, 02:22:31.950 --> 02:22:34.180 if you support negative numbers, as well. 02:22:34.180 --> 02:22:37.500 And the problem with that is that we're about to trip over the same issue 02:22:37.500 --> 02:22:39.450 again in not too long from now. 02:22:39.450 --> 02:22:45.760 This is the 2038 problem because in the year 2038, on that date, mark my words, 02:22:45.760 --> 02:22:46.830 things could break again. 02:22:46.830 --> 02:22:47.430 Why? 02:22:47.430 --> 02:22:50.820 Because that 32-bit value is going to accidentally wrap 02:22:50.820 --> 02:22:53.873 around back to a 0 or a negative value. 02:22:53.873 --> 02:22:56.290 So we're going to go through the whole darn process again. 02:22:56.290 --> 02:22:59.190 Now, thankfully the solution, as you might expect, is kind of just 02:22:59.190 --> 02:23:01.470 to kick the can even further down the road 02:23:01.470 --> 02:23:07.050 and use 64 bits, which I think will get us another 290 million years of runway. 02:23:07.050 --> 02:23:08.290 It's more than twice. 02:23:08.290 --> 02:23:10.527 So it's not our problem anymore at that point. 02:23:10.527 --> 02:23:12.610 But that's fundamentally going to be the solution. 02:23:12.610 --> 02:23:15.160 But it will still be finite. 02:23:15.160 --> 02:23:18.240 So we're just deferring to our descendants 02:23:18.240 --> 02:23:21.150 to actually deal with the issue some millions of years from now 02:23:21.150 --> 02:23:22.930 if these things are still running. 02:23:22.930 --> 02:23:26.010 So if that does happen, here's the specific date 02:23:26.010 --> 02:23:28.290 that, in 2038, all of a sudden our clocks will still 02:23:28.290 --> 02:23:32.400 think because a negative number will get subtracted to the current epoch time. 02:23:32.400 --> 02:23:35.140 So it will think we're back in 1901. 02:23:35.140 --> 02:23:38.170 So this has had some fun and very real world implications. 02:23:38.170 --> 02:23:41.250 So for instance, this is the game Pac-Man, which you might have played. 02:23:41.250 --> 02:23:44.020 It kind of came out around my day, back in time. 02:23:44.020 --> 02:23:48.950 And if you get to the 256th level, this unfortunately 02:23:48.950 --> 02:23:50.700 is what happens because they didn't really 02:23:50.700 --> 02:23:54.280 expect that players would spend all this much time playing Pac-Man apparently. 02:23:54.280 --> 02:23:56.370 And they didn't really have a condition saying, 02:23:56.370 --> 02:23:59.832 you win if you get to the 255th or 266th level. 02:23:59.832 --> 02:24:02.790 And so what happens here essentially is that the whole screen gets very 02:24:02.790 --> 02:24:06.120 garbled because there's an integer in the original Pac-Man that 02:24:06.120 --> 02:24:11.100 counts to 256, but that's too big, so it wraps back around to 0. 02:24:11.100 --> 02:24:14.700 And it doesn't know when to stop printing fruits on the screen, 02:24:14.700 --> 02:24:16.260 as in this case, to collect. 02:24:16.260 --> 02:24:19.470 Another example of this is actually from the original Donkey Kong 02:24:19.470 --> 02:24:24.420 game, which looks something like this in my day, too, whereby in Donkey Kong, 02:24:24.420 --> 02:24:26.880 there was this mathematical formula, whereby 02:24:26.880 --> 02:24:31.740 the number of seconds you have to solve the game was a function of 10 times 02:24:31.740 --> 02:24:34.500 your current level number plus the number 4. 02:24:34.500 --> 02:24:36.330 That dictated how many seconds you get. 02:24:36.330 --> 02:24:39.480 So of course, the higher the level, you get more and more time 02:24:39.480 --> 02:24:41.130 as the level climbs. 02:24:41.130 --> 02:24:47.580 Unfortunately, once you hit level 22, the math ends up being 10 times 02:24:47.580 --> 02:24:51.690 22 plus 4, which gives you the number 260. 02:24:51.690 --> 02:24:55.290 And they, too, were using 8-bit values, a single byte 02:24:55.290 --> 02:25:00.520 to represent numbers, which means 260 is bigger than 256. 02:25:00.520 --> 02:25:02.520 And the way that math worked out was, well, 02:25:02.520 --> 02:25:08.250 260 minus 256, if it wraps back around, gave people four seconds to solve level 02:25:08.250 --> 02:25:10.440 22, which is just impossible. 02:25:10.440 --> 02:25:12.480 Like, Mario can't even get up a couple of levels 02:25:12.480 --> 02:25:15.040 or so from where he actually was. 02:25:15.040 --> 02:25:17.400 So that, too, was sort of a well-known bug, 02:25:17.400 --> 02:25:20.680 as well, since that works out to be there. 02:25:20.680 --> 02:25:25.260 Lastly, and this one is all the more real, in 2015, 02:25:25.260 --> 02:25:30.150 Boeing 787 was documented as having not a hardware bug but a software bug 02:25:30.150 --> 02:25:31.560 in the following sense. 02:25:31.560 --> 02:25:37.060 "A model 787 airplane that has been powered continuously for 248 days 02:25:37.060 --> 02:25:42.430 can lose all of its power due to the control unit simultaneously going 02:25:42.430 --> 02:25:43.690 into failsafe mode. 02:25:43.690 --> 02:25:48.100 This condition was caused by a software counter that will overflow 02:25:48.100 --> 02:25:51.700 after 248 days of continuous power. 02:25:51.700 --> 02:25:55.720 Boeing at the time was in the process of developing a CPU software upgrade that 02:25:55.720 --> 02:25:57.250 will remedy the unsafe condition." 02:25:57.250 --> 02:25:58.310 And people did the math. 02:25:58.310 --> 02:26:02.440 It turns out that Boeing was probably using an integer that was 32 bits. 02:26:02.440 --> 02:26:06.650 And they were keeping track of time not in seconds but hundredths of seconds, 02:26:06.650 --> 02:26:12.830 because if you do out the math, after a 32-bit value has reached 4 billion-- 02:26:12.830 --> 02:26:18.650 or 2 billion one hundredths of a second, the number wraps around back to 0, 02:26:18.650 --> 02:26:19.840 or negative 2 billion. 02:26:19.840 --> 02:26:23.480 And the implications was literally the plane's power would stop. 02:26:23.480 --> 02:26:26.770 And if you can believe it, if you grew up with Windows, macOS, or whatnot, 02:26:26.770 --> 02:26:29.080 anyone want to conjecture what the solution was 02:26:29.080 --> 02:26:33.550 until Boeing updated their software? 02:26:33.550 --> 02:26:35.295 STUDENT: Turn it off, turn it back on. 02:26:35.295 --> 02:26:37.128 DAVID MALAN: Turn the plane off, and turn it 02:26:37.128 --> 02:26:41.280 back on because that has the effect of resetting its memory and therefore 02:26:41.280 --> 02:26:43.200 all of its variables back to 0. 02:26:43.200 --> 02:26:47.910 So this is ultimately to say as you dive into problem set 1, your first in C, 02:26:47.910 --> 02:26:51.360 you, too, will make quite a few mistakes when it comes to correctness. 02:26:51.360 --> 02:26:54.840 You, too, will encounter opportunities for better design and better style. 02:26:54.840 --> 02:26:57.272 In the real world, there are very much these issues. 02:26:57.272 --> 02:26:59.730 So even if you struggle, know that for better or for worse, 02:26:59.730 --> 02:27:00.900 you're in very good company. 02:27:00.900 --> 02:27:03.567 But some three months from now, you will be in much better shape 02:27:03.567 --> 02:27:06.210 because this was week 1, and this is CS50. 02:27:06.210 --> 02:27:07.710 [APPLAUSE] 02:27:11.310 --> 02:27:14.360 [INTRIGUING MUSIC]