WEBVTT X-TIMESTAMP-MAP=LOCAL:00:00:00.000,MPEGTS:900000 00:00:00.000 --> 00:00:02.988 [REEL-TO-REEL PLAYER STARTING] 00:00:02.988 --> 00:00:05.976 [MUSIC PLAYING] 00:01:13.350 --> 00:01:16.090 DAVID J. MALAN: All right, this is CS50. 00:01:16.090 --> 00:01:19.090 And this is week 1, wherein we continue programming, 00:01:19.090 --> 00:01:22.420 but we do it in a different language because recall last time, we 00:01:22.420 --> 00:01:25.060 focused on this graphical language called Scratch. 00:01:25.060 --> 00:01:28.360 But we use Scratch, not only because it's sort of fun and accessible, 00:01:28.360 --> 00:01:31.750 but because it allows us to explore a lot of these concepts here, 00:01:31.750 --> 00:01:35.810 namely functions, and conditionals, Boolean expressions, loops, variables, 00:01:35.810 --> 00:01:36.410 and more. 00:01:36.410 --> 00:01:41.050 And so, indeed, even if today's syntax, as we transition to this new language 00:01:41.050 --> 00:01:44.980 called C, feels a little bit cryptic, maybe a little intimidating at first, 00:01:44.980 --> 00:01:48.040 and you don't quite see all of the meaning of the symbols 00:01:48.040 --> 00:01:51.310 beyond the syntax itself, realize that the ideas are ultimately 00:01:51.310 --> 00:01:52.670 going to be the same. 00:01:52.670 --> 00:01:55.870 In fact, as we transition from what was last week-- 00:01:55.870 --> 00:02:00.017 a Hello World program that looked a little something like this-- this week, 00:02:00.017 --> 00:02:02.350 of course, it's going to now look a little more cryptic. 00:02:02.350 --> 00:02:04.350 It's going to look a little something like this. 00:02:04.350 --> 00:02:06.370 And now even if you can't quite distinguish 00:02:06.370 --> 00:02:08.479 what all of the various symbols mean in this code, 00:02:08.479 --> 00:02:10.120 it turns out that at the end of the day, it's 00:02:10.120 --> 00:02:11.578 indeed going to do what you expect. 00:02:11.578 --> 00:02:14.170 It's just going to say, hello, world on the screen, 00:02:14.170 --> 00:02:15.370 just like we did in Scratch. 00:02:15.370 --> 00:02:19.610 So let's start to apply some terminology to these tokens first. 00:02:19.610 --> 00:02:22.332 So what we're about to see, what we're about to write henceforth, 00:02:22.332 --> 00:02:24.040 we're going to start calling source code. 00:02:24.040 --> 00:02:27.908 Code that you the human programmer write is just henceforth called source code. 00:02:27.908 --> 00:02:29.200 Doesn't matter if it's Scratch. 00:02:29.200 --> 00:02:32.370 Doesn't matter if it's C. Doesn't matter if it's Python before long. 00:02:32.370 --> 00:02:34.120 Source code is the general term for really 00:02:34.120 --> 00:02:37.330 what you and I as human programmers will ultimately write. 00:02:37.330 --> 00:02:42.190 Of course, computers don't understand source code, it turns out. 00:02:42.190 --> 00:02:46.200 Computers don't understand Scratch and Puzzle Pieces, per se, or C code 00:02:46.200 --> 00:02:47.200 like we're about to see. 00:02:47.200 --> 00:02:49.870 They only understand this, which we called what last week? 00:02:49.870 --> 00:02:50.650 AUDIENCE: Zeros and ones. 00:02:50.650 --> 00:02:51.525 DAVID J. MALAN: Yeah. 00:02:51.525 --> 00:02:53.080 So this is binary, zeros and ones. 00:02:53.080 --> 00:02:56.470 But really, it's just information represented in binary. 00:02:56.470 --> 00:03:00.370 And in fact, the technical term now for patterns of zeros and ones 00:03:00.370 --> 00:03:04.810 that a computer not only understands how to interpret as letters, or numbers, 00:03:04.810 --> 00:03:09.520 or colors, or images, or more, but knows how to execute as well henceforth 00:03:09.520 --> 00:03:12.880 is going to be called machine code to contrast it with source code. 00:03:12.880 --> 00:03:15.160 So whereas you and I, the humans, write source code, 00:03:15.160 --> 00:03:18.860 it's the computer that ultimately only understands machine code. 00:03:18.860 --> 00:03:21.940 And even though we won't get into the details of exactly what pattern 00:03:21.940 --> 00:03:27.010 of symbols means what, you'll see that in this kind of pattern of zeros 00:03:27.010 --> 00:03:28.600 and ones, there's going to be numbers. 00:03:28.600 --> 00:03:29.530 There's going to be letters. 00:03:29.530 --> 00:03:32.200 But there's also going to be instructions because, indeed, computers 00:03:32.200 --> 00:03:35.140 are really good at doing things-- addition, subtraction, moving things 00:03:35.140 --> 00:03:36.430 in and out of memory. 00:03:36.430 --> 00:03:40.720 And suffice it to say that the Macs, the PCs, the other computers of the world 00:03:40.720 --> 00:03:44.740 have just decided as a society what certain patterns of zeros and ones 00:03:44.740 --> 00:03:48.220 mean when it comes to operations as well-- so not just data, 00:03:48.220 --> 00:03:49.200 but instructions. 00:03:49.200 --> 00:03:50.950 But those patterns are not something we're 00:03:50.950 --> 00:03:52.575 going to focus on in a class like this. 00:03:52.575 --> 00:03:55.450 We're going to focus on the higher level software side of things, 00:03:55.450 --> 00:03:58.910 simply assuming that we need to somehow output machine code. 00:03:58.910 --> 00:04:02.050 So it turns out, then, that this problem we 00:04:02.050 --> 00:04:04.300 have to solve getting from source code to machine code 00:04:04.300 --> 00:04:07.120 actually fits into the same paradigm as last time. 00:04:07.120 --> 00:04:11.230 But the input in this case is going to be source code on the one hand. 00:04:11.230 --> 00:04:13.750 That's what you and I ideally will write so that we 00:04:13.750 --> 00:04:15.430 don't have to write zeros and ones. 00:04:15.430 --> 00:04:18.140 But we need to somehow output machine code 00:04:18.140 --> 00:04:19.990 because that's what your Macs, PCs, phones 00:04:19.990 --> 00:04:21.730 are actually going to understand. 00:04:21.730 --> 00:04:25.390 Well, it turns out there are special programs in life whose purpose is 00:04:25.390 --> 00:04:28.690 to do exactly this conversion-- convert the source code you 00:04:28.690 --> 00:04:32.320 and I write to the machine code that our phones and computers understand. 00:04:32.320 --> 00:04:36.050 And that type of program is going to be called a compiler. 00:04:36.050 --> 00:04:39.400 So indeed today, we'll introduce you to another piece of software. 00:04:39.400 --> 00:04:40.810 And these come in many forms. 00:04:40.810 --> 00:04:45.580 We'll use a popular one here that allows you to convert source code in C 00:04:45.580 --> 00:04:48.805 to machine code in zeros and ones. 00:04:48.805 --> 00:04:50.680 Now, you didn't have to do this with Scratch. 00:04:50.680 --> 00:04:53.513 In the world of Scratch, it was as simple as clicking the green flag 00:04:53.513 --> 00:04:57.280 because essentially MIT did all of the heavy lifting there figuring out 00:04:57.280 --> 00:05:00.760 how to convert these graphical puzzle pieces to the underlying machine code. 00:05:00.760 --> 00:05:04.420 But now starting today, as we begin to study programming and computer science 00:05:04.420 --> 00:05:06.550 proper, now that power moves to you. 00:05:06.550 --> 00:05:09.340 And it's up to you now to do that kind of conversion. 00:05:09.340 --> 00:05:12.160 But thankfully, the fact that these compilers exist 00:05:12.160 --> 00:05:14.320 means that you and I don't have to program 00:05:14.320 --> 00:05:17.500 in machine code like our ancestors once upon a time did, 00:05:17.500 --> 00:05:19.973 be it virtually or with physical punch cards, 00:05:19.973 --> 00:05:21.640 like pieces of paper with holes in them. 00:05:21.640 --> 00:05:25.810 You and I get to focus on our keyboard, as such. 00:05:25.810 --> 00:05:29.370 But it's not just going to be a matter today of writing code. 00:05:29.370 --> 00:05:31.120 It's going to be a matter ultimately today 00:05:31.120 --> 00:05:32.930 onward of writing good code as well. 00:05:32.930 --> 00:05:35.180 And this is the kind of thing that you don't just learn overnight. 00:05:35.180 --> 00:05:35.870 It takes time. 00:05:35.870 --> 00:05:36.620 It takes practice. 00:05:36.620 --> 00:05:38.650 Just like writing an essay in any subject 00:05:38.650 --> 00:05:41.050 might take time, and practice, and iteration over time. 00:05:41.050 --> 00:05:44.020 But in a programming class like CS50, we're 00:05:44.020 --> 00:05:48.820 going to aspire to evaluate the quality of code along these three axes, 00:05:48.820 --> 00:05:49.360 generally. 00:05:49.360 --> 00:05:51.040 Is it correct, first and foremost? 00:05:51.040 --> 00:05:52.810 Does the code do what it's supposed to do? 00:05:52.810 --> 00:05:54.460 After all, if it doesn't, well, what was the point 00:05:54.460 --> 00:05:55.835 of writing it in the first place? 00:05:55.835 --> 00:05:59.350 So it goes without saying that you want code you write to be correct. 00:05:59.350 --> 00:06:00.820 And it's obviously not always. 00:06:00.820 --> 00:06:03.340 Again, anytime your Mac, or PC, or phone has crashed, 00:06:03.340 --> 00:06:05.560 some human somewhere wrote buggy-- 00:06:05.560 --> 00:06:07.030 that is code with mistakes. 00:06:07.030 --> 00:06:10.060 But code correctness is going to be the first and foremost goal. 00:06:10.060 --> 00:06:13.930 But then there's a more subjective goal see in time, a matter of design. 00:06:13.930 --> 00:06:16.030 And we saw a little bit of this last week 00:06:16.030 --> 00:06:19.510 when I proposed that we could design even scratch programs better, 00:06:19.510 --> 00:06:22.510 maybe by using loops instead of just by copying and pasting 00:06:22.510 --> 00:06:24.170 the same blocks again and again. 00:06:24.170 --> 00:06:26.080 So design is more subjective. 00:06:26.080 --> 00:06:29.830 It's more of a learned art whereby two people might ultimately 00:06:29.830 --> 00:06:32.882 disagree as to which version of a program is better designed. 00:06:32.882 --> 00:06:35.840 But we'll give you building blocks and principles over the coming weeks 00:06:35.840 --> 00:06:37.840 so that you can have a better sense for yourself 00:06:37.840 --> 00:06:40.090 if your own code is well designed. 00:06:40.090 --> 00:06:41.530 And why is that valuable? 00:06:41.530 --> 00:06:44.980 Well, the better designed your code is, often the faster it's going to run, 00:06:44.980 --> 00:06:47.438 the more maintainable it's going to be by you or colleagues 00:06:47.438 --> 00:06:49.438 if you're working with others in the real world. 00:06:49.438 --> 00:06:50.900 So good design is a good thing. 00:06:50.900 --> 00:06:54.490 It helps you communicate your ideas, just like in a typical English essay. 00:06:54.490 --> 00:06:57.523 And then lastly, we'll talk this week onward about style. 00:06:57.523 --> 00:06:59.690 And this is really just the aesthetics of your code. 00:06:59.690 --> 00:07:04.720 It turns out that computers often don't care how sloppy your actual code is, 00:07:04.720 --> 00:07:08.920 where in the world of code, it turns out that you don't really need 00:07:08.920 --> 00:07:10.750 to indent things in a beautiful way. 00:07:10.750 --> 00:07:13.150 You don't need to paginate things like might in an essay. 00:07:13.150 --> 00:07:16.390 The computer generally does not care, but the human does. 00:07:16.390 --> 00:07:17.817 The teaching assistant does. 00:07:17.817 --> 00:07:19.900 You will care the next day when you're just trying 00:07:19.900 --> 00:07:21.560 to understand what your code does. 00:07:21.560 --> 00:07:24.520 So we'll focus lastly on style, the aesthetics of the code 00:07:24.520 --> 00:07:25.520 that you're writing. 00:07:25.520 --> 00:07:27.280 So where are we going to write code? 00:07:27.280 --> 00:07:28.940 Where are we going to compile code? 00:07:28.940 --> 00:07:32.770 So for this class, not only with C, but the other languages we use later 00:07:32.770 --> 00:07:35.140 in the term, we're going to use a free text 00:07:35.140 --> 00:07:39.280 editor that is program called Visual Studio Code, AKA VS Code. 00:07:39.280 --> 00:07:43.450 It's super popular nowadays, not just for C, but for C++, and Python, 00:07:43.450 --> 00:07:45.970 and Java, and any number of other languages. 00:07:45.970 --> 00:07:49.270 It's a text editor in the sense that it lets you edit text. 00:07:49.270 --> 00:07:52.150 And that's all code is going to be. 00:07:52.150 --> 00:07:54.907 Now, strictly speaking, you could write code on paper/pencil. 00:07:54.907 --> 00:07:56.740 In fact, in high school if you took a class, 00:07:56.740 --> 00:07:59.532 you might have done that one or more times as an in-class exercise. 00:07:59.532 --> 00:08:02.532 You can't run it on paper, of course, but you could write it, certainly. 00:08:02.532 --> 00:08:04.570 You could use something like Microsoft Word, 00:08:04.570 --> 00:08:07.240 or Notepad.exe, or Text Edit on the Mac. 00:08:07.240 --> 00:08:09.340 But none of those programs are really designed 00:08:09.340 --> 00:08:12.190 to format the code in the best way for you, 00:08:12.190 --> 00:08:15.250 nor are they designed to let you compile and run the code. 00:08:15.250 --> 00:08:19.120 So VS Code is going to be a tool via which you can do all that 00:08:19.120 --> 00:08:22.240 and more-- write the code, compile the code, run the code. 00:08:22.240 --> 00:08:25.630 So that you all don't have to wrestle with stupid technical support 00:08:25.630 --> 00:08:29.110 headaches at the beginning of the course by installing this software and that 00:08:29.110 --> 00:08:33.070 on your Macs or PCs, we'll use a cloud-based version of VS Code 00:08:33.070 --> 00:08:34.780 at code.cs50.io. 00:08:34.780 --> 00:08:36.580 And that's going to be the exact same tool. 00:08:36.580 --> 00:08:38.860 And the goal, then, is by the end of the semester 00:08:38.860 --> 00:08:43.240 to migrate you off of that cloud-based environment to your own Mac and PC 00:08:43.240 --> 00:08:46.090 so that even if CS50 is the only CS class you ever take, 00:08:46.090 --> 00:08:50.290 you're 100% equipped to continue writing code after the class using 00:08:50.290 --> 00:08:54.010 not something that's even CS50-specific, but a de facto industry 00:08:54.010 --> 00:08:55.760 standard, at least for some time. 00:08:55.760 --> 00:08:59.020 So what's this program VS Code going to look like, be it on your Mac, 00:08:59.020 --> 00:09:00.990 PC, or initially in your browser? 00:09:00.990 --> 00:09:02.990 It's going to look a little something like this. 00:09:02.990 --> 00:09:05.657 And there's going to be several different regions to the screen. 00:09:05.657 --> 00:09:07.450 And pictured here is that very same code I 00:09:07.450 --> 00:09:10.335 keep proposing as the simplest program you can write in C. 00:09:10.335 --> 00:09:12.460 And what are these different regions of the screen? 00:09:12.460 --> 00:09:15.440 Well, there's essentially these four here. 00:09:15.440 --> 00:09:19.660 So first, highlighted up top is going to be one or more tabs where 00:09:19.660 --> 00:09:21.160 you're going to actually write code. 00:09:21.160 --> 00:09:23.230 So much like in Google Docs or Microsoft Word, 00:09:23.230 --> 00:09:24.940 you can have tabs open with files. 00:09:24.940 --> 00:09:28.330 Similarly in VS Code-- or, really, any programming environment-- 00:09:28.330 --> 00:09:30.830 you generally nowadays have tabs of some sort. 00:09:30.830 --> 00:09:34.480 And this is going to be a tab containing a file, it seems, called hello.c. 00:09:34.480 --> 00:09:38.020 And that's going to be the very first file we write in just a moment. 00:09:38.020 --> 00:09:40.720 Down here, though, is going to be an interface that many of you 00:09:40.720 --> 00:09:41.920 might not know. 00:09:41.920 --> 00:09:44.170 This is what's called a terminal window. 00:09:44.170 --> 00:09:47.920 And a terminal window provides what's generally called a Command Line 00:09:47.920 --> 00:09:49.720 Interface, or CLI. 00:09:49.720 --> 00:09:53.680 And this is in contrast with a Graphical User Interface, or GUI. 00:09:53.680 --> 00:09:57.760 Now, you and I, every day, are using GUIs on our phones, on our PCs. 00:09:57.760 --> 00:10:01.420 And a GUI is literally graphical-- so menus, and buttons, and icons. 00:10:01.420 --> 00:10:04.060 And you generally use your finger or a trackpad 00:10:04.060 --> 00:10:06.380 or a mouse or something like that to interact with it. 00:10:06.380 --> 00:10:08.410 But it turns out that many programmers-- they're 00:10:08.410 --> 00:10:11.770 saying most programmers, at least over time, come to prefer, 00:10:11.770 --> 00:10:14.620 not a GUI, but a CLI, a Command Line Interface 00:10:14.620 --> 00:10:20.650 where you actually do everything somewhat arcanely via keyboard alone. 00:10:20.650 --> 00:10:21.250 Why? 00:10:21.250 --> 00:10:24.610 Well, it turns out, there's just more features built in to most computers 00:10:24.610 --> 00:10:26.260 if you can access them with a keyboard. 00:10:26.260 --> 00:10:29.530 It turns out, most of us can type faster than you can point and click. 00:10:29.530 --> 00:10:32.330 And so that ends up being an efficiency gain over time. 00:10:32.330 --> 00:10:35.140 So in time, will you get comfortable using this terminal 00:10:35.140 --> 00:10:39.370 window to do things like compile your code or make your program 00:10:39.370 --> 00:10:40.390 as well as run it. 00:10:40.390 --> 00:10:43.810 So you won't be in the habit initially of just double clicking icons 00:10:43.810 --> 00:10:45.800 like we do in our typical real world. 00:10:45.800 --> 00:10:47.890 You'll do it the programmer's way. 00:10:47.890 --> 00:10:51.820 But it's not to the exclusion of adding icons, and clickability, and more. 00:10:51.820 --> 00:10:53.950 On the left-hand side of VS Code, there's 00:10:53.950 --> 00:10:56.920 going to be a somewhat familiar File Explorer, 00:10:56.920 --> 00:11:00.040 some kind of hierarchical tree, like on your Mac or PC where you can 00:11:00.040 --> 00:11:02.110 see all of the files in your account. 00:11:02.110 --> 00:11:04.390 Pictured here, for instance, is just hello.c, 00:11:04.390 --> 00:11:06.140 which I'll create myself in a moment. 00:11:06.140 --> 00:11:09.343 And then far away on the left is the so-called Activity Bar, 00:11:09.343 --> 00:11:12.260 and this is where you just get a lot of traditional menus and buttons. 00:11:12.260 --> 00:11:16.250 So VS Code itself gives you both a GUI and a CLI. 00:11:16.250 --> 00:11:19.958 But it's within the CLI, the terminal window, the bottom region of the screen 00:11:19.958 --> 00:11:22.250 that we're actually going to type most of our commands. 00:11:22.250 --> 00:11:25.417 And in general in class, I'm going to hide all of the graphical stuff that's 00:11:25.417 --> 00:11:28.380 just not of all that much interest. 00:11:28.380 --> 00:11:30.710 So with that said, let me actually change over 00:11:30.710 --> 00:11:32.878 to a live version of VS Code. 00:11:32.878 --> 00:11:34.670 And I've indeed hidden in the Activity Bar. 00:11:34.670 --> 00:11:36.470 I've indeed hidden the File Explorer. 00:11:36.470 --> 00:11:39.380 So what I have here for visibility sake is a really big area 00:11:39.380 --> 00:11:42.840 for writing code and a really big terminal window at the bottom. 00:11:42.840 --> 00:11:45.260 You'll see in the terminal window, there's dollar sign. 00:11:45.260 --> 00:11:47.160 And this doesn't mean any form of currency. 00:11:47.160 --> 00:11:51.230 This is just the standard symbol that represents type commands here. 00:11:51.230 --> 00:11:53.480 So the fact that there's just dollar sign and a cursor 00:11:53.480 --> 00:11:55.490 means, eventually, that's where I'm going to type commands. 00:11:55.490 --> 00:11:58.020 But first, I'm going to actually create some code. 00:11:58.020 --> 00:12:02.900 So how might I program using VS Code-- be it on my Mac, PC, 00:12:02.900 --> 00:12:07.160 or in this cloud-based environment that you'll get set up for problem set 1-- 00:12:07.160 --> 00:12:08.870 go about writing my first file? 00:12:08.870 --> 00:12:10.610 Well, perhaps the easiest way is this. 00:12:10.610 --> 00:12:14.090 Literally run the command code and then the name of the file 00:12:14.090 --> 00:12:15.200 you want to create. 00:12:15.200 --> 00:12:18.838 Notice that I deliberately end the file with .c in lowercase. 00:12:18.838 --> 00:12:21.380 Notice that I've deliberately lowercased the whole file name. 00:12:21.380 --> 00:12:22.672 And these are just conventions. 00:12:22.672 --> 00:12:24.140 You could use a capital H. 00:12:24.140 --> 00:12:27.260 You kind of could use a capital C. But just don't do that. 00:12:27.260 --> 00:12:30.260 Follow best practices so that it's consistent with what most everyone 00:12:30.260 --> 00:12:31.100 else would do. 00:12:31.100 --> 00:12:33.770 When I hit Enter, I just get an empty tab, 00:12:33.770 --> 00:12:35.540 just like the screenshot a moment ago. 00:12:35.540 --> 00:12:40.100 And it's in this tab where I can now write my very first program in C. 00:12:40.100 --> 00:12:42.620 Unfortunately, it's not quite as user-friendly as Scratch 00:12:42.620 --> 00:12:45.992 where you drag and drop a couple of puzzle pieces and, boom, it's done. 00:12:45.992 --> 00:12:47.450 So I'm going to do this for memory. 00:12:47.450 --> 00:12:49.970 But this, too, will become familiar to you over time. 00:12:49.970 --> 00:12:53.720 I'm going to include something called stdio.h. 00:12:53.720 --> 00:12:57.230 I'm going to type int main, void in parentheses. 00:12:57.230 --> 00:13:01.190 On a new line, I'm going to insert some curly braces, as we'll call them. 00:13:01.190 --> 00:13:03.830 And then I'm going to type printf, and then some 00:13:03.830 --> 00:13:09.200 parentheses, and then in quotes, hello, comma, world, then a backslash, then 00:13:09.200 --> 00:13:12.800 a lowercase n, then a close quote, and then a semicolon 00:13:12.800 --> 00:13:14.280 at the very end of the line. 00:13:14.280 --> 00:13:19.010 So all I've done is recreate, just from memory, that very first program. 00:13:19.010 --> 00:13:21.710 In a little bit, we'll make clear what most of this does. 00:13:21.710 --> 00:13:23.857 But for now, let's just actually run this thing. 00:13:23.857 --> 00:13:26.690 And just like I clicked the green flag last week for the first time, 00:13:26.690 --> 00:13:29.840 let's actually compile and run this program. 00:13:29.840 --> 00:13:33.967 If it were your Mac or PC and Google, or Microsoft, or someone else 00:13:33.967 --> 00:13:36.050 had made the software, at this point in the story, 00:13:36.050 --> 00:13:37.408 we'd be double clicking an icon. 00:13:37.408 --> 00:13:38.450 But we can't do that yet. 00:13:38.450 --> 00:13:39.930 This is still source code. 00:13:39.930 --> 00:13:42.380 So I'm going to click back down in my terminal window. 00:13:42.380 --> 00:13:45.650 Notice I have a second dollar sign below the first, which just 00:13:45.650 --> 00:13:47.880 means it's ready for a second command. 00:13:47.880 --> 00:13:53.000 And now the command via which to make this an actual program, to compile it 00:13:53.000 --> 00:13:56.990 from source code to machine code is, going to be quite simply make 00:13:56.990 --> 00:13:59.360 and then the name of the program I want to make. 00:13:59.360 --> 00:14:03.710 Slight subtlety-- I'm omitting deliberately .c because the program I 00:14:03.710 --> 00:14:05.870 want to make, I just want to call hello. 00:14:05.870 --> 00:14:07.400 Don't write make hello.c. 00:14:07.400 --> 00:14:08.780 Just write make hello. 00:14:08.780 --> 00:14:13.040 And this program make is essentially our compiler. 00:14:13.040 --> 00:14:15.560 Technically speaking, it's a program that automates 00:14:15.560 --> 00:14:17.580 the compilation of my program for me. 00:14:17.580 --> 00:14:20.180 But it is going to see that I've typed the word hello. 00:14:20.180 --> 00:14:25.100 It's going to automatically look now for a file on the hard drive called hello.c 00:14:25.100 --> 00:14:30.690 and convert it from source code in C to machine code in zeros and ones. 00:14:30.690 --> 00:14:37.170 So if I didn't make any typos, Enter, nothing seems to happen. 00:14:37.170 --> 00:14:38.210 And that's a good thing. 00:14:38.210 --> 00:14:41.862 Almost always, if nothing gets outputted on the screen, you did good. 00:14:41.862 --> 00:14:43.070 You didn't make any mistakes. 00:14:43.070 --> 00:14:43.880 You didn't get yelled at. 00:14:43.880 --> 00:14:45.000 There's no error messages. 00:14:45.000 --> 00:14:46.590 So this is actually a good thing. 00:14:46.590 --> 00:14:47.942 How do I now run this program? 00:14:47.942 --> 00:14:50.150 Well, notice I've got a third dollar sign, which just 00:14:50.150 --> 00:14:52.110 means I'm ready for a third command. 00:14:52.110 --> 00:14:55.400 And now I'm going to go ahead and run ./hello. 00:14:55.400 --> 00:14:58.798 And this is admittedly a little weird that you have to do dot slash. 00:14:58.798 --> 00:15:00.590 But for now just take on faith that this is 00:15:00.590 --> 00:15:04.610 how you run a program called hello In your current folder, 00:15:04.610 --> 00:15:07.730 in your current directory in this cloud-based environment. 00:15:07.730 --> 00:15:10.430 All right, crossing my fingers again, hitting Enter. 00:15:10.430 --> 00:15:12.110 And voila. 00:15:12.110 --> 00:15:15.950 My very first program in C, hello, world. 00:15:15.950 --> 00:15:20.480 And now let me go ahead and reveal the File Explorer that I proposed 00:15:20.480 --> 00:15:21.292 exists earlier. 00:15:21.292 --> 00:15:23.750 I'm just going to use the keyboard shortcut to reveal that. 00:15:23.750 --> 00:15:27.000 And generally, I keep it closed because I don't really need to constantly what 00:15:27.000 --> 00:15:28.250 files are in my account. 00:15:28.250 --> 00:15:31.820 But you'll see now in the File Explorer, similar in spirit to a Mac or PC 00:15:31.820 --> 00:15:35.270 but graphically a little different, here's my file, hello.c. 00:15:35.270 --> 00:15:37.520 It's highlighted because I have that tab open. 00:15:37.520 --> 00:15:40.970 But now there's a second file here called just hello. 00:15:40.970 --> 00:15:42.690 That's the name of my program. 00:15:42.690 --> 00:15:46.100 So if you were on a Mac or PC, you would ideally double click that thing. 00:15:46.100 --> 00:15:48.162 You can't do that in a command line environment. 00:15:48.162 --> 00:15:49.370 You have to run it down here. 00:15:49.370 --> 00:15:50.453 But that's all we've done. 00:15:50.453 --> 00:15:53.750 We've created a file called hello.c, and then my compiler 00:15:53.750 --> 00:15:56.240 made the program from that. 00:15:56.240 --> 00:16:00.080 Let me pause here and see if there's any questions because that's 00:16:00.080 --> 00:16:01.970 a lot of magical phrases. 00:16:01.970 --> 00:16:04.450 Yeah? 00:16:04.450 --> 00:16:04.950 Yeah. 00:16:04.950 --> 00:16:08.390 So if you're currently following along, playing along at home 00:16:08.390 --> 00:16:10.890 and you're getting some kind of error message, part of today 00:16:10.890 --> 00:16:13.950 will be for me to deliberately induce some of those error messages. 00:16:13.950 --> 00:16:17.070 For now let me just propose that if you literally did what I did, 00:16:17.070 --> 00:16:19.320 you must have made a typo somewhere. 00:16:19.320 --> 00:16:23.790 And notice that it's indeed standard io-- stdio.h. 00:16:23.790 --> 00:16:25.890 Maybe you typed studio.h? 00:16:25.890 --> 00:16:30.600 OK, super common mistake, I could call you out. 00:16:30.600 --> 00:16:32.280 It is not studio.h. 00:16:32.280 --> 00:16:34.560 It is stdio.h-- so common. 00:16:34.560 --> 00:16:37.658 But this is exactly representative of the kind of stupid headaches 00:16:37.658 --> 00:16:40.200 you're going to run into this week, probably for a few weeks, 00:16:40.200 --> 00:16:41.730 probably, honestly, for a few years. 00:16:41.730 --> 00:16:45.180 But you start to see past these stupid mistakes over time, 00:16:45.180 --> 00:16:47.610 and it just gets easier and easier because the computer is 00:16:47.610 --> 00:16:49.110 going to be so regimented. 00:16:49.110 --> 00:16:50.950 It will only do what you tell it to do. 00:16:50.950 --> 00:16:54.223 And if you say because it's verbally sounds like studio.h, 00:16:54.223 --> 00:16:55.890 it's not going to know what the file is. 00:16:55.890 --> 00:16:58.182 So actually, thank you for tripping over that so early. 00:16:58.182 --> 00:16:59.740 That's super common to happen. 00:16:59.740 --> 00:17:00.240 Yeah? 00:17:00.240 --> 00:17:02.540 AUDIENCE: Why do you have two hello files? 00:17:02.540 --> 00:17:03.799 DAVID J. MALAN: Why do I have to hello files? 00:17:03.799 --> 00:17:04.400 AUDIENCE: Yes. 00:17:04.400 --> 00:17:06.400 DAVID J. MALAN: So why do I have to hello files? 00:17:06.400 --> 00:17:09.170 One is the one I created as the human called hello.c, 00:17:09.170 --> 00:17:10.520 and it's pictured right here. 00:17:10.520 --> 00:17:15.890 But then when I ran make hello, that process compiled my source code 00:17:15.890 --> 00:17:17.040 into machine code. 00:17:17.040 --> 00:17:20.240 So this second file just called hello is the file that 00:17:20.240 --> 00:17:25.700 contains all of those zeros and ones that the server actually understands. 00:17:25.700 --> 00:17:27.200 All right, so yeah, question? 00:17:27.200 --> 00:17:29.710 AUDIENCE: The access to the hello [INAUDIBLE] 00:17:29.710 --> 00:17:31.960 DAVID J. MALAN: If you try clicking on the hello file, 00:17:31.960 --> 00:17:34.270 you'll see in this environment the VS Code, 00:17:34.270 --> 00:17:36.580 quote/unquote, The file is not displayed in the editor 00:17:36.580 --> 00:17:38.230 because it is either binary-- 00:17:38.230 --> 00:17:41.437 AKA zeros and ones-- or uses an unsupported text encoding. 00:17:41.437 --> 00:17:42.520 In this case, it's binary. 00:17:42.520 --> 00:17:43.660 It's zeros and ones. 00:17:43.660 --> 00:17:47.680 Now, you could use software to see those zeros and ones. 00:17:47.680 --> 00:17:50.320 It won't be intellectually enlightening to most any human. 00:17:50.320 --> 00:17:53.165 So VS Code just takes the choice of not showing it to you at all. 00:17:53.165 --> 00:17:56.290 So that would be a common mistake too, clicking on a file you don't intend. 00:17:56.290 --> 00:18:00.190 But the source code is indeed going to be editable by us. 00:18:00.190 --> 00:18:01.900 All right, so I've written this program. 00:18:01.900 --> 00:18:04.780 It seems to magically work, at least with some effort 00:18:04.780 --> 00:18:06.700 if you get every single keystroke right. 00:18:06.700 --> 00:18:08.440 Well, what is it that's going on? 00:18:08.440 --> 00:18:09.460 And how is this working? 00:18:09.460 --> 00:18:13.180 Well, first of all, notice that even without my highlighting things 00:18:13.180 --> 00:18:17.740 or choosing buttons for menus, notice that it's already color coded. 00:18:17.740 --> 00:18:20.980 And yet, I wasn't highlighting along the way in Google Docs style, 00:18:20.980 --> 00:18:22.510 changing the color, certainly. 00:18:22.510 --> 00:18:25.960 Well, it turns out, what VS Code and most programming environments 00:18:25.960 --> 00:18:29.600 nowadays do for you automatically is syntax highlighting. 00:18:29.600 --> 00:18:33.850 So syntax highlighting is just this feature of typical text editors 00:18:33.850 --> 00:18:36.760 nowadays that analyzes the code that you've typed. 00:18:36.760 --> 00:18:40.000 And when it notices certain types of keystrokes, 00:18:40.000 --> 00:18:43.900 things that represent functions, or conditionals, or loops, or variables-- 00:18:43.900 --> 00:18:47.570 a lot of the vocab from last week-- it just highlights it ever so differently 00:18:47.570 --> 00:18:48.070 for you. 00:18:48.070 --> 00:18:51.430 So main, for instance, which we'll soon see, is in purple here. 00:18:51.430 --> 00:18:53.890 Int, and void, and include are in red. 00:18:53.890 --> 00:18:55.630 Hello, world is in blue. 00:18:55.630 --> 00:18:57.390 My parentheses are in green. 00:18:57.390 --> 00:18:59.290 This will totally vary by programmer too. 00:18:59.290 --> 00:19:02.995 In fact, if you do want to change these colors for problem set 1 00:19:02.995 --> 00:19:04.870 for your own environment, you can poke around 00:19:04.870 --> 00:19:07.190 VS Code Settings via the gear icon. 00:19:07.190 --> 00:19:09.820 You can change to a different color theme. 00:19:09.820 --> 00:19:13.480 Syntax highlighting isn't some specific color scheme like it is in Scratch. 00:19:13.480 --> 00:19:16.485 It just generally is to each human their own preference. 00:19:16.485 --> 00:19:18.610 But that's all that's happening here is this notion 00:19:18.610 --> 00:19:20.830 of syntax highlighting at the moment. 00:19:20.830 --> 00:19:25.510 Well, what more is going on in this code before I run it, but rather write it? 00:19:25.510 --> 00:19:28.790 Well, it looks a little something like this if I take away all of the colors. 00:19:28.790 --> 00:19:30.550 And then just for discussion's sake, let me go ahead 00:19:30.550 --> 00:19:32.500 and color it a little more like Scratch. 00:19:32.500 --> 00:19:34.690 Recall that our very first Scratch program 00:19:34.690 --> 00:19:39.670 that just said hello, world on the screen had a green flag clicked icon-- 00:19:39.670 --> 00:19:45.070 puzzle piece, roughly in orange, and then a purple say block beneath it. 00:19:45.070 --> 00:19:48.820 So whereas this is the C version, if we run rewind to last week, 00:19:48.820 --> 00:19:50.950 this was the same program in Scratch. 00:19:50.950 --> 00:19:53.090 But what's happening now is exactly the same. 00:19:53.090 --> 00:19:55.060 So if you think back to last week and you've 00:19:55.060 --> 00:19:58.600 got some function, like the say function in purple, 00:19:58.600 --> 00:20:01.270 that might take one or more arguments, like inputs that 00:20:01.270 --> 00:20:03.190 influences what it says on the screen. 00:20:03.190 --> 00:20:05.230 And then functions, recall, can sometimes 00:20:05.230 --> 00:20:08.480 have side effects, like the speech bubble appears on the screen. 00:20:08.480 --> 00:20:11.260 So last week when we used the say block and we 00:20:11.260 --> 00:20:13.840 passed in an argument of hello, world at left, 00:20:13.840 --> 00:20:17.915 we got this visual side effect on the screen that says now hello, world 00:20:17.915 --> 00:20:18.790 in the speech bubble. 00:20:18.790 --> 00:20:23.230 And that's exactly what just happened in VS Code but much, much more textually. 00:20:23.230 --> 00:20:25.900 And let's look a little closer now at the code itself. 00:20:25.900 --> 00:20:29.020 Let me wave my hand at the equivalent of when 00:20:29.020 --> 00:20:32.890 green flag clicked part of my code, and let's focus only 00:20:32.890 --> 00:20:38.350 on the say block in Scratch and the corresponding function in C. 00:20:38.350 --> 00:20:41.770 So if I step through this and I wanted to convert what 00:20:41.770 --> 00:20:44.830 we did last week with the say block to C, 00:20:44.830 --> 00:20:47.645 I would first use the print function-- although that's actually 00:20:47.645 --> 00:20:48.520 a bit of a white lie. 00:20:48.520 --> 00:20:50.440 It's actually the printf function. 00:20:50.440 --> 00:20:52.030 Printf means formatted. 00:20:52.030 --> 00:20:55.360 And it's just a function that allows you to format text on the screen. 00:20:55.360 --> 00:20:58.570 There is no say function in C. There's a printf function. 00:20:58.570 --> 00:21:02.650 What MIT did down the road years ago was they took what existed historically 00:21:02.650 --> 00:21:05.290 as printf, and they simplified it for a broader audience 00:21:05.290 --> 00:21:08.050 by just calling it essentially say instead. 00:21:08.050 --> 00:21:13.450 But notice that now if I want to convert the Scratch code at left to C code 00:21:13.450 --> 00:21:16.250 it right, it's the same shape. 00:21:16.250 --> 00:21:18.940 So MIT deliberately used this white oval, 00:21:18.940 --> 00:21:23.510 if only because it conjures this idea of having parentheses too. 00:21:23.510 --> 00:21:26.770 So on the right, if I want to pass an argument or an input 00:21:26.770 --> 00:21:31.240 to the printf function, I use an open parentheses and a close parentheses. 00:21:31.240 --> 00:21:33.700 In those parentheses, I then type whatever 00:21:33.700 --> 00:21:35.600 it is I want to print on the screen-- 00:21:35.600 --> 00:21:37.460 in this case, hello, comma, world. 00:21:37.460 --> 00:21:39.310 But notice I've deliberately left some room 00:21:39.310 --> 00:21:42.160 because you need some extra keystrokes in the world of C. 00:21:42.160 --> 00:21:44.590 Any time you type out some text-- 00:21:44.590 --> 00:21:49.150 otherwise known as a string of text, to use computer science jargon-- 00:21:49.150 --> 00:21:52.100 you need to quote it, in this case with double quotes. 00:21:52.100 --> 00:21:54.520 Double quote at the left, double quote at the right. 00:21:54.520 --> 00:21:57.730 And notice too I'm going to include some slightly cryptic symbol 00:21:57.730 --> 00:22:01.660 here too-- backslash n, which I also typed and said verbally earlier, 00:22:01.660 --> 00:22:05.480 and then one last nuisance at the end of this, which is a semicolon. 00:22:05.480 --> 00:22:08.890 So suffice it to say, this is why we start with Scratch. 00:22:08.890 --> 00:22:10.960 This, drag and drop, you're good to go. 00:22:10.960 --> 00:22:14.680 In a language like C, printf, parentheses, double quotes, the text 00:22:14.680 --> 00:22:16.630 you want, backslash n, semicolon at the end. 00:22:16.630 --> 00:22:18.970 There's just so much syntactic overhead. 00:22:18.970 --> 00:22:21.290 But at the end of the day, it's just a function. 00:22:21.290 --> 00:22:25.180 And you'll get used to these nuisances like the parentheses, the quotes, 00:22:25.180 --> 00:22:27.130 the semicolon, and the like. 00:22:27.130 --> 00:22:31.810 But things can very easily you go wrong, and it's very easy to make mistakes, 00:22:31.810 --> 00:22:33.380 even with lines of code like this. 00:22:33.380 --> 00:22:34.190 So let me do this. 00:22:34.190 --> 00:22:37.070 Let me go back to VS Code where I have the exact same code. 00:22:37.070 --> 00:22:40.910 Notice that on line 5 is exactly that line of code. 00:22:40.910 --> 00:22:42.910 So this is the equivalent of the say block. 00:22:42.910 --> 00:22:46.090 And let's consider what mistakes I may make early on or even now 00:22:46.090 --> 00:22:49.930 20 years later after learning this that are quite common in general. 00:22:49.930 --> 00:22:52.180 Suppose I forget the semicolon there. 00:22:52.180 --> 00:22:53.380 So easy to do. 00:22:53.380 --> 00:22:54.910 You will do this eventually. 00:22:54.910 --> 00:22:57.970 Let's see what happens now when I go back to my terminal window 00:22:57.970 --> 00:22:59.920 and try to compile my code again. 00:22:59.920 --> 00:23:02.590 Just to keep things tidy, I'm going to clear my screen. 00:23:02.590 --> 00:23:05.170 But that's just for lecture's sake so that we can focus only 00:23:05.170 --> 00:23:06.460 on the most recent command. 00:23:06.460 --> 00:23:09.940 But I'm going to go ahead now and rerun make hello. 00:23:09.940 --> 00:23:13.690 This will ensure that my program is recompiled. 00:23:13.690 --> 00:23:14.950 And this is a manual process. 00:23:14.950 --> 00:23:16.060 I changed my code. 00:23:16.060 --> 00:23:18.670 The zeros and ones on the hard drive have not changed. 00:23:18.670 --> 00:23:21.980 I need to recompile it to output the latest machine code. 00:23:21.980 --> 00:23:22.580 So here we go. 00:23:22.580 --> 00:23:24.830 I'm going to hit Enter, crossing my fingers as before. 00:23:24.830 --> 00:23:29.320 But again, I remove the semicolon by accident. 00:23:29.320 --> 00:23:29.980 Oh, my god. 00:23:29.980 --> 00:23:33.700 There's more lines of errors now than there are of actual code. 00:23:33.700 --> 00:23:35.770 And this, too, takes some getting used to. 00:23:35.770 --> 00:23:38.590 The programs we're using were not necessarily written 00:23:38.590 --> 00:23:40.480 with the least comfortable audience in mind 00:23:40.480 --> 00:23:42.760 but, really, professional programmers back in the day. 00:23:42.760 --> 00:23:46.000 But through practice, and through experience, and through mistakes, 00:23:46.000 --> 00:23:47.750 you'll start to notice patterns here too. 00:23:47.750 --> 00:23:49.090 So here's what I typed. 00:23:49.090 --> 00:23:51.220 Make hello after the sign prompt. 00:23:51.220 --> 00:23:57.010 Now I get yelled at as follows, hello.c, colon, 5, colon, 29. 00:23:57.010 --> 00:23:58.420 Well, what's that referring to? 00:23:58.420 --> 00:24:03.460 I've screwed up somewhere-- on line 5, on the 29th character on that line. 00:24:03.460 --> 00:24:05.740 Generally, the specific character is not that useful 00:24:05.740 --> 00:24:07.448 unless you actually want to count it out. 00:24:07.448 --> 00:24:08.630 But line 5 is a good clue. 00:24:08.630 --> 00:24:09.130 Why? 00:24:09.130 --> 00:24:11.660 It means I screwed up somewhere on line 5 here. 00:24:11.660 --> 00:24:12.160 All right. 00:24:12.160 --> 00:24:13.360 Well, what is the error? 00:24:13.360 --> 00:24:16.242 Expected a semicolon after expression. 00:24:16.242 --> 00:24:17.950 And this error is actually pretty obvious 00:24:17.950 --> 00:24:20.103 now that I see it and I realize, oh, wait a minute. 00:24:20.103 --> 00:24:21.520 All right, here's my line of code. 00:24:21.520 --> 00:24:26.890 Here in sort of ASCII art, so to speak-- textual text representing graphics-- 00:24:26.890 --> 00:24:30.550 it wants me to put in green here the semicolon at the end of that line. 00:24:30.550 --> 00:24:32.470 1 error generated, builtin-- 00:24:32.470 --> 00:24:33.850 so some esoteric stuff there. 00:24:33.850 --> 00:24:36.340 But my program did not compile. 00:24:36.340 --> 00:24:39.470 When you see an error like this, it means it did not work. 00:24:39.470 --> 00:24:40.360 So what's the fix? 00:24:40.360 --> 00:24:45.470 Well, obviously, the fix is to go back up here, put the semicolon there. 00:24:45.470 --> 00:24:48.760 And now if I recompile my code with make hello-- 00:24:48.760 --> 00:24:52.060 I won't clear my screen just yet just to show you the difference-- now 00:24:52.060 --> 00:24:52.990 it just worked. 00:24:52.990 --> 00:24:55.550 So we're back in business as before. 00:24:55.550 --> 00:24:57.910 All right, let me pause here, though, and ask if there's 00:24:57.910 --> 00:25:02.240 any questions about what I just did. 00:25:02.240 --> 00:25:04.460 These error messages will become frequent initially. 00:25:04.460 --> 00:25:04.960 Yeah? 00:25:04.960 --> 00:25:08.848 AUDIENCE: So do you need a semicolon after line or just some of them? 00:25:08.848 --> 00:25:10.390 DAVID J. MALAN: Really good question. 00:25:10.390 --> 00:25:12.960 Do you need a semicolon after every line or just some? 00:25:12.960 --> 00:25:14.022 It turns out, just some. 00:25:14.022 --> 00:25:16.980 This is something you'll learn through practice, through demonstrations 00:25:16.980 --> 00:25:18.240 and examples today. 00:25:18.240 --> 00:25:22.810 Generally, you put a semicolon after a statement, so to speak. 00:25:22.810 --> 00:25:25.230 And this is the technical term for this line of code. 00:25:25.230 --> 00:25:25.950 It's a statement. 00:25:25.950 --> 00:25:29.230 And think of it as it's the code equivalent of an English sentence. 00:25:29.230 --> 00:25:32.820 So the semicolon in code is like a period in English 00:25:32.820 --> 00:25:34.830 when you're done with that particular thought. 00:25:34.830 --> 00:25:37.650 You don't need semicolons for now anywhere else. 00:25:37.650 --> 00:25:39.750 And we'll see examples of where else you put them. 00:25:39.750 --> 00:25:42.780 But it usually is at the end of a line of code 00:25:42.780 --> 00:25:46.980 that isn't purely syntactic like curly braces instead. 00:25:46.980 --> 00:25:51.600 Other questions on the mistake I just fixed and created for myself? 00:25:51.600 --> 00:25:52.230 Yeah? 00:25:52.230 --> 00:25:55.170 AUDIENCE: [INAUDIBLE] 00:25:55.170 --> 00:25:56.170 DAVID J. MALAN: Correct. 00:25:56.170 --> 00:25:58.950 So line 5 is where the error is most likely. 00:25:58.950 --> 00:26:02.250 Character 29 means it's 29 characters that way. 00:26:02.250 --> 00:26:04.800 And then it's actually, in this case, giving me a suggestion. 00:26:04.800 --> 00:26:07.420 The compiler won't always know how to advise me, 00:26:07.420 --> 00:26:09.750 especially if I've made a real mess of my code. 00:26:09.750 --> 00:26:13.260 But often, it will do its best to give you the answer like this. 00:26:13.260 --> 00:26:14.170 Yeah? 00:26:14.170 --> 00:26:16.930 AUDIENCE: How come you first put code hello.c? 00:26:16.930 --> 00:26:21.140 DAVID J. MALAN: Ah, so how come I first typed code, space, hello.c, 00:26:21.140 --> 00:26:22.940 and now I'm typing make hello? 00:26:22.940 --> 00:26:24.180 Two different processes. 00:26:24.180 --> 00:26:27.350 So when I typed code, space, hello.c, that 00:26:27.350 --> 00:26:31.280 was because I wanted to open VS Code and create a new file called hello.c. 00:26:31.280 --> 00:26:34.910 It's like going to File, New in a Mac or PC. 00:26:34.910 --> 00:26:38.690 Thereafter, though, once the file exists and is actually open here-- 00:26:38.690 --> 00:26:41.900 and it does autosave, you don't need to hit Command-S or Control-S all 00:26:41.900 --> 00:26:42.560 the time-- 00:26:42.560 --> 00:26:46.110 I can now compile it with make hello again and again. 00:26:46.110 --> 00:26:50.570 So theoretically, I should never need to type code, space, hello.c 00:26:50.570 --> 00:26:54.020 again unless I want to create a brand-new file called the same thing. 00:26:54.020 --> 00:26:57.200 All right, so what about this other piece of syntax here? 00:26:57.200 --> 00:26:58.790 Let me clear my terminal window here. 00:26:58.790 --> 00:27:01.280 You can also hit Control-L just to throw everything 00:27:01.280 --> 00:27:03.380 away just to clean it up aesthetically. 00:27:03.380 --> 00:27:06.470 Suppose that I omit whatever this sequence of symbols 00:27:06.470 --> 00:27:09.680 is, backslash n, since I'm not really sure at first glance 00:27:09.680 --> 00:27:11.460 why that's even there. 00:27:11.460 --> 00:27:13.310 Does anyone want to conjecture, especially 00:27:13.310 --> 00:27:18.110 if you've never programmed before, what might happen now if I recompile 00:27:18.110 --> 00:27:20.450 and rerun this version of the program? 00:27:20.450 --> 00:27:25.130 I left the semicolon, but I took away the backslash n. 00:27:25.130 --> 00:27:28.390 Any instincts? 00:27:28.390 --> 00:27:29.920 All right, well-- yeah? 00:27:29.920 --> 00:27:32.470 AUDIENCE: Will the next dollar sign appear 00:27:32.470 --> 00:27:34.190 straight after your hello, world? 00:27:34.190 --> 00:27:35.190 DAVID J. MALAN: It will. 00:27:35.190 --> 00:27:38.740 The next dollar sign will appear right after my hello, world. 00:27:38.740 --> 00:27:40.564 But what makes you think that? 00:27:40.564 --> 00:27:43.010 AUDIENCE: Because the backslash n creates a new line? 00:27:43.010 --> 00:27:44.010 DAVID J. MALAN: Exactly. 00:27:44.010 --> 00:27:46.050 Backslash n is actually a special sequence 00:27:46.050 --> 00:27:48.060 of symbols that creates a new line. 00:27:48.060 --> 00:27:52.710 And so, to your point, if I recompile this program, make hello, Enter-- 00:27:52.710 --> 00:27:55.420 no syntax error, so it did compile this time. 00:27:55.420 --> 00:27:57.180 So you don't need the backslash n. 00:27:57.180 --> 00:27:58.800 You do need the semicolon. 00:27:58.800 --> 00:28:02.730 But if you don't have the backslash n, watch what happens when I do ./hello 00:28:02.730 --> 00:28:03.510 this time. 00:28:03.510 --> 00:28:07.230 Now, indeed, I see hello, comma, world and then a weird dollar sign. 00:28:07.230 --> 00:28:08.460 And this is still a prompt. 00:28:08.460 --> 00:28:12.270 I can still type commands at it, like clear, and everything gets cleaned up. 00:28:12.270 --> 00:28:13.710 But it just looks kind of stupid. 00:28:13.710 --> 00:28:18.240 If I run it again here with ./hello, it's just not very user friendly. 00:28:18.240 --> 00:28:20.740 It is convention that when you're done running your program, 00:28:20.740 --> 00:28:22.950 you should ideally clean things up, move the cursor 00:28:22.950 --> 00:28:24.460 to the next line for the user. 00:28:24.460 --> 00:28:27.540 And so the backslash n is simply the special symbol, 00:28:27.540 --> 00:28:32.640 otherwise known as an escape sequence that C knows 00:28:32.640 --> 00:28:34.980 means move the cursor to the next line. 00:28:34.980 --> 00:28:39.640 In other languages, Python among them, uses this same symbology as well. 00:28:39.640 --> 00:28:44.850 Now, if I go back to the code here and, for instance, 00:28:44.850 --> 00:28:47.220 I try to do this differently. 00:28:47.220 --> 00:28:49.020 Suppose I don't put the backslash n. 00:28:49.020 --> 00:28:52.860 I just hit Enter like a normal person would in Google Docs or Microsoft Word. 00:28:52.860 --> 00:28:55.107 Let me go ahead and try compiling this program. 00:28:55.107 --> 00:28:56.940 And this, you would hope, would work, right? 00:28:56.940 --> 00:29:00.210 You would hope this would print out hello, world and then a blank line 00:29:00.210 --> 00:29:02.220 because I move the cursor to the next line. 00:29:02.220 --> 00:29:02.790 But no. 00:29:02.790 --> 00:29:07.290 If I run make hello now and try to compile that, C does not like this. 00:29:07.290 --> 00:29:09.690 Now I get a different error, still on line 5, 00:29:09.690 --> 00:29:12.240 this time starting at character 12-- 00:29:12.240 --> 00:29:15.810 error, missing terminating double quote character and then 00:29:15.810 --> 00:29:17.070 some other esoteric stuff. 00:29:17.070 --> 00:29:19.530 And then this does not sound good-- fatal error this time, 00:29:19.530 --> 00:29:21.900 too many errors emitted, stopping now. 00:29:21.900 --> 00:29:23.470 So I really screwed up here. 00:29:23.470 --> 00:29:25.320 So why can't I do this? 00:29:25.320 --> 00:29:26.190 Just because. 00:29:26.190 --> 00:29:29.730 The humans who designed C decided that if you have a string of text, 00:29:29.730 --> 00:29:31.380 it must stay on the same line. 00:29:31.380 --> 00:29:32.760 It can get really long. 00:29:32.760 --> 00:29:36.150 It can soft wrap-- that is, without you hitting Enter. 00:29:36.150 --> 00:29:38.220 But you can't hit Enter to create a new line. 00:29:38.220 --> 00:29:42.870 If you deliberately want a new line, you have to indeed use this backslash n 00:29:42.870 --> 00:29:43.958 escape character. 00:29:43.958 --> 00:29:45.250 So let me go ahead and do this. 00:29:45.250 --> 00:29:46.710 Let me put it back. 00:29:46.710 --> 00:29:48.720 Let me go back to my terminal window. 00:29:48.720 --> 00:29:50.080 I'll clear the screen again. 00:29:50.080 --> 00:29:54.090 Let me go ahead now and do make hello to recompile to that version-- ./hello. 00:29:54.090 --> 00:29:54.900 And voila. 00:29:54.900 --> 00:29:57.780 We're back in business with hello. 00:29:57.780 --> 00:30:00.300 All right, so now let's tease apart some other aspects 00:30:00.300 --> 00:30:03.870 of this code because there's a lot going on just to get us to say hello, 00:30:03.870 --> 00:30:04.920 world on the screen. 00:30:04.920 --> 00:30:07.740 For today, we're largely going to ignore this-- int 00:30:07.740 --> 00:30:10.145 main(void) and these curly braces here. 00:30:10.145 --> 00:30:12.520 We'll come back to that before long as to why it's there. 00:30:12.520 --> 00:30:15.870 But for now just think of int main(void) and these curly braces 00:30:15.870 --> 00:30:19.180 here as really being the C equivalent of when green flag clicked. 00:30:19.180 --> 00:30:19.680 Why? 00:30:19.680 --> 00:30:20.638 You just need it there. 00:30:20.638 --> 00:30:22.320 That's how you get your program going. 00:30:22.320 --> 00:30:25.500 And main is indeed going to be some special function, but more on that 00:30:25.500 --> 00:30:26.340 another time. 00:30:26.340 --> 00:30:28.950 But why do I have this line of code here? 00:30:28.950 --> 00:30:33.990 The correct spelling is indeed stdio.h, S-T-D-I-O dot H. 00:30:33.990 --> 00:30:37.500 And they're angled brackets this time, so that's a little new. 00:30:37.500 --> 00:30:40.290 There's a hash and then an include keyword. 00:30:40.290 --> 00:30:42.123 If you don't know what something is, there's 00:30:42.123 --> 00:30:45.165 not really that much harm in just getting rid of it and see what happens. 00:30:45.165 --> 00:30:46.360 So let me delete that line. 00:30:46.360 --> 00:30:48.910 Let me go back to my terminal window, clear the screen, 00:30:48.910 --> 00:30:50.160 and then run make hello again. 00:30:50.160 --> 00:30:53.290 And let's try compiling this program now without that first line. 00:30:53.290 --> 00:30:53.790 Why? 00:30:53.790 --> 00:30:56.340 I don't understand it, so let's see what happens. 00:30:56.340 --> 00:30:58.920 All right, here's yet another error, but let's see-- 00:30:58.920 --> 00:31:03.480 hello.c, line 5, character 5-- so it's pretty early on-- 00:31:03.480 --> 00:31:07.920 error, implicitly declaring library function printf with type int 00:31:07.920 --> 00:31:09.150 and then dot, dot, dot. 00:31:09.150 --> 00:31:12.630 So implicitly declaring library function printf-- 00:31:12.630 --> 00:31:14.490 so this is very cryptic sounding. 00:31:14.490 --> 00:31:16.920 You'll get better at understanding phrases like these. 00:31:16.920 --> 00:31:22.620 But apparently, I do need the include line for stdio.h. 00:31:22.620 --> 00:31:23.820 But why? 00:31:23.820 --> 00:31:27.810 Based on this symptom, what might your instinct 00:31:27.810 --> 00:31:33.330 be for what that first line of code is doing for us in the first place? 00:31:33.330 --> 00:31:35.370 Why intuitively must it be there? 00:31:35.370 --> 00:31:37.290 AUDIENCE: It's how the [INAUDIBLE] functions. 00:31:37.290 --> 00:31:38.290 DAVID J. MALAN: Exactly. 00:31:38.290 --> 00:31:41.350 It's like importing a library so that you can do things like print things 00:31:41.350 --> 00:31:42.137 out on the screen. 00:31:42.137 --> 00:31:45.220 Now, in Scratch, you didn't have to do this for most of the puzzle pieces. 00:31:45.220 --> 00:31:47.950 But you might recall that partway through week 0, 00:31:47.950 --> 00:31:51.640 I went to the Extensions button at the bottom left of the Scratch screen, 00:31:51.640 --> 00:31:54.340 and I imported some extra puzzle pieces for text 00:31:54.340 --> 00:31:59.170 to speech that gave us the creepy humanized voice that actually came out 00:31:59.170 --> 00:32:00.100 of the cat's mouth. 00:32:00.100 --> 00:32:02.500 Well, that was like adding a library-- 00:32:02.500 --> 00:32:04.390 code that someone else wrote. 00:32:04.390 --> 00:32:06.550 In that case, it was a third party. 00:32:06.550 --> 00:32:08.380 But I gave myself access to it. 00:32:08.380 --> 00:32:09.250 Same here. 00:32:09.250 --> 00:32:13.900 Turns out that you don't really get printf automatically in C. 00:32:13.900 --> 00:32:17.560 You have to include a so-called header file that 00:32:17.560 --> 00:32:20.020 declares that function to exist. 00:32:20.020 --> 00:32:22.570 Now, the reason for this historically is just efficiency. 00:32:22.570 --> 00:32:26.882 Back in the day when computers were really slower and resource constrained, 00:32:26.882 --> 00:32:29.590 you don't want to just give yourself access to the entire kitchen 00:32:29.590 --> 00:32:30.610 sink of functionality. 00:32:30.610 --> 00:32:34.690 You only want to include only the functions you actually care about. 00:32:34.690 --> 00:32:39.180 Nowadays, it's a copy/paste step because you almost always 00:32:39.180 --> 00:32:40.930 want to print something out on the screen, 00:32:40.930 --> 00:32:42.680 at least when writing programs like these. 00:32:42.680 --> 00:32:45.760 But these so-called header files contain enough information 00:32:45.760 --> 00:32:50.350 about all of the functions in what's called the Standard I/O Library. 00:32:50.350 --> 00:32:53.450 And standard I/O just means standard Input and Output. 00:32:53.450 --> 00:32:54.700 And that's appropriate, right? 00:32:54.700 --> 00:32:57.010 Because printing is pretty basic output. 00:32:57.010 --> 00:32:59.920 Turns out, there's other functions for getting input from the human's 00:32:59.920 --> 00:33:01.310 keyboard-- more on that in a bit. 00:33:01.310 --> 00:33:03.970 But any time you want to print something on the screen in C, 00:33:03.970 --> 00:33:07.630 you indeed need to include this header file at the top of your code. 00:33:07.630 --> 00:33:11.350 And that's going to essentially inform the compiler, hey, compiler, 00:33:11.350 --> 00:33:15.980 I want to use functionality from the Standard I/O Library, 00:33:15.980 --> 00:33:18.320 including printf in this case. 00:33:18.320 --> 00:33:20.770 And if you omit the header file by accident, 00:33:20.770 --> 00:33:24.040 it's just not going to work because it doesn't know what printf is. 00:33:24.040 --> 00:33:27.970 It's some unrecognized symbol in that case. 00:33:27.970 --> 00:33:34.320 All right, questions, then, about this line of code, this line of code here, 00:33:34.320 --> 00:33:37.590 or what these header files are? 00:33:37.590 --> 00:33:40.890 All right, you might wonder, well, how do you know what functions exist? 00:33:40.890 --> 00:33:43.990 How do you know what files you might indeed want to include? 00:33:43.990 --> 00:33:46.620 Well, it turns out that C is a many-year-old language, 00:33:46.620 --> 00:33:48.720 and it has ample documentation. 00:33:48.720 --> 00:33:52.770 A caveat is that its documentation isn't necessarily all that user friendly. 00:33:52.770 --> 00:33:56.370 But what we have for the course is a simplified version 00:33:56.370 --> 00:34:01.680 of the official documentation for C at this URL here, manual.cs50.io. 00:34:01.680 --> 00:34:04.380 So in the world of C, and other languages too, 00:34:04.380 --> 00:34:06.150 there are what are called manual pages. 00:34:06.150 --> 00:34:08.820 And these are just text-based documentation 00:34:08.820 --> 00:34:11.010 that, honestly, is typically written in a voice 00:34:11.010 --> 00:34:14.560 that you have to be an experienced programmer to understand some of it. 00:34:14.560 --> 00:34:17.699 So what we've done in this version of the same documentation 00:34:17.699 --> 00:34:20.699 is we've imported all of the original official documentation, 00:34:20.699 --> 00:34:24.074 but we've added less comfortable translations in English 00:34:24.074 --> 00:34:26.699 for a lot of the functionality that you might use in class just 00:34:26.699 --> 00:34:27.713 to help onboard you. 00:34:27.713 --> 00:34:30.630 So at the end of the day, you don't need this documentation long term. 00:34:30.630 --> 00:34:34.320 But just to get started, we'll translate it into terminology 00:34:34.320 --> 00:34:36.630 that you might appreciate from a teaching assistant, 00:34:36.630 --> 00:34:39.969 for instance, as opposed to the original author of these documents. 00:34:39.969 --> 00:34:42.420 And so, for instance, if you were interested in reading up 00:34:42.420 --> 00:34:48.330 on what functions exist in the stdio.h file, well, 00:34:48.330 --> 00:34:52.830 you could go to a URL like this, or you could search for it at manual.cs50.io. 00:34:52.830 --> 00:34:56.350 That would show you a list of all of the available functions in that library, 00:34:56.350 --> 00:34:58.350 and print if indeed would be one of them. 00:34:58.350 --> 00:35:00.683 And then you could click further on that, reaching a URL 00:35:00.683 --> 00:35:03.475 like this that's going to give you all of the documentation for how 00:35:03.475 --> 00:35:04.110 to use printf. 00:35:04.110 --> 00:35:07.560 It turns out, you can do even more than just printing out hello, world. 00:35:07.560 --> 00:35:09.450 And we'll scratch the surface of that today. 00:35:09.450 --> 00:35:12.900 But it turns out that the documentation will always 00:35:12.900 --> 00:35:16.680 be your authoritative source ultimately for questions like, what can I do, 00:35:16.680 --> 00:35:18.160 and how can I do it? 00:35:18.160 --> 00:35:23.010 Meanwhile, it turns out that CS50 has its own library 00:35:23.010 --> 00:35:25.980 and accessible via header file called cs50.h. 00:35:25.980 --> 00:35:28.530 It turns out in C that output is actually 00:35:28.530 --> 00:35:30.750 pretty easy, relatively speaking, once you 00:35:30.750 --> 00:35:34.110 get used to all the curly braces, parentheses, quote marks, and the like. 00:35:34.110 --> 00:35:36.670 But input is a little more difficult. 00:35:36.670 --> 00:35:41.100 And if you have programmed before, input's not that hard to do in Python. 00:35:41.100 --> 00:35:42.540 It's not that hard to do in Java. 00:35:42.540 --> 00:35:46.312 It's more difficult to do in C. And we'll see why in a couple of weeks. 00:35:46.312 --> 00:35:48.270 But for the first couple of weeks of the class, 00:35:48.270 --> 00:35:50.880 we actually provide you with some training wheels, 00:35:50.880 --> 00:35:53.700 of sorts, whereby we have a number of functions 00:35:53.700 --> 00:35:56.430 that are declared in this file, cs50.h. 00:35:56.430 --> 00:35:59.220 It lives its documentation at a URL like this. 00:35:59.220 --> 00:36:01.230 And in a moment, we'll use a few of these. 00:36:01.230 --> 00:36:05.040 You'll see that CS50 provides you with some functions like get_char 00:36:05.040 --> 00:36:08.580 for get a single character from the user's keyboard, 00:36:08.580 --> 00:36:11.790 get_int to get an integer from the user's keyboard, 00:36:11.790 --> 00:36:15.450 get_string to get a sequence of text from the user's keyboard, and a bunch 00:36:15.450 --> 00:36:16.930 of others as well. 00:36:16.930 --> 00:36:19.920 So let's actually use some of these functions, how about, 00:36:19.920 --> 00:36:22.410 by revisiting, really, the second program we 00:36:22.410 --> 00:36:26.710 wrote in Scratch last time, which adds some input to the output. 00:36:26.710 --> 00:36:28.830 So first version of Scratch was just hello, world. 00:36:28.830 --> 00:36:31.200 Said the same thing every time you click the green flag. 00:36:31.200 --> 00:36:33.180 Version 2, recall, though, did this. 00:36:33.180 --> 00:36:35.190 It asked the user, what's your name? 00:36:35.190 --> 00:36:40.870 And then that somehow gave it back a return value, we called it. 00:36:40.870 --> 00:36:44.100 And we then joined hello and that name to say something a little more 00:36:44.100 --> 00:36:46.420 interesting on the screen. 00:36:46.420 --> 00:36:48.420 So what did that model look like? 00:36:48.420 --> 00:36:49.560 Same thing as before. 00:36:49.560 --> 00:36:52.680 We've got a function in the middle where function is like the code 00:36:52.680 --> 00:36:54.480 implementation of our algorithm. 00:36:54.480 --> 00:36:56.910 That takes in one or more arguments, like what is it you 00:36:56.910 --> 00:37:00.000 want to say on the screen ultimately? 00:37:00.000 --> 00:37:03.580 And return value, in this case, is going to be actually a value that comes back. 00:37:03.580 --> 00:37:07.660 So in the case of getting input, we can consider this ask block again, 00:37:07.660 --> 00:37:08.490 like last week. 00:37:08.490 --> 00:37:12.420 The input to it is whatever words of English you want to ask the user. 00:37:12.420 --> 00:37:14.670 And then it returns a value. 00:37:14.670 --> 00:37:17.550 And this was called by default in MIT'S world answer. 00:37:17.550 --> 00:37:20.460 But we'll see in C, you can call these return values anything 00:37:20.460 --> 00:37:22.300 you want ultimately in variables. 00:37:22.300 --> 00:37:24.100 But this is different from a side effect. 00:37:24.100 --> 00:37:27.100 A side effect is just something visual often that happens on the screen, 00:37:27.100 --> 00:37:28.980 like the speech bubble or hello, world. 00:37:28.980 --> 00:37:32.220 A return value is actually a value you get back from a function 00:37:32.220 --> 00:37:34.020 that you can use or reuse. 00:37:34.020 --> 00:37:38.400 So how do we convert this Scratch block from last week to C code this week? 00:37:38.400 --> 00:37:41.340 Well, if you want to ask the user for something like their name, 00:37:41.340 --> 00:37:42.580 you can do this. 00:37:42.580 --> 00:37:45.600 You use a CS50 function called get_string. 00:37:45.600 --> 00:37:49.950 And you use the parentheses to represent here comes the inputs there too. 00:37:49.950 --> 00:37:52.967 You can then put the sentence you want to ask the user-- 00:37:52.967 --> 00:37:54.300 quote/unquote, what's your name? 00:37:54.300 --> 00:37:57.150 But you do indeed need the quotes literally in C. 00:37:57.150 --> 00:37:59.220 So I'll go ahead and add those as well. 00:37:59.220 --> 00:38:03.720 Subtle, but I've deliberately included a space after the question mark, 00:38:03.720 --> 00:38:06.840 but before the double quote, just so that the cursor 00:38:06.840 --> 00:38:08.998 moves one step over because, in this case, 00:38:08.998 --> 00:38:11.790 we're not going to get a special speech box like we did in Scratch. 00:38:11.790 --> 00:38:14.582 It's just going to leave the cursor where it is, so we'll see that, 00:38:14.582 --> 00:38:16.980 aesthetically, that just moves the blinking cursor one 00:38:16.980 --> 00:38:19.800 space after the sentence on the screen. 00:38:19.800 --> 00:38:21.930 All right, but the catch is with Scratch, 00:38:21.930 --> 00:38:25.140 we just automatically got back the answer from the user 00:38:25.140 --> 00:38:27.180 in a special variable called answer. 00:38:27.180 --> 00:38:30.270 In C, you're going to have to be a little more specific. 00:38:30.270 --> 00:38:35.780 In C, If you want to get back a return value from a function like get_string, 00:38:35.780 --> 00:38:40.420 you have to use an equal sign and then the name of a variable on the left. 00:38:40.420 --> 00:38:42.280 The choice of variables is up to you. 00:38:42.280 --> 00:38:44.290 I could have called this anything-- x, y, z. 00:38:44.290 --> 00:38:47.470 I'm going to more descriptively call it answer for parity with what 00:38:47.470 --> 00:38:48.880 MIT did with Scratch. 00:38:48.880 --> 00:38:53.090 But notice that this doesn't represent equality, per se. 00:38:53.090 --> 00:38:55.640 This is assignment in this case. 00:38:55.640 --> 00:38:58.180 So in C, when you use a single equal sign, 00:38:58.180 --> 00:39:01.720 that means copy the value on the right over to the value 00:39:01.720 --> 00:39:03.590 on the left-- from right to left. 00:39:03.590 --> 00:39:05.390 So what does this do for us? 00:39:05.390 --> 00:39:08.170 Well, if get_string is a function that prompts the user with, 00:39:08.170 --> 00:39:12.160 quote/unquote, what's your name, and it has I claim a return value, 00:39:12.160 --> 00:39:14.750 that means it hands me back some value. 00:39:14.750 --> 00:39:17.960 But it's up to me in C to do something with that value. 00:39:17.960 --> 00:39:21.520 So if I want to copy that value into a variable that I can use and reuse, 00:39:21.520 --> 00:39:25.300 I use an equal sign, and I invent on the left-hand side of that equal sign 00:39:25.300 --> 00:39:27.340 any variable name I want. 00:39:27.340 --> 00:39:28.450 There are certain rules. 00:39:28.450 --> 00:39:29.700 There are certain conventions. 00:39:29.700 --> 00:39:32.590 But generally if you use a single word with all lowercase, 00:39:32.590 --> 00:39:34.570 you're in good shape. 00:39:34.570 --> 00:39:37.040 But C's a little more pedantic than that. 00:39:37.040 --> 00:39:38.980 And those of you who have programmed before 00:39:38.980 --> 00:39:41.410 might not be used to this, for instance, in Python, which 00:39:41.410 --> 00:39:43.330 is a world we'll get to in a few weeks. 00:39:43.330 --> 00:39:48.670 You also have to tell C what type of value you're storing. 00:39:48.670 --> 00:39:54.370 So if I do want a string of text from the user-- so not an integer, not 00:39:54.370 --> 00:39:55.270 a single character. 00:39:55.270 --> 00:39:58.430 I want a whole string of text, like a phrase, a sentence, a name, 00:39:58.430 --> 00:39:59.270 in this case-- 00:39:59.270 --> 00:40:04.250 I have to tell C that this variable is of type string. 00:40:04.250 --> 00:40:06.267 So it's a little wordy, but you get used to it. 00:40:06.267 --> 00:40:07.600 And you just have to be precise. 00:40:07.600 --> 00:40:12.760 You're informing the computer what type of value is going in this variable. 00:40:12.760 --> 00:40:15.040 All right, it's so close to being correct, 00:40:15.040 --> 00:40:19.210 but I have omitted something that's annoyingly important still. 00:40:19.210 --> 00:40:20.470 What's missing still? 00:40:20.470 --> 00:40:21.070 Yeah? 00:40:21.070 --> 00:40:21.970 AUDIENCE: Semicolon? 00:40:21.970 --> 00:40:23.178 DAVID J. MALAN: So semicolon. 00:40:23.178 --> 00:40:24.230 This is a statement. 00:40:24.230 --> 00:40:27.040 This is like a full thought, if you will. 00:40:27.040 --> 00:40:31.680 In Code, I do need to end it ultimately with the semicolon at the end there. 00:40:31.680 --> 00:40:33.430 All right, so this was more of a mouthful, 00:40:33.430 --> 00:40:35.720 but let's try using this in now my code. 00:40:35.720 --> 00:40:40.250 Let me go back to VS Code where I have version 0 of my code here. 00:40:40.250 --> 00:40:44.560 Let me go ahead and include one other file at the top of hello.c, 00:40:44.560 --> 00:40:48.790 namely include cs50.h so that I have access now 00:40:48.790 --> 00:40:51.370 to get_string and anything else I might want. 00:40:51.370 --> 00:40:56.710 Now let me go ahead and add a line of code here inside of these curly braces. 00:40:56.710 --> 00:40:58.390 And let me go ahead and do this-- 00:40:58.390 --> 00:41:03.820 string answer equals get_string, quote/unquote, what's your name, 00:41:03.820 --> 00:41:04.847 question mark. 00:41:04.847 --> 00:41:07.180 I'm going to add an extra space before the double quote. 00:41:07.180 --> 00:41:10.430 I'm going to indeed end my thought with a semicolon. 00:41:10.430 --> 00:41:14.260 And now let me deliberately make a mistake, just to make a point here. 00:41:14.260 --> 00:41:19.840 Let me now try changing hello, world to hello, comma, answer. 00:41:19.840 --> 00:41:22.630 Now, perhaps, even though this is some new lines of code, 00:41:22.630 --> 00:41:24.520 you can see where I've errored already. 00:41:24.520 --> 00:41:26.980 But let me try making this program now. 00:41:26.980 --> 00:41:27.970 So far, so good. 00:41:27.970 --> 00:41:29.120 So no error messages. 00:41:29.120 --> 00:41:30.140 So that's a good thing. 00:41:30.140 --> 00:41:34.000 Let me go ahead and run ./hello, and you'll see the prompt. 00:41:34.000 --> 00:41:35.650 What's your name, question mark. 00:41:35.650 --> 00:41:37.942 And notice, the cursor is indeed one space to the right 00:41:37.942 --> 00:41:39.817 just because I thought it would look prettier 00:41:39.817 --> 00:41:42.190 to put a little blank space there as opposed to leaving 00:41:42.190 --> 00:41:43.600 it right after the question mark. 00:41:43.600 --> 00:41:44.530 Let me type my name. 00:41:44.530 --> 00:41:48.340 But even if you've never programmed before, I have screwed up here. 00:41:48.340 --> 00:41:51.240 What are we going to see on the screen when I hit Enter? 00:41:51.240 --> 00:41:52.240 AUDIENCE: Hello, answer. 00:41:52.240 --> 00:41:53.115 DAVID J. MALAN: Yeah. 00:41:53.115 --> 00:41:54.280 Hello, answer, most likely. 00:41:54.280 --> 00:41:54.730 Why? 00:41:54.730 --> 00:41:56.855 Because the computer is going to take me literally. 00:41:56.855 --> 00:41:59.020 And if I say, quote/unquote, hello, answer. 00:41:59.020 --> 00:42:01.750 That is the string of text followed by a new line that's 00:42:01.750 --> 00:42:03.260 going to be outputted to the screen. 00:42:03.260 --> 00:42:08.530 So we need some way of actually plugging answer into this line of code. 00:42:08.530 --> 00:42:10.330 It's not quite as simple as scratch where 00:42:10.330 --> 00:42:14.140 you could just grab a second say block and drag and drop the variable there. 00:42:14.140 --> 00:42:15.670 We actually need a new syntax. 00:42:15.670 --> 00:42:18.250 And it's going to look weird at first, but it is everywhere 00:42:18.250 --> 00:42:22.900 in software nowadays, especially in the world of C and certain other languages. 00:42:22.900 --> 00:42:27.610 So let me go ahead and propose that I solve it as follows. 00:42:27.610 --> 00:42:31.450 Well, back when we did this in Scratch, remember that the most elegant solution 00:42:31.450 --> 00:42:32.350 was this here. 00:42:32.350 --> 00:42:36.550 We used the say block still, which is going to be analogous to printf today. 00:42:36.550 --> 00:42:41.630 But I use the join puzzle piece and Scratch to combine hello, comma, space, 00:42:41.630 --> 00:42:43.340 and then the name of the human. 00:42:43.340 --> 00:42:45.790 So how do we translate this code to C? 00:42:45.790 --> 00:42:47.830 Well, it's going to look a little different now. 00:42:47.830 --> 00:42:51.700 I'm going to start with printf with some parentheses and a semicolon 00:42:51.700 --> 00:42:53.530 representing the say block. 00:42:53.530 --> 00:42:55.240 But how do I now do this joining? 00:42:55.240 --> 00:42:58.330 This is where the puzzle pieces don't quite translate perfectly. 00:42:58.330 --> 00:43:00.290 This would be the way to do this. 00:43:00.290 --> 00:43:03.430 You put hello, comma, and then a placeholder. 00:43:03.430 --> 00:43:07.810 So this is what's known as a format code in C, specifically for printf. 00:43:07.810 --> 00:43:11.350 And it just means this is a placeholder for a string. 00:43:11.350 --> 00:43:12.740 Again, a string is just text. 00:43:12.740 --> 00:43:17.120 So this means, hey, computer, print out literally, hello, comma, space, 00:43:17.120 --> 00:43:23.200 and then not literally %s. %s is treated specially to mean plug in some value 00:43:23.200 --> 00:43:23.903 here. 00:43:23.903 --> 00:43:25.570 All right, so what else do I still need? 00:43:25.570 --> 00:43:28.030 Well, this is still some text, so I'm still 00:43:28.030 --> 00:43:32.460 going to surround the whole thing with double quotes. 00:43:32.460 --> 00:43:35.220 I'm still going to include my backslash n just 00:43:35.220 --> 00:43:37.870 to keep things tidy and move the cursor to the next line. 00:43:37.870 --> 00:43:45.120 So the last step here in C is to somehow join the answer with that word hello. 00:43:45.120 --> 00:43:49.980 And the way you do this is with printf, passing it not one argument, which 00:43:49.980 --> 00:43:51.000 is what I keep doing. 00:43:51.000 --> 00:43:53.820 I keep passing it one string of text, quote/unquote. 00:43:53.820 --> 00:43:58.320 I'm going to now add a comma and then the name of the value that I want 00:43:58.320 --> 00:44:02.760 printf to go back and plug into that %s. 00:44:02.760 --> 00:44:04.410 And printf is just smart about this. 00:44:04.410 --> 00:44:09.390 If you have one %s and one additional argument after a comma, it just does-- 00:44:09.390 --> 00:44:10.980 from right to left, it plugs it in. 00:44:10.980 --> 00:44:16.470 If you have two %s's and two variables after the comma, that's OK too. 00:44:16.470 --> 00:44:19.860 If you separate them with commas, it'll plug the first into the first %s 00:44:19.860 --> 00:44:22.380 and the second variable into the second %s. 00:44:22.380 --> 00:44:24.750 So it's just left to right, order of operations. 00:44:24.750 --> 00:44:30.302 It's not as pretty or as simple as this, but this is how it's done in C. 00:44:30.302 --> 00:44:32.760 All right, let me pause because this is a lot of symbology. 00:44:32.760 --> 00:44:35.080 Any questions on this technique here? 00:44:35.080 --> 00:44:35.580 Yeah? 00:44:35.580 --> 00:44:39.725 AUDIENCE: Why did you exclude the backslash n in the previous section? 00:44:39.725 --> 00:44:41.600 DAVID J. MALAN: Yeah, a really good question. 00:44:41.600 --> 00:44:45.550 Why did I exclude the backslash n a moment ago? 00:44:45.550 --> 00:44:48.280 Really, just my sense of aesthetics, if you will. 00:44:48.280 --> 00:44:49.760 No good reason beyond that. 00:44:49.760 --> 00:44:52.210 So if I look back at my code, you quite rightly 00:44:52.210 --> 00:44:54.460 notice that I didn't have a backslash n there. 00:44:54.460 --> 00:44:57.400 That's just because, for whatever sense of style that I have, 00:44:57.400 --> 00:45:00.460 I wanted the name to be typed right after the question. 00:45:00.460 --> 00:45:04.030 I totally could have added a backslash n there instead of a space. 00:45:04.030 --> 00:45:06.490 That would have just allowed me to type down here. 00:45:06.490 --> 00:45:07.490 Totally fine. 00:45:07.490 --> 00:45:09.670 Just wanted to show you something different. 00:45:09.670 --> 00:45:10.210 Good catch. 00:45:10.210 --> 00:45:10.660 Yeah? 00:45:10.660 --> 00:45:12.070 AUDIENCE: Can you show an example with two %s's? 00:45:12.070 --> 00:45:14.470 DAVID J. MALAN: Can I show an example with two %s's? 00:45:14.470 --> 00:45:15.250 Surely. 00:45:15.250 --> 00:45:17.570 So let me in VS Code do this. 00:45:17.570 --> 00:45:20.050 Let me clear my terminal window to clean things up. 00:45:20.050 --> 00:45:21.170 And let me do this. 00:45:21.170 --> 00:45:23.620 Instead of calling the variable answer all over the place, 00:45:23.620 --> 00:45:26.080 let me call it first. 00:45:26.080 --> 00:45:27.490 And I'll ask two questions. 00:45:27.490 --> 00:45:28.880 What's your first name? 00:45:28.880 --> 00:45:32.620 And now let me do string last equals get_string-- 00:45:32.620 --> 00:45:35.560 whoops, capitalization matters, so let me fix my capital S 00:45:35.560 --> 00:45:41.720 there-- quote/unquote, What's your last name, question mark, semicolon. 00:45:41.720 --> 00:45:47.320 And now we'll plug in one %s and a second %s. 00:45:47.320 --> 00:45:52.720 And now I'm going to plug in first first and last last, coincidentally. 00:45:52.720 --> 00:45:55.240 And now I'm going to go back to the terminal window. 00:45:55.240 --> 00:46:00.280 Make hello-- crossing my fingers, all good-- ./hello. 00:46:00.280 --> 00:46:02.620 Here's my first question, David. 00:46:02.620 --> 00:46:04.240 Here's my second question, Malan. 00:46:04.240 --> 00:46:05.650 And again? 00:46:05.650 --> 00:46:06.670 Hello, David Malan. 00:46:06.670 --> 00:46:08.440 So it just inserts them left to right. 00:46:08.440 --> 00:46:10.510 All I was doing for parity with Scratch though-- 00:46:10.510 --> 00:46:12.670 and let me go ahead and undo this again. 00:46:12.670 --> 00:46:15.130 I'll go back to answer, like this. 00:46:15.130 --> 00:46:17.800 I'll go back to just asking for the person's name. 00:46:17.800 --> 00:46:19.300 I'm going to delete mention of last. 00:46:19.300 --> 00:46:21.520 I'm going to delete mention of the second %s. 00:46:21.520 --> 00:46:24.400 And now if I recompile this simpler version, 00:46:24.400 --> 00:46:27.720 oh, I did screw up-- didn't intend it. 00:46:27.720 --> 00:46:29.220 What did I do wrong? 00:46:29.220 --> 00:46:31.353 AUDIENCE: You forgot to change first in line 7. 00:46:31.353 --> 00:46:33.270 DAVID J. MALAN: Yeah, so just newbie mistakes. 00:46:33.270 --> 00:46:37.800 So I changed my variable back to answer just to be consistent with week 0, 00:46:37.800 --> 00:46:39.610 but I didn't change it here. 00:46:39.610 --> 00:46:42.750 So I have an use of undeclared identifier first. 00:46:42.750 --> 00:46:46.470 It's undeclared in the sense that I declared answer a line prior. 00:46:46.470 --> 00:46:47.950 I didn't declare first. 00:46:47.950 --> 00:46:51.060 So indeed, intuitively, I want to just change that to that. 00:46:51.060 --> 00:46:56.740 Let me now do make hello again, ./hello, type in just my first name this time. 00:46:56.740 --> 00:46:59.400 And there it is-- hello, David. 00:46:59.400 --> 00:47:02.220 Questions on this then syntax with printf? 00:47:02.220 --> 00:47:03.390 Yeah? 00:47:03.390 --> 00:47:04.608 AUDIENCE: [INAUDIBLE] 00:47:04.608 --> 00:47:06.150 DAVID J. MALAN: Ah, the placeholder-- 00:47:06.150 --> 00:47:09.240 I'll zoom in-- is just a single percent then an s. 00:47:09.240 --> 00:47:17.370 So inside of my string here is %s, and then I have a comma outside the quotes, 00:47:17.370 --> 00:47:23.400 and then the name of the variable whose value I want to plug in for that %s. 00:47:23.400 --> 00:47:28.080 And now notice there's technically two commas inside 00:47:28.080 --> 00:47:30.300 of these parentheses on line 7. 00:47:30.300 --> 00:47:33.690 And yet, I claim that printf, at the moment, 00:47:33.690 --> 00:47:37.290 is only taking in two arguments. 00:47:37.290 --> 00:47:41.582 Why is there then two commas but only two arguments? 00:47:41.582 --> 00:47:43.290 If there were two commas, you would think 00:47:43.290 --> 00:47:45.700 there would be three arguments, right? 00:47:45.700 --> 00:47:47.904 AUDIENCE: The comma is between the quotes, 00:47:47.904 --> 00:47:49.700 so it counts as a comma [INAUDIBLE] 00:47:49.700 --> 00:47:50.700 DAVID J. MALAN: Exactly. 00:47:50.700 --> 00:47:53.160 The comma in between the quotes is just an English thing. 00:47:53.160 --> 00:47:55.240 It's separating the hello from the name. 00:47:55.240 --> 00:47:57.690 So that's why indeed it's not only in quotes, 00:47:57.690 --> 00:48:01.710 that's also why programs like VS Code tend to syntax highlight it 00:48:01.710 --> 00:48:05.580 a little differently just so that it jumps out as different to you, 00:48:05.580 --> 00:48:08.790 even though, in this case, it's a little subtle-- a light blue versus white-- 00:48:08.790 --> 00:48:10.830 but indeed, it's trying its best. 00:48:10.830 --> 00:48:13.150 Other questions now on this placeholder? 00:48:13.150 --> 00:48:13.650 Yeah? 00:48:13.650 --> 00:48:16.390 AUDIENCE: If you wanted to put an exclamation point at the end, 00:48:16.390 --> 00:48:18.460 would you put a comma after your answer variable, 00:48:18.460 --> 00:48:21.943 and would that put it [INAUDIBLE],, or would you have to add a new line? 00:48:21.943 --> 00:48:23.360 DAVID J. MALAN: Ah, good question. 00:48:23.360 --> 00:48:25.750 If I wanted to add an exclamation point after the name, 00:48:25.750 --> 00:48:28.230 would I have to add another placeholder and so forth? 00:48:28.230 --> 00:48:29.980 I could actually do that much more simply. 00:48:29.980 --> 00:48:33.610 I can just put the exclamation point right after the percent sign. 00:48:33.610 --> 00:48:35.830 I don't need an additional placeholder, per se. 00:48:35.830 --> 00:48:40.030 If I zoom out now and run make hello again, ./hello, 00:48:40.030 --> 00:48:42.280 and type in just my name-- no exclamation point-- 00:48:42.280 --> 00:48:45.580 now you'll see more excitedly, hello, comma, David. 00:48:45.580 --> 00:48:46.510 So printf is smart. 00:48:46.510 --> 00:48:51.400 It will figure out where the %s is and then go and replace it. 00:48:51.400 --> 00:48:54.662 Now, let me propose that a common thing in programming 00:48:54.662 --> 00:48:57.370 is that as soon as we make a decision as how to design something, 00:48:57.370 --> 00:49:01.240 we often paint ourselves into a corner and regret a decision. 00:49:01.240 --> 00:49:08.410 Can anyone think of a problem that arises from using %s as a placeholder 00:49:08.410 --> 00:49:11.680 in this string to printf? 00:49:11.680 --> 00:49:14.635 What could go wrong if we're using percent in this special way? 00:49:14.635 --> 00:49:16.775 AUDIENCE: [INAUDIBLE] 00:49:16.775 --> 00:49:17.650 DAVID J. MALAN: Yeah. 00:49:17.650 --> 00:49:20.320 If you literally want to say, for whatever weird reason, 00:49:20.320 --> 00:49:23.245 %s on the screen-- or honestly, even just a single %. 00:49:23.245 --> 00:49:25.930 It turns out that a percent sign is treated 00:49:25.930 --> 00:49:29.650 specially inside of printf strings. 00:49:29.650 --> 00:49:31.460 So what's the solution here? 00:49:31.460 --> 00:49:34.690 There's different patterns of solutions to problems like these. 00:49:34.690 --> 00:49:40.990 But suppose you wanted to say, I got 100%, for instance. 00:49:40.990 --> 00:49:43.480 Let me go ahead and change this completely. 00:49:43.480 --> 00:49:47.290 So I got 100% on your test or whatever. 00:49:47.290 --> 00:49:50.860 All right, let me go ahead and run make hello, Enter. 00:49:50.860 --> 00:49:52.950 All right, so invalid conversions specifier. 00:49:52.950 --> 00:49:55.450 I mean, I have no idea what this means, but it's underlining 00:49:55.450 --> 00:49:57.410 the percent sign as problematic. 00:49:57.410 --> 00:50:00.730 Well, it turns out that humans years ago decided, ugh, all right, damn it. 00:50:00.730 --> 00:50:01.615 We already used %. 00:50:01.615 --> 00:50:04.990 Well, two percent signs will mean one %, literally. 00:50:04.990 --> 00:50:09.727 So now if I rerun make hello, aha, ./hello, I got 100%. 00:50:09.727 --> 00:50:13.060 So there's going to be things like that, honestly, that you have to ask someone, 00:50:13.060 --> 00:50:15.190 you have to Google, you have to look it up in the documentation. 00:50:15.190 --> 00:50:17.840 But there's always a solution to those kinds of problems. 00:50:17.840 --> 00:50:19.930 And thankfully, they don't come up all that often. 00:50:19.930 --> 00:50:21.230 Yeah? 00:50:21.230 --> 00:50:22.360 Oh, just pointing. 00:50:22.360 --> 00:50:23.060 Other questions? 00:50:23.060 --> 00:50:23.560 Yeah? 00:50:23.560 --> 00:50:27.622 AUDIENCE: So if you have multiple [INAUDIBLE] 00:50:27.622 --> 00:50:29.580 DAVID J. MALAN: If you have multiple variables, 00:50:29.580 --> 00:50:31.380 it is in the left-right order. 00:50:31.380 --> 00:50:34.187 So printf will analyze the first string of text 00:50:34.187 --> 00:50:35.520 that you pass in between quotes. 00:50:35.520 --> 00:50:40.290 And whatever the first % is, the first variable that's passed in after a comma 00:50:40.290 --> 00:50:41.207 gets plugged in there. 00:50:41.207 --> 00:50:44.290 And then the second gets plugged into the second, third, and to the third, 00:50:44.290 --> 00:50:44.832 and so forth. 00:50:44.832 --> 00:50:47.130 So it's just based on left to right. 00:50:47.130 --> 00:50:48.220 Yeah? 00:50:48.220 --> 00:50:50.760 AUDIENCE: This more of a clarification question. 00:50:50.760 --> 00:50:52.453 What exactly does the %s mean? 00:50:52.453 --> 00:50:54.120 DAVID J. MALAN: It's just a placeholder. 00:50:54.120 --> 00:50:58.570 It's called a format code, and it just means colloquially, plug in some value 00:50:58.570 --> 00:50:59.070 here. 00:50:59.070 --> 00:51:04.060 And printf-- the humans who wrote printf decades ago decided to treat %s 00:51:04.060 --> 00:51:04.560 special. 00:51:04.560 --> 00:51:04.890 Why? 00:51:04.890 --> 00:51:05.490 Just because. 00:51:05.490 --> 00:51:06.900 They needed some placeholder. 00:51:06.900 --> 00:51:10.110 They decided that, eh, no one's ever going to really want to type %s. 00:51:10.110 --> 00:51:12.420 And if they do, they can just do %%s. 00:51:12.420 --> 00:51:17.280 So they decided to implement printf in such a way that they have code that 00:51:17.280 --> 00:51:20.190 analyzes whatever text comes in, looks for %s, 00:51:20.190 --> 00:51:24.960 and then somehow plugs in the subsequent values into that placeholder. 00:51:24.960 --> 00:51:28.390 And just the-- ah, question? 00:51:28.390 --> 00:51:28.890 Sorry? 00:51:28.890 --> 00:51:30.870 AUDIENCE: What if we wanted to do our initials or something? 00:51:30.870 --> 00:51:33.720 DAVID J. MALAN: Ah, so what if you wanted to do a single characters, 00:51:33.720 --> 00:51:38.070 like initials, like D M or D J M for first, middle, last, absolutely. 00:51:38.070 --> 00:51:41.670 And that, too, is a perfect segue from the two of you to what, in general, 00:51:41.670 --> 00:51:44.310 are going to be called data types in C. 00:51:44.310 --> 00:51:48.135 So it turns out, in C, there's not only strings as text. 00:51:48.135 --> 00:51:50.760 And we'll see in more detail over the next couple of weeks what 00:51:50.760 --> 00:51:52.560 a string really is underneath the hood. 00:51:52.560 --> 00:51:55.620 But strings of text are not the only thing that programs can output. 00:51:55.620 --> 00:51:58.860 They can indeed output single characters, as for initials. 00:51:58.860 --> 00:52:01.020 They can output integers as well. 00:52:01.020 --> 00:52:03.510 Turns out that printf has different format codes 00:52:03.510 --> 00:52:05.868 for all sorts of different data types. 00:52:05.868 --> 00:52:08.410 And just some of the data types we'll see in the coming weeks 00:52:08.410 --> 00:52:10.530 will be this list here, which you'll notice it 00:52:10.530 --> 00:52:13.920 almost perfectly lines up with the CS50 functions 00:52:13.920 --> 00:52:17.722 that I rattled off earlier, like get_char, get_int, get_string. 00:52:17.722 --> 00:52:20.430 The reason we called those functions that is because each of them 00:52:20.430 --> 00:52:23.490 is designed to return to you a different type of value. 00:52:23.490 --> 00:52:26.070 We've used get_string already in this example here. 00:52:26.070 --> 00:52:29.880 We'll soon see get_int, and we'll see opportunities to use others. 00:52:29.880 --> 00:52:33.660 But these indeed are the menu of available data 00:52:33.660 --> 00:52:35.940 types plus others-- dot, dot, dot-- that you 00:52:35.940 --> 00:52:38.400 can use when writing a program in C. 00:52:38.400 --> 00:52:41.430 The onus, therefore, is on you to decide in advance, 00:52:41.430 --> 00:52:44.250 do I want to store an int in this variable, or a string, 00:52:44.250 --> 00:52:48.420 or, heck, when writing fancier code, an image, or a sound, or a video, even. 00:52:48.420 --> 00:52:51.030 Those can all be different data types, dot dot dot. 00:52:51.030 --> 00:52:54.300 But for now we'll focus really on just these primitives. 00:52:54.300 --> 00:52:54.988 That was a lot. 00:52:54.988 --> 00:52:57.030 Let's go ahead and take a five-minute break here. 00:52:57.030 --> 00:52:57.680 No cookies yet. 00:52:57.680 --> 00:53:00.180 But in five minutes, we'll come back, dive into more detail. 00:53:00.180 --> 00:53:02.097 On our second break today, we'll have cookies. 00:53:05.640 --> 00:53:07.295 All right, we are back. 00:53:07.295 --> 00:53:09.170 And so if you have been playing along at home 00:53:09.170 --> 00:53:11.587 but hitting some bumps in the road, that's totally normal. 00:53:11.587 --> 00:53:13.430 And indeed, the goals of lecture generally 00:53:13.430 --> 00:53:16.395 will be to give you a sense, conceptually, of where we'll 00:53:16.395 --> 00:53:18.020 be going during the course of the week. 00:53:18.020 --> 00:53:20.498 But it's indeed through the hands-on labs and problem sets 00:53:20.498 --> 00:53:22.790 that you'll really have an opportunity at your own pace 00:53:22.790 --> 00:53:25.730 to work through some of those same bumps in the road. 00:53:25.730 --> 00:53:28.880 But for today, let me give you a few more building blocks. 00:53:28.880 --> 00:53:31.460 And these two will translate from Scratch initially. 00:53:31.460 --> 00:53:33.860 Namely, like conditionals, like how now in C, 00:53:33.860 --> 00:53:36.690 after knowing now how we can use functions-- 00:53:36.690 --> 00:53:39.530 at least get_string and printf-- 00:53:39.530 --> 00:53:43.370 and we can use variables like the string I created earlier, 00:53:43.370 --> 00:53:46.490 how can I now add to the mix things like decision making and conditionals 00:53:46.490 --> 00:53:47.100 at that? 00:53:47.100 --> 00:53:50.780 Well, with conditionals in Scratch, we had this kind of syntax on the left. 00:53:50.780 --> 00:53:55.220 Here in Scratch is how you might express if two variables, x and y, 00:53:55.220 --> 00:53:56.360 have this relationship. 00:53:56.360 --> 00:54:01.020 If x is less than y, then say on the screen, x is less than y. 00:54:01.020 --> 00:54:03.320 Well, let me translate that to the right now in C code. 00:54:03.320 --> 00:54:06.500 So in C, the corresponding code is going to look like this, 00:54:06.500 --> 00:54:08.390 assuming x and y already exist-- 00:54:08.390 --> 00:54:09.530 more on that later. 00:54:09.530 --> 00:54:13.140 And notice a pattern we're going to see again and again. 00:54:13.140 --> 00:54:18.560 There is going to be parentheses around the x and less than y-- so parentheses 00:54:18.560 --> 00:54:20.390 around the Boolean expression, recall. 00:54:20.390 --> 00:54:23.768 The Boolean expression is the true/false, the yes/no answer, 00:54:23.768 --> 00:54:26.060 a question that you're trying to ask in order to decide 00:54:26.060 --> 00:54:27.680 whether or not to do something. 00:54:27.680 --> 00:54:29.310 So you use parentheses there. 00:54:29.310 --> 00:54:34.550 So similar in functions where we use parentheses for printf and parentheses 00:54:34.550 --> 00:54:38.660 for get_string, and this is just a weird inconsistency stylistically. 00:54:38.660 --> 00:54:42.860 When using the keyword if, you should, as a matter of best practice, 00:54:42.860 --> 00:54:44.690 put a space after the word if. 00:54:44.690 --> 00:54:49.070 When using a function like printf or get_string, you shouldn't. 00:54:49.070 --> 00:54:52.400 Both will work, but you'll find that these are conventions stylistically 00:54:52.400 --> 00:54:55.970 that most people adhere to-- so space when using an if here. 00:54:55.970 --> 00:54:58.850 All right, now inside of the curly braces 00:54:58.850 --> 00:55:02.360 is where the actual code goes that you want to execute conditionally. 00:55:02.360 --> 00:55:05.270 So if you want to print out x is less than y 00:55:05.270 --> 00:55:08.570 only if x is actually less than y in C, you 00:55:08.570 --> 00:55:10.670 use this open curly brace-- which, up until now, 00:55:10.670 --> 00:55:12.740 you've probably rarely used on your keyboard-- 00:55:12.740 --> 00:55:14.820 and the closed curly brace down here. 00:55:14.820 --> 00:55:17.960 And those are hugging, if you will, the one or more lines 00:55:17.960 --> 00:55:20.990 of code underneath the if-- very similar in spirit 00:55:20.990 --> 00:55:25.050 to how the orange block here hugs the purple puzzle piece here. 00:55:25.050 --> 00:55:27.050 So there's no graphics in C. It's all text. 00:55:27.050 --> 00:55:31.760 So you can think of those curly braces as really representing the same idea. 00:55:31.760 --> 00:55:37.460 As a side note, if you only have one line of code inside of the if 00:55:37.460 --> 00:55:41.430 condition, if you will, you strictly, speaking, don't need the curly braces. 00:55:41.430 --> 00:55:43.670 But as a matter of good style, do include them. 00:55:43.670 --> 00:55:46.040 It will make more obvious what your intent is. 00:55:46.040 --> 00:55:48.650 How about in Scratch if you wanted to express this-- 00:55:48.650 --> 00:55:52.700 two ways in the road that you might go, left or right, so to speak? 00:55:52.700 --> 00:55:56.480 Well, if x is less than y, I want to say, x is less than y. 00:55:56.480 --> 00:56:01.190 Else, I want to say the opposite, x is not less than y in this case. 00:56:01.190 --> 00:56:03.710 So I'm making a decision based on that Boolean expression. 00:56:03.710 --> 00:56:08.340 In C, It's almost the same, but you're adding to the mix the key word else-- 00:56:08.340 --> 00:56:11.210 so MIT borrowed for Scratch the same keyword there-- 00:56:11.210 --> 00:56:14.690 and a second pair of curly braces, open and close respectively. 00:56:14.690 --> 00:56:17.150 And you might guess now what goes inside of those. 00:56:17.150 --> 00:56:22.905 Well, you print out x is less than y, or you print out x is not less than y. 00:56:22.905 --> 00:56:25.280 All right, what if there is a three-way fork in the road? 00:56:25.280 --> 00:56:29.370 In Scratch, this actually gets a little unwieldy graphically, if you will. 00:56:29.370 --> 00:56:34.490 But notice that in Scratch, this is how we could express if x is less than y, 00:56:34.490 --> 00:56:36.110 say x is less than y. 00:56:36.110 --> 00:56:40.760 Else if x is greater than y, say x is greater than y. 00:56:40.760 --> 00:56:45.470 Else if x equals y, then say x is equal to y. 00:56:45.470 --> 00:56:48.770 Now, minor inconsistency here. 00:56:48.770 --> 00:56:51.980 Just a little bit ago, I claimed, in C, that an equal sign 00:56:51.980 --> 00:56:54.435 represents what operation? 00:56:54.435 --> 00:56:55.310 AUDIENCE: Assignment. 00:56:55.310 --> 00:56:57.770 DAVID J. MALAN: Assignment from right to left. 00:56:57.770 --> 00:56:59.900 Insofar as Scratch is really meant for kids, 00:56:59.900 --> 00:57:03.350 and they didn't really want to get into the weeds of this kind of semantic, 00:57:03.350 --> 00:57:06.360 equal sign in Scratch means equality. 00:57:06.360 --> 00:57:09.050 However, we're going to need to fix this in C in just a moment. 00:57:09.050 --> 00:57:11.750 In C, equal sign means assignment right to left. 00:57:11.750 --> 00:57:14.210 In Scratch, it literally means what you would expect. 00:57:14.210 --> 00:57:17.690 All right, let's translate this code then to C. On the right, 00:57:17.690 --> 00:57:20.780 this code would correspond really to this. 00:57:20.780 --> 00:57:24.110 And you can perhaps see, somewhat goofily, what the solution was, 00:57:24.110 --> 00:57:28.160 not unlike the %% solution earlier when humans painted themselves into one 00:57:28.160 --> 00:57:29.100 other corner. 00:57:29.100 --> 00:57:32.900 You say if, you say else if, and you say else if, 00:57:32.900 --> 00:57:36.620 and how did we resolve the use of a single equal sign already? 00:57:36.620 --> 00:57:39.650 In C, when you want to express equality-- 00:57:39.650 --> 00:57:42.110 is the thing on the left equal to the thing on the right-- 00:57:42.110 --> 00:57:45.590 you literally use two equal signs right next to each other, no space 00:57:45.590 --> 00:57:47.090 in between them. 00:57:47.090 --> 00:57:50.960 But now this code would be correct on both the left and the right, 00:57:50.960 --> 00:57:53.640 whether you're doing this in Scratch or C respectively. 00:57:53.640 --> 00:57:58.400 But now we can nitpick our code, specifically the design thereof. 00:57:58.400 --> 00:58:02.820 Logically, can anyone critique the design of this code, 00:58:02.820 --> 00:58:04.280 either in Scratch or C? 00:58:04.280 --> 00:58:06.200 I feel like we could do better. 00:58:06.200 --> 00:58:07.576 How about in back? 00:58:07.576 --> 00:58:10.908 AUDIENCE: The only option after it getting greater than or less 00:58:10.908 --> 00:58:12.930 than is [INAUDIBLE]. 00:58:12.930 --> 00:58:13.930 DAVID J. MALAN: Perfect. 00:58:13.930 --> 00:58:17.350 Logically, it's got to be the case that x is less than y, 00:58:17.350 --> 00:58:22.510 or x is greater than y, or by conclusion, it's got to be equal to y. 00:58:22.510 --> 00:58:24.910 So why are you wasting my time or the computer's time 00:58:24.910 --> 00:58:26.170 asking a third question? 00:58:26.170 --> 00:58:30.160 You don't need to ask this final else if because logically, as you note, 00:58:30.160 --> 00:58:31.510 it should go without saying. 00:58:31.510 --> 00:58:33.220 So it's a minor tweak. 00:58:33.220 --> 00:58:37.120 You're doing extra work potentially in the cases where x equals y. 00:58:37.120 --> 00:58:38.350 So we can just refine that. 00:58:38.350 --> 00:58:42.280 And just like in Scratch, you could just use an else block, similarly in C, 00:58:42.280 --> 00:58:47.110 could we simplify this code to just an else, a sort of catch-all logically 00:58:47.110 --> 00:58:49.720 that just handles the reality that, of course, that's going 00:58:49.720 --> 00:58:52.400 to be the final situation instead. 00:58:52.400 --> 00:58:55.570 All right, so we have this ability now to express conditionals 00:58:55.570 --> 00:58:56.770 with Boolean expressions. 00:58:56.770 --> 00:58:59.030 Let's actually do something with this next here. 00:58:59.030 --> 00:59:00.610 So let me go back to VS Code. 00:59:00.610 --> 00:59:03.520 I've closed hello.c, and I want to create a second file 00:59:03.520 --> 00:59:05.020 for the sake of some demos now. 00:59:05.020 --> 00:59:09.160 Recall that you can create a new files by typing code, space, and then 00:59:09.160 --> 00:59:11.440 the name of the file you want to create. 00:59:11.440 --> 00:59:13.565 For instance, I might do compare.c. 00:59:13.565 --> 00:59:15.940 I want to write a program that's going to start comparing 00:59:15.940 --> 00:59:17.740 some values for demonstration's sake. 00:59:17.740 --> 00:59:20.050 But before I do that, let me just show you 00:59:20.050 --> 00:59:23.830 by opening the File Explorer at right, this is similar in spirit 00:59:23.830 --> 00:59:25.180 to a Mac or PC. 00:59:25.180 --> 00:59:28.750 You can go up here and click on an icon, and you can click on the plus icon, 00:59:28.750 --> 00:59:30.010 and you'll get a blue box. 00:59:30.010 --> 00:59:34.120 And I can type in compare.c, and I can just manually create it that way. 00:59:34.120 --> 00:59:37.930 Notice that opens the tab even without my having typed code. 00:59:37.930 --> 00:59:41.470 So again, on the left, you have a GUI, a Graphical User Interface, 00:59:41.470 --> 00:59:42.820 albeit a simplistic one. 00:59:42.820 --> 00:59:45.970 On the right and at the bottom here, you have a command line interface, 00:59:45.970 --> 00:59:47.260 but they're one in the same. 00:59:47.260 --> 00:59:52.090 What's nice, though, is that if I close this file accidentally, intentionally, 00:59:52.090 --> 00:59:54.790 whatnot, I can reopen it without creating 00:59:54.790 --> 00:59:58.930 a new one by just running that same command-- code, space, compare.c. 00:59:58.930 --> 01:00:00.340 So code is a VS Code thing. 01:00:00.340 --> 01:00:02.140 It's just a user-friendly shortcut. 01:00:02.140 --> 01:00:05.888 But it's just creating a file or opening an existing file like that. 01:00:05.888 --> 01:00:08.930 I'm going to hide the File Explorer just to make more room for code here. 01:00:08.930 --> 01:00:10.222 And let's go ahead and do this. 01:00:10.222 --> 01:00:14.200 Let's write a program that compares two values that the human inputs, 01:00:14.200 --> 01:00:15.340 but not strings this time. 01:00:15.340 --> 01:00:17.170 Let's use some actual integers. 01:00:17.170 --> 01:00:20.920 All right, I'm going to go ahead and include the CS50 library's header 01:00:20.920 --> 01:00:22.090 file at top-- 01:00:22.090 --> 01:00:23.260 cs50.h. 01:00:23.260 --> 01:00:25.804 I'm going to also include stdio.h. 01:00:25.804 --> 01:00:26.668 Why? 01:00:26.668 --> 01:00:31.190 One gives me user-friendly input via get_string, get_int, and so forth. 01:00:31.190 --> 01:00:35.560 One gives me user-friendly output via printf in the case of stdio.h. 01:00:35.560 --> 01:00:39.430 Now I'm just going to blindly type this line of code, which we'll come back to 01:00:39.430 --> 01:00:40.310 in future weeks. 01:00:40.310 --> 01:00:42.520 But for now, that's analogous to the when 01:00:42.520 --> 01:00:44.920 green flag clicked code in Scratch. 01:00:44.920 --> 01:00:46.460 And now let's go ahead and do this. 01:00:46.460 --> 01:00:49.210 Let me go ahead and get_int from the user 01:00:49.210 --> 01:00:51.713 and ask the user, What's x, question mark. 01:00:51.713 --> 01:00:53.380 I'm not going to bother with a new line. 01:00:53.380 --> 01:00:56.410 I want to keep it all in one line, just for aesthetics' sake. 01:00:56.410 --> 01:00:59.710 But when I get back and int, just like I get back a string, 01:00:59.710 --> 01:01:01.580 I get back a return value. 01:01:01.580 --> 01:01:06.040 So if I want to store the result of get_int somewhere, 01:01:06.040 --> 01:01:07.927 I had better put it in a variable. 01:01:07.927 --> 01:01:09.760 And I can call the variable anything I want. 01:01:09.760 --> 01:01:12.790 Previously, I used answer, or first, or last. 01:01:12.790 --> 01:01:14.410 Now I'm going to use x. 01:01:14.410 --> 01:01:18.310 But there's still two things left to do here logically, even though we 01:01:18.310 --> 01:01:19.870 haven't technically done this yet. 01:01:19.870 --> 01:01:21.130 What I still need to do? 01:01:21.130 --> 01:01:22.410 AUDIENCE: A semicolon. 01:01:22.410 --> 01:01:24.535 DAVID J. MALAN: So I need the semicolon at the end. 01:01:24.535 --> 01:01:26.010 AUDIENCE: And the int first. 01:01:26.010 --> 01:01:27.885 DAVID J. MALAN: And the int at the beginning. 01:01:27.885 --> 01:01:31.257 You the programmer, starting today, need to decide what you're 01:01:31.257 --> 01:01:32.840 going to be storing in your variables. 01:01:32.840 --> 01:01:35.750 And you just need to tell the computer that so that it knows. 01:01:35.750 --> 01:01:38.990 Now, as a teaser for languages like Python, more modern languages, 01:01:38.990 --> 01:01:41.240 turns out, humans realized, well, gee, this is stupid. 01:01:41.240 --> 01:01:44.115 Why can't the computer just figure out that I'm putting an int there? 01:01:44.115 --> 01:01:45.800 Why do I have to tell it proactively? 01:01:45.800 --> 01:01:48.080 So in some languages nowadays, like Python 01:01:48.080 --> 01:01:50.990 will get rid of some of this syntax, will get rid of the semicolons. 01:01:50.990 --> 01:01:54.530 But for now we're looking at, really, the origins of how this all worked. 01:01:54.530 --> 01:01:57.380 All right, so I've done this one line ending with semicolon. 01:01:57.380 --> 01:01:58.440 Let me do one other. 01:01:58.440 --> 01:02:02.390 And let me get a second int asking the user, What's y, question mark. 01:02:02.390 --> 01:02:06.680 So almost identical but different responses from the user, hopefully. 01:02:06.680 --> 01:02:10.490 And let me just ask simply if x is less than y, 01:02:10.490 --> 01:02:14.690 in parentheses, then some curly braces, let me go ahead and print out, 01:02:14.690 --> 01:02:18.950 quote/unquote, x is less than y backslash n. 01:02:18.950 --> 01:02:20.600 And now just as a side note-- 01:02:20.600 --> 01:02:23.240 I seem to be typing fast. 01:02:23.240 --> 01:02:25.610 Some of that is because VS Code is helping me. 01:02:25.610 --> 01:02:29.720 Let me go back to this first line with the if, hit Enter. 01:02:29.720 --> 01:02:33.630 And now I'm only on my keyboard going to type the open curly brace. 01:02:33.630 --> 01:02:36.410 This is a feature of many text editors nowadays. 01:02:36.410 --> 01:02:37.980 It finishes part of your thought. 01:02:37.980 --> 01:02:38.480 Why? 01:02:38.480 --> 01:02:40.580 Just to save yourself a keystroke to make sure 01:02:40.580 --> 01:02:42.660 you don't accidentally forget the closing one. 01:02:42.660 --> 01:02:45.750 So you'll notice sometimes that things are happening that you didn't type. 01:02:45.750 --> 01:02:49.550 It's just VS Code or future programs you use trying to be helpful for you. 01:02:49.550 --> 01:02:52.445 I'll go ahead and manually type out now printf 01:02:52.445 --> 01:02:57.050 x is less than y backslash n close quote semicolon. 01:02:57.050 --> 01:03:01.400 So let me go ahead now and try to run this, and we'll see-- 01:03:01.400 --> 01:03:02.000 let's see. 01:03:02.000 --> 01:03:05.510 So make-- not hello-- but make compare because this file is 01:03:05.510 --> 01:03:09.050 called compare.c, hitting Enter. 01:03:09.050 --> 01:03:12.320 No output is good because it means I haven't messed up. 01:03:12.320 --> 01:03:16.580 Let me ./compare instead of ./hello, Enter. 01:03:16.580 --> 01:03:17.390 What's x? 01:03:17.390 --> 01:03:18.410 How about 1? 01:03:18.410 --> 01:03:19.040 What's y? 01:03:19.040 --> 01:03:19.840 How about 2? 01:03:19.840 --> 01:03:22.230 X is less than y. 01:03:22.230 --> 01:03:23.387 Well, let's try it again. 01:03:23.387 --> 01:03:25.220 And here, I'll save you some keystrokes too. 01:03:25.220 --> 01:03:26.360 Let me clear my screen. 01:03:26.360 --> 01:03:30.350 Instead of constantly typing ./this and ./that, 01:03:30.350 --> 01:03:34.610 you can also use your keyboard's arrow keys in VS Code to scroll back through 01:03:34.610 --> 01:03:35.310 time. 01:03:35.310 --> 01:03:37.940 So if I hit Up once, there's the last command I wrote. 01:03:37.940 --> 01:03:41.480 If I do it Up twice, there's the second to last command I wrote. 01:03:41.480 --> 01:03:43.460 So sometimes if you see me doing things fast, 01:03:43.460 --> 01:03:46.550 it's just because I'm cheating and going through my history like that. 01:03:46.550 --> 01:03:51.380 All right, let me go ahead, though, and rerun ./compare, Enter. 01:03:51.380 --> 01:03:52.670 Let's reverse it this time-- 01:03:52.670 --> 01:03:55.100 2 for x, 1 for y. 01:03:55.100 --> 01:03:56.870 And now, of course, there's no output. 01:03:56.870 --> 01:03:58.670 All right, well, that's logically to be expected 01:03:58.670 --> 01:04:00.170 because we didn't have an else here. 01:04:00.170 --> 01:04:00.980 So let's add that. 01:04:00.980 --> 01:04:05.060 Else-- now let's open my curly braces, letting VS Code do one of them 01:04:05.060 --> 01:04:12.350 for me-- printf, quote/unquote, x is not less than y backslash n semicolon. 01:04:12.350 --> 01:04:16.430 Let me go ahead and try this again-- ./compare, Enter. 01:04:16.430 --> 01:04:19.100 Again, 2 for x, 1 for y. 01:04:19.100 --> 01:04:20.540 And we should see-- 01:04:20.540 --> 01:04:22.990 huh. 01:04:22.990 --> 01:04:24.830 What did I do wrong? 01:04:24.830 --> 01:04:27.050 Why am I not seeing any else output? 01:04:27.050 --> 01:04:27.550 Yeah? 01:04:27.550 --> 01:04:29.592 AUDIENCE: You changed your code when you rebuild. 01:04:29.592 --> 01:04:30.690 You need to compile it. 01:04:30.690 --> 01:04:31.290 DAVID J. MALAN: Exactly. 01:04:31.290 --> 01:04:34.415 You got to get into the habit after you change your code of recompiling it. 01:04:34.415 --> 01:04:36.420 Or otherwise, the zeros and ones in the server 01:04:36.420 --> 01:04:39.000 are the old ones until you manually compile. 01:04:39.000 --> 01:04:41.040 So let's fix this-- make compare, Enter. 01:04:41.040 --> 01:04:42.030 No error messages. 01:04:42.030 --> 01:04:45.420 That's good. ./compare, 2, 1. 01:04:45.420 --> 01:04:47.320 And now I get back the output. 01:04:47.320 --> 01:04:49.230 So x is not less than y. 01:04:49.230 --> 01:04:52.390 How about if I go and add in the third condition? 01:04:52.390 --> 01:04:55.650 Well, we can do this either efficiently or inefficiently. 01:04:55.650 --> 01:04:57.270 Let me go ahead and refine this. 01:04:57.270 --> 01:05:03.780 So else if x is greater than y, let's literally say, x is greater than y. 01:05:03.780 --> 01:05:07.950 And now I could do x else if x equals equals y. 01:05:07.950 --> 01:05:11.080 But I think we already claimed that that's unnecessarily inefficient. 01:05:11.080 --> 01:05:12.810 So let's just have our catchall. 01:05:12.810 --> 01:05:14.730 And here I'm going to say, quote/unquote, 01:05:14.730 --> 01:05:19.960 x is equal to y backslash n, close quote there. 01:05:19.960 --> 01:05:24.070 So I think now with this code, we've handled all three scenarios. 01:05:24.070 --> 01:05:28.680 Let me go ahead and recompile it properly-- make compare, ./compare. 01:05:28.680 --> 01:05:31.350 And now 1 and 2-- 01:05:31.350 --> 01:05:32.340 is less than y. 01:05:32.340 --> 01:05:33.510 Let me run it again. 01:05:33.510 --> 01:05:36.690 2 and 1-- x is greater than y. 01:05:36.690 --> 01:05:41.100 And lastly, 1 and 1, and x is equal to y. 01:05:41.100 --> 01:05:43.270 So for the most part, our code is getting longer. 01:05:43.270 --> 01:05:45.870 We're up to 21 lines of code, though some of them 01:05:45.870 --> 01:05:47.700 are just single characters on the screen. 01:05:47.700 --> 01:05:49.410 Almost everything else is the same. 01:05:49.410 --> 01:05:56.190 I'm using the CS50 library's header file for my get_int function, stdio.h 01:05:56.190 --> 01:05:58.590 for my printf function, and the rest of this 01:05:58.590 --> 01:06:01.810 is just now new syntax for conditionals as well. 01:06:01.810 --> 01:06:04.350 Questions, then, on this C implementation 01:06:04.350 --> 01:06:08.237 of just some basic comparisons like this? 01:06:08.237 --> 01:06:08.820 Any questions? 01:06:08.820 --> 01:06:09.320 Yeah? 01:06:09.320 --> 01:06:12.360 AUDIENCE: Just a syntax question-- do the opening 01:06:12.360 --> 01:06:14.530 brackets need to be on a separate line? 01:06:14.530 --> 01:06:15.190 DAVID J. MALAN: Good question. 01:06:15.190 --> 01:06:17.440 Do the opening brackets need to be on a separate line? 01:06:17.440 --> 01:06:18.610 In CS50, yes. 01:06:18.610 --> 01:06:21.310 What you'll see is that as part of the submission process, 01:06:21.310 --> 01:06:25.540 we compare your code against a style guide, which is the norm in industry. 01:06:25.540 --> 01:06:29.290 A company would have its own sense of style and how its code should look. 01:06:29.290 --> 01:06:31.540 And there's generally automated tools within a company 01:06:31.540 --> 01:06:35.080 that help give feedback on the code or stylize it as such. 01:06:35.080 --> 01:06:38.410 There are alternative styles than what we use in the class. 01:06:38.410 --> 01:06:41.500 We deliberately keep and ask that you keep 01:06:41.500 --> 01:06:44.110 the curly braces on their own line, if only 01:06:44.110 --> 01:06:48.430 because it rather resembles like the hugging nature of Scratch's blocks 01:06:48.430 --> 01:06:51.370 and just makes clear that they're balanced, opened and closed. 01:06:51.370 --> 01:06:56.020 However, another common paradigm in some languages and with some programmers 01:06:56.020 --> 01:06:59.420 is to do something like this on each of them. 01:06:59.420 --> 01:07:03.670 So you have the opening curly brace on the same line as here. 01:07:03.670 --> 01:07:05.030 We do not recommend this. 01:07:05.030 --> 01:07:07.900 This is en vogue in the JavaScript world and some others. 01:07:07.900 --> 01:07:11.110 But ultimately in the real world, it's up to each individual programmer 01:07:11.110 --> 01:07:13.720 and/or the company they're working for, if applicable, 01:07:13.720 --> 01:07:16.210 to decide on those things. 01:07:16.210 --> 01:07:18.640 All right, so beyond, then, these conditionals, 01:07:18.640 --> 01:07:21.140 what if we want to do something that's maybe pretty common? 01:07:21.140 --> 01:07:24.280 So almost every piece of software or website nowadays that you use 01:07:24.280 --> 01:07:28.360 has you agree to some terms and conditions by typing Yes or No or just 01:07:28.360 --> 01:07:30.280 Y for Yes and N for No. 01:07:30.280 --> 01:07:33.195 So how could we implement some kind of agreement system? 01:07:33.195 --> 01:07:34.070 Well, let me do this. 01:07:34.070 --> 01:07:37.810 Let me create a new program, a third one called agree.c. 01:07:37.810 --> 01:07:41.230 So I'm going to write code agree.c just to give myself a new tab. 01:07:41.230 --> 01:07:44.230 I'm going to start, as always now, include cs50.h. 01:07:44.230 --> 01:07:46.480 Let's include stdio.h. 01:07:46.480 --> 01:07:50.770 And then let me do my int main(void)-- which, again, for today's purposes, 01:07:50.770 --> 01:07:53.200 we'll take at face value is just copy/paste. 01:07:53.200 --> 01:07:57.850 And if I just want to get Y or N, for instance, instead of Yes or No, 01:07:57.850 --> 01:08:00.520 we can just use a simpler variable here. 01:08:00.520 --> 01:08:03.800 How about just a char, a character, a single character? 01:08:03.800 --> 01:08:07.120 So I can use get_char to ask the user, for instance, 01:08:07.120 --> 01:08:09.760 do you agree, question mark. 01:08:09.760 --> 01:08:12.880 But as before, I need to store this somewhere. 01:08:12.880 --> 01:08:15.130 So I don't want a string because that's a single char. 01:08:15.130 --> 01:08:16.180 I don't want an int. 01:08:16.180 --> 01:08:17.380 I just want a char. 01:08:17.380 --> 01:08:21.500 And it's literally C-H-A-R. And then I can call this thing anything I want. 01:08:21.500 --> 01:08:25.370 It's conventional if you have a simple program with just a single variable 01:08:25.370 --> 01:08:27.040 and it's of type char, call it c. 01:08:27.040 --> 01:08:28.569 If it's an int, call it i. 01:08:28.569 --> 01:08:29.830 If it's a string, call it s. 01:08:29.830 --> 01:08:32.590 For now I'm just going to keep it simple and call it c. 01:08:32.590 --> 01:08:34.370 And now I'm going to ask a question. 01:08:34.370 --> 01:08:43.240 So if c equals equals, how about, quote/unquote, y, then 01:08:43.240 --> 01:08:47.290 let me go ahead and print out Agreed backslash n, 01:08:47.290 --> 01:08:50.380 as though they agreed to my terms and conditions. 01:08:50.380 --> 01:08:51.880 Otherwise, let's see. 01:08:51.880 --> 01:08:57.729 Else if the character equals equals, quote/unquote, n, then let me go ahead 01:08:57.729 --> 01:09:03.609 and print out, say, Not agreed, as though they didn't, quote/unquote. 01:09:03.609 --> 01:09:07.060 And let's leave it at that, I think, here initially. 01:09:07.060 --> 01:09:11.830 Now, you'll notice one curiosity, one inconsistency perhaps. 01:09:11.830 --> 01:09:15.760 Does anyone want to call it out, though it's somewhat subtle? 01:09:15.760 --> 01:09:19.720 I've done something ever so slightly differently without explaining it yet. 01:09:19.720 --> 01:09:20.380 Do you see it? 01:09:20.380 --> 01:09:22.625 AUDIENCE: The single quotation mark. 01:09:22.625 --> 01:09:23.500 DAVID J. MALAN: Yeah. 01:09:23.500 --> 01:09:27.880 So I've suddenly used single quotation marks for my single characters 01:09:27.880 --> 01:09:30.590 and double quotes for my actual strings of text. 01:09:30.590 --> 01:09:34.210 This is a necessity in C. When you're dealing with strings, like strings 01:09:34.210 --> 01:09:37.420 of text, like someone's name, a sentence, a paragraph, anything 01:09:37.420 --> 01:09:41.380 really more than one character, you typically use double quotes. 01:09:41.380 --> 01:09:42.399 And indeed, you must. 01:09:42.399 --> 01:09:47.620 When dealing with deliberately single characters, like I am here for y or n, 01:09:47.620 --> 01:09:49.819 you must use single quotes instead. 01:09:49.819 --> 01:09:50.319 Why? 01:09:50.319 --> 01:09:52.240 Because that makes sure that the computer 01:09:52.240 --> 01:09:54.550 knows that it's indeed a char and not a string. 01:09:54.550 --> 01:09:55.930 So double quotes are for strings. 01:09:55.930 --> 01:09:57.520 Single quotes are for chars. 01:09:57.520 --> 01:10:00.550 So with that said, let me go ahead and zoom out. 01:10:00.550 --> 01:10:04.780 Let me go ahead in my terminal window run make agree, Enter. 01:10:04.780 --> 01:10:08.770 Seems to work OK so let me go ahead and do ./agree. 01:10:08.770 --> 01:10:12.250 Let me go ahead now and type in y. 01:10:12.250 --> 01:10:13.090 Here we go. 01:10:13.090 --> 01:10:14.980 Enter. 01:10:14.980 --> 01:10:16.540 Huh. 01:10:16.540 --> 01:10:17.470 Let me try that again. 01:10:17.470 --> 01:10:18.580 Rerun ./agree. 01:10:18.580 --> 01:10:20.170 How about no? 01:10:20.170 --> 01:10:22.480 Enter. 01:10:22.480 --> 01:10:25.720 Why is it not behaving as I would have expected? 01:10:25.720 --> 01:10:28.480 AUDIENCE: Because you entered the capital Y and capital N. 01:10:28.480 --> 01:10:29.590 DAVID J. MALAN: Yeah, I kind of cheated there, 01:10:29.590 --> 01:10:32.230 and I hit the Caps Lock key just as I started typing in input. 01:10:32.230 --> 01:10:32.730 Why? 01:10:32.730 --> 01:10:35.950 Because I deliberately wanted to type in uppercase instead of lowercase, 01:10:35.950 --> 01:10:37.540 which is kind of reasonable. 01:10:37.540 --> 01:10:40.728 It's a little obnoxious if you force the user to toggle their caps lock 01:10:40.728 --> 01:10:42.770 key on or off when you just need a simple answer. 01:10:42.770 --> 01:10:45.310 That's not the best User Experience, or UX. 01:10:45.310 --> 01:10:47.200 But it would work if I cooperated. 01:10:47.200 --> 01:10:49.420 Let me run this again without caps lock-- 01:10:49.420 --> 01:10:52.030 y lowercase for yes. 01:10:52.030 --> 01:10:55.210 Ah, that worked. n lowercase for no. 01:10:55.210 --> 01:10:55.990 That worked. 01:10:55.990 --> 01:10:57.910 But how could I get it to work for both? 01:10:57.910 --> 01:10:59.180 Well, how about this? 01:10:59.180 --> 01:11:01.400 Let me go ahead and just add two possibilities. 01:11:01.400 --> 01:11:06.340 So else if c equals equals quote/unquote capital Y, 01:11:06.340 --> 01:11:10.720 then also do printf agreed backslash n. 01:11:10.720 --> 01:11:17.470 And down here, else if c equals equals single quote capital N, 01:11:17.470 --> 01:11:20.980 then go ahead and print out, again, Not agreed. 01:11:20.980 --> 01:11:23.770 This, I will claim now, is correct. 01:11:23.770 --> 01:11:26.980 And I'll do make agree real fast, ./agree. 01:11:26.980 --> 01:11:28.210 And I'll use capital. 01:11:28.210 --> 01:11:29.170 It now works. 01:11:29.170 --> 01:11:30.610 I'll use capital. 01:11:30.610 --> 01:11:32.200 It again works. 01:11:32.200 --> 01:11:34.510 But this is perhaps not the best design. 01:11:34.510 --> 01:11:39.220 Let me hide the terminal window and pull this up on the screen all at once. 01:11:39.220 --> 01:11:43.195 Why might this arguably not be the best design, even though it's correct? 01:11:46.250 --> 01:11:49.628 There's another term of art we can toss here, like [SNIFFS] something 01:11:49.628 --> 01:11:51.170 smells kind of funky about this code. 01:11:51.170 --> 01:11:52.450 This is an actual term of art. 01:11:52.450 --> 01:11:54.100 There's code smell here. 01:11:54.100 --> 01:11:55.930 Something smells a little off. 01:11:55.930 --> 01:11:56.620 Why? 01:11:56.620 --> 01:11:57.894 What do you think? 01:11:57.894 --> 01:12:01.846 AUDIENCE: [INAUDIBLE] 01:12:06.895 --> 01:12:07.770 DAVID J. MALAN: Yeah. 01:12:07.770 --> 01:12:09.370 There's the same output again and again. 01:12:09.370 --> 01:12:10.530 I mean, I manually typed it. 01:12:10.530 --> 01:12:12.905 But honestly, I might as well have just copied and pasted 01:12:12.905 --> 01:12:17.080 most of my original code to do it again and again for the two capital letters. 01:12:17.080 --> 01:12:23.370 So if line 10 and 14 are the same AND line 18 and 22 are the same, AND then 01:12:23.370 --> 01:12:26.875 the rest of these if and else ifs are almost the same, 01:12:26.875 --> 01:12:28.500 [SNIFFS] there's some code smell there. 01:12:28.500 --> 01:12:29.370 It's not well designed. 01:12:29.370 --> 01:12:29.820 Why? 01:12:29.820 --> 01:12:32.778 Because if I want to change things now, just like last week in Scratch, 01:12:32.778 --> 01:12:35.970 I might have to change my code in multiple places or copy/paste 01:12:35.970 --> 01:12:37.120 is never a good thing. 01:12:37.120 --> 01:12:41.280 And god forbid I want to add support for Yes and No as full words, 01:12:41.280 --> 01:12:42.760 it's really going to get long. 01:12:42.760 --> 01:12:44.170 So how can we solve this? 01:12:44.170 --> 01:12:47.160 Well, it turns out, we can combine some of these thoughts. 01:12:47.160 --> 01:12:49.470 So let me try to improve the Yeses first. 01:12:49.470 --> 01:12:54.325 It turns out, if I delete that clause, I can actually or things together. 01:12:54.325 --> 01:12:57.450 In Scratch, there's a couple of puzzle pieces, if you didn't discover them, 01:12:57.450 --> 01:12:59.430 that literally have the word or and the word 01:12:59.430 --> 01:13:02.350 and on them, which allow you to combine Boolean expressions. 01:13:02.350 --> 01:13:06.600 So that either this or this is true, or this and this is true. 01:13:06.600 --> 01:13:09.270 In C, you can't just say the word or. 01:13:09.270 --> 01:13:12.850 You instead use two vertical bars. 01:13:12.850 --> 01:13:16.260 And vertical bars together mean or, logically. 01:13:16.260 --> 01:13:21.780 And so I can say, c equals equals quote/unquote capital Y, Agreed. 01:13:21.780 --> 01:13:24.270 And now I can get rid of this code down here. 01:13:24.270 --> 01:13:29.100 And let me go ahead and say, vertical bar twice c 01:13:29.100 --> 01:13:32.340 equals quote/unquote N in all caps. 01:13:32.340 --> 01:13:36.870 And now my program's roughly a third smaller, which is good. 01:13:36.870 --> 01:13:38.140 There's less redundancy. 01:13:38.140 --> 01:13:43.290 And if I reopen my terminal window, rerun make of agree, ./agree, 01:13:43.290 --> 01:13:49.860 now I can type little y or big Y and same thing for lowercase and uppercase 01:13:49.860 --> 01:13:54.090 N. Any questions then on this syntax, whereby now you can combine thoughts 01:13:54.090 --> 01:13:56.407 and just tighten things up? 01:13:56.407 --> 01:13:57.990 And there'll be other such tricks too. 01:13:57.990 --> 01:13:58.942 Yeah? 01:13:58.942 --> 01:14:01.615 AUDIENCE: Is there not a function to just ignore the case? 01:14:01.615 --> 01:14:03.240 DAVID J. MALAN: A really good question. 01:14:03.240 --> 01:14:06.030 Is there not a function to just ignore the case? 01:14:06.030 --> 01:14:07.890 Short answer, there is. 01:14:07.890 --> 01:14:10.950 And we'll see how to do that in, actually, just about a week's time. 01:14:10.950 --> 01:14:13.080 And in other languages, there's even more ways 01:14:13.080 --> 01:14:17.100 to just canonicalize the user's input, throwing away any space characters 01:14:17.100 --> 01:14:19.890 they might have accidentally hit, forcing everything to lowercase. 01:14:19.890 --> 01:14:23.372 In C, It's going to be a little more work on our part to do that. 01:14:23.372 --> 01:14:26.080 But in fact, as early as next week, we'll see how we can do that. 01:14:26.080 --> 01:14:29.490 But for now we're comparing indeed just these literal values. 01:14:29.490 --> 01:14:30.570 Other questions? 01:14:30.570 --> 01:14:33.874 AUDIENCE: So we're assuming the user's putting in what they're suggesting. 01:14:33.874 --> 01:14:37.618 How do you handle if they were to put in a number? 01:14:37.618 --> 01:14:39.160 DAVID J. MALAN: Really good question. 01:14:39.160 --> 01:14:42.068 So we are assuming, with this program and all of my last ones, 01:14:42.068 --> 01:14:45.360 that the human's cooperating and when I ask for their name, they typed in David 01:14:45.360 --> 01:14:49.290 and not 123, or, in this case, they typed in a single character and not 01:14:49.290 --> 01:14:50.040 a full word. 01:14:50.040 --> 01:14:53.520 So this is one of the features often of using a library. 01:14:53.520 --> 01:14:59.550 So for instance, if I run agree again, and I say something like sure, Enter, 01:14:59.550 --> 01:15:01.330 it rejects it altogether. 01:15:01.330 --> 01:15:01.830 Why? 01:15:01.830 --> 01:15:05.850 Because s, u, r, e is a string of characters. 01:15:05.850 --> 01:15:07.320 It's not a single character. 01:15:07.320 --> 01:15:11.380 Now, I could just say something like x, which is neither y nor n, of course. 01:15:11.380 --> 01:15:14.190 But it tolerates that because it's a single character. 01:15:14.190 --> 01:15:17.790 But built in to CS50's library is some built-in rejections 01:15:17.790 --> 01:15:19.210 of inputs that's not expected. 01:15:19.210 --> 01:15:22.920 So if you use get_int and the user types in not the number 1 or 2 01:15:22.920 --> 01:15:26.940 but cat, C-A-T, it will just prompt them again, prompt them again. 01:15:26.940 --> 01:15:30.480 And this is where, too, if you were to do this manually in C, 01:15:30.480 --> 01:15:34.068 you end up writing this much code just to check for all of these errors. 01:15:34.068 --> 01:15:36.360 That's why we use these training wheels for a few weeks 01:15:36.360 --> 01:15:38.190 just to make the code more robust. 01:15:38.190 --> 01:15:40.500 But in a few weeks' time, we'll take the liberty away. 01:15:40.500 --> 01:15:44.970 And you'll see and understand how it's indeed doing all that. 01:15:44.970 --> 01:15:46.750 All right, so how about this. 01:15:46.750 --> 01:15:50.640 Let's now transition to something a little more Scratch-like, literally, 01:15:50.640 --> 01:15:53.290 by creating how about another program here called meow-- 01:15:53.290 --> 01:15:54.567 so meow.c. 01:15:54.567 --> 01:15:56.650 We won't have any audio capabilities for this one. 01:15:56.650 --> 01:15:57.750 We'll just rely on print. 01:15:57.750 --> 01:16:00.390 And suppose that I wanted to write a program 01:16:00.390 --> 01:16:03.000 and see that just simulates a cat meowing. 01:16:03.000 --> 01:16:04.960 So I don't need any user input just yet. 01:16:04.960 --> 01:16:06.960 So I'm just going to use stdio.h. 01:16:06.960 --> 01:16:09.940 I'm going to do my usual int main(void) up here. 01:16:09.940 --> 01:16:13.710 And then I'm just going to go ahead and do printf meow backslash n. 01:16:13.710 --> 01:16:16.650 And let's have this cat meow three times, like last week. 01:16:16.650 --> 01:16:18.870 So I'm going to do meow, meow, meow. 01:16:18.870 --> 01:16:21.100 Notice as an aside whenever you highlight the lines, 01:16:21.100 --> 01:16:22.350 you'll see little dots appear. 01:16:22.350 --> 01:16:24.780 This is just a visual cue to you to let you figure out 01:16:24.780 --> 01:16:26.460 how many spaces you've indented. 01:16:26.460 --> 01:16:30.133 VS Code, like a lot of editors, will automatically indent your code for you. 01:16:30.133 --> 01:16:32.550 I've not been hitting the space bar four times every time. 01:16:32.550 --> 01:16:34.020 I've not even been hitting Tab. 01:16:34.020 --> 01:16:38.280 However, in C, the convention is indeed to indent lines 01:16:38.280 --> 01:16:40.410 where appropriate by four spaces-- 01:16:40.410 --> 01:16:41.933 so not three, not five. 01:16:41.933 --> 01:16:44.100 And these dots help you see things so that they just 01:16:44.100 --> 01:16:45.850 line up as a matter of good style. 01:16:45.850 --> 01:16:48.600 All right, so this program, I'm just going to stipulate right now, 01:16:48.600 --> 01:16:49.600 is indeed going to work. 01:16:49.600 --> 01:16:52.560 Make meow-- which is kind of cute-- and now meow. 01:16:52.560 --> 01:16:54.000 There, three times. 01:16:54.000 --> 01:16:54.540 Correct. 01:16:54.540 --> 01:16:55.500 It's meowing three times. 01:16:55.500 --> 01:16:57.060 But of course, this is not well designed. 01:16:57.060 --> 01:16:58.935 It wasn't well designed in Scratch last week. 01:16:58.935 --> 01:17:00.480 Why? 01:17:00.480 --> 01:17:03.130 What should I be doing differently? 01:17:03.130 --> 01:17:03.630 Yeah? 01:17:03.630 --> 01:17:04.120 AUDIENCE: A loop? 01:17:04.120 --> 01:17:05.412 AUDIENCE: This could be a loop. 01:17:05.412 --> 01:17:07.140 DAVID J. MALAN: Yeah. 01:17:07.140 --> 01:17:09.310 It's a perfect opportunity for a loop. 01:17:09.310 --> 01:17:09.810 Why? 01:17:09.810 --> 01:17:12.810 Because if you wanted to change maybe the capitalization of these words, 01:17:12.810 --> 01:17:16.260 or you wanted to change the sound to like woof for a dog or something, 01:17:16.260 --> 01:17:18.390 you'd have to change it one, two, three places. 01:17:18.390 --> 01:17:20.160 And that's just kind of stupid, right? 01:17:20.160 --> 01:17:23.020 In code, you should ideally change things in one place. 01:17:23.020 --> 01:17:24.880 So how might I do that? 01:17:24.880 --> 01:17:27.120 Well, we could introduce a loop, yes. 01:17:27.120 --> 01:17:30.420 But we're going to need another building block as well that we had in Scratch, 01:17:30.420 --> 01:17:32.710 namely those things called variables. 01:17:32.710 --> 01:17:35.070 So recall that a variable, like an algebra-- x, 01:17:35.070 --> 01:17:38.520 y, z, whatever-- can store a value for you. 01:17:38.520 --> 01:17:42.630 And a variable in Scratch might have looked like this. 01:17:42.630 --> 01:17:45.880 You use this orange puzzle piece to set a variable of any name, 01:17:45.880 --> 01:17:46.890 not just x, y, or z. 01:17:46.890 --> 01:17:49.710 But you could call it something more descriptive, like counter, 01:17:49.710 --> 01:17:51.840 and you can set it equal to some value. 01:17:51.840 --> 01:17:56.490 In C, the way to do this is similar to spirit to some of the syntax 01:17:56.490 --> 01:17:57.570 we've seen thus far. 01:17:57.570 --> 01:17:59.910 You start by saying the name of the variable you want, 01:17:59.910 --> 01:18:01.740 a single equal sign, and then the value. 01:18:01.740 --> 01:18:05.470 You want to initialize it too, copying therefore from right to left. 01:18:05.470 --> 01:18:05.970 Why? 01:18:05.970 --> 01:18:09.570 Because the equal sign denotes, again, assignment from right to left. 01:18:09.570 --> 01:18:10.740 This isn't enough though. 01:18:10.740 --> 01:18:12.282 You might have the intuition already. 01:18:12.282 --> 01:18:16.170 What's missing probably from this line of code just to create a variable? 01:18:16.170 --> 01:18:16.767 AUDIENCE: Int. 01:18:16.767 --> 01:18:19.350 DAVID J. MALAN: So we need int to make sure the computer knows 01:18:19.350 --> 01:18:20.610 that this is indeed an int. 01:18:20.610 --> 01:18:23.802 And then lastly, semicolon as well. 01:18:23.802 --> 01:18:25.260 And that now completes the thought. 01:18:25.260 --> 01:18:27.302 So a little more annoying than Scratch, but we're 01:18:27.302 --> 01:18:28.660 starting to see patterns here. 01:18:28.660 --> 01:18:30.810 So not every piece of syntax will be new. 01:18:30.810 --> 01:18:33.480 All right, if you want to increment the counter by one, 01:18:33.480 --> 01:18:37.480 Scratch uses the verb change, and they mean add the value to counter. 01:18:37.480 --> 01:18:41.700 So if I want to increment an existing variable called counter, 01:18:41.700 --> 01:18:43.930 this syntax is a little more interesting. 01:18:43.930 --> 01:18:48.690 It turns out the code looks like this, which almost seems like a paradox. 01:18:48.690 --> 01:18:51.990 How can counter equal counter plus 1? 01:18:51.990 --> 01:18:53.160 That's not how math works. 01:18:53.160 --> 01:18:56.860 But again, a single equal sign is assignment from right to left. 01:18:56.860 --> 01:18:59.910 So this is saying, take whatever the value of counter is, add 1 to it, 01:18:59.910 --> 01:19:03.930 and copy that value from right to left into counter itself. 01:19:03.930 --> 01:19:07.530 You still need the semicolon, but I claim 01:19:07.530 --> 01:19:13.330 you do not need to mention the keyword int when updating an existing variable. 01:19:13.330 --> 01:19:18.060 So only when you create a variable in C do you use the word string, or the word 01:19:18.060 --> 01:19:19.950 int, or any of the others we'll eventually 01:19:19.950 --> 01:19:23.370 see-- only when creating it or initializing it for the first time. 01:19:23.370 --> 01:19:25.780 Thereafter if you want to change it, it just exists. 01:19:25.780 --> 01:19:27.060 It's the word you gave it. 01:19:27.060 --> 01:19:29.950 The computer is smart enough to at least remember what type it is. 01:19:29.950 --> 01:19:32.100 So this line is now complete 01:19:32.100 --> 01:19:35.580 Turns out, in code, as we'll see, it's pretty common to want to add things 01:19:35.580 --> 01:19:37.740 together, increment things by one. 01:19:37.740 --> 01:19:40.710 So there's actually different syntax for the same idea. 01:19:40.710 --> 01:19:43.290 The term of art here is syntactic sugar. 01:19:43.290 --> 01:19:46.410 There's often in code many ways to do the same thing, 01:19:46.410 --> 01:19:49.900 even though, at the end of the day, they do exactly the same functionality. 01:19:49.900 --> 01:19:54.120 So for instance, if, after a few days of CS50, you find this a little tedious 01:19:54.120 --> 01:19:57.765 to keep typing in some program, you can simplify it to just this. 01:19:57.765 --> 01:19:59.340 This is the syntactic sugar. 01:19:59.340 --> 01:20:03.810 You can use plus equals and only mention the variable name once on the left, 01:20:03.810 --> 01:20:06.480 and it just knows that means the previous thing. 01:20:06.480 --> 01:20:10.420 It's just slightly more succinct. 01:20:10.420 --> 01:20:12.900 This, too, is such a common thing to add 1 to a value. 01:20:12.900 --> 01:20:13.800 And it doesn't have to be 1. 01:20:13.800 --> 01:20:14.800 But in this case, it is. 01:20:14.800 --> 01:20:19.110 But if it is indeed 1, you can further tighten the code up to just do this, 01:20:19.110 --> 01:20:20.550 counter++. 01:20:20.550 --> 01:20:25.740 So any time in C you see ++, it means literally adding 1 to that particular 01:20:25.740 --> 01:20:26.472 variable. 01:20:26.472 --> 01:20:28.680 There's other ways to do this in the other direction. 01:20:28.680 --> 01:20:31.420 If you want to subtract 1 from a variable, 01:20:31.420 --> 01:20:34.890 you can use any of the previous syntax using a minus sign instead of plus, 01:20:34.890 --> 01:20:38.490 or you can more succinctly do counter--. 01:20:38.490 --> 01:20:42.520 This is the way a typical C programmer would do this. 01:20:42.520 --> 01:20:45.210 All right, so if we have no variables, let's 01:20:45.210 --> 01:20:47.500 go and solve the meowing with loop. 01:20:47.500 --> 01:20:49.320 So in Scratch, we saw loops like this. 01:20:49.320 --> 01:20:52.680 This, of course, had the cat meow three times. 01:20:52.680 --> 01:20:54.480 How do we do this in C? 01:20:54.480 --> 01:20:58.900 Now, this is where things get a little more involved code-wise. 01:20:58.900 --> 01:21:01.140 but if you understand each and every line, 01:21:01.140 --> 01:21:03.520 we'll follow logically what's going on. 01:21:03.520 --> 01:21:07.320 So here, I claim, is one way to implement 01:21:07.320 --> 01:21:12.330 a loop that iterates three times in C. And this is kind of ridiculous, right? 01:21:12.330 --> 01:21:15.900 We went from two super simple puzzle pieces like this to, my god, 01:21:15.900 --> 01:21:18.990 it's 1, 2, 3, 4, 5, 6 lines of code, all of which are pretty involved. 01:21:18.990 --> 01:21:20.740 So that escalated quickly. 01:21:20.740 --> 01:21:21.960 But what's each line doing? 01:21:21.960 --> 01:21:24.120 And we'll see other ways to do this more simply. 01:21:24.120 --> 01:21:28.710 So we're initializing a variable called counter to 3, just like before. 01:21:28.710 --> 01:21:29.370 Why? 01:21:29.370 --> 01:21:32.800 Well, what does it mean to loop or to repeat something three times? 01:21:32.800 --> 01:21:35.190 Well, it's like doing something three times, 01:21:35.190 --> 01:21:37.260 and then do it, and then count down, and then 01:21:37.260 --> 01:21:41.080 do it, and then count down, and then do it, until you're all out of counts. 01:21:41.080 --> 01:21:44.910 So this is declaring a variable called counter, setting it equal to 3. 01:21:44.910 --> 01:21:50.370 Then I'm inducing a loop in C, which is similar in spirit to repeat 3, 01:21:50.370 --> 01:21:52.440 but you have to do more of the math yourself. 01:21:52.440 --> 01:21:54.990 So I'm asking the question in parentheses, 01:21:54.990 --> 01:21:59.200 while count is greater than 0, what do I want to do? 01:21:59.200 --> 01:22:04.080 Well, per the indentation inside the curly braces, I want to meow one time. 01:22:04.080 --> 01:22:06.990 And then, to be clear, what's this last line of code doing? 01:22:06.990 --> 01:22:12.120 If counter starts off at three, this makes it 2 by subtracting 1 from it. 01:22:12.120 --> 01:22:13.320 Then what happens? 01:22:13.320 --> 01:22:17.620 By nature of the loop, just like in Scratch, it knows to go back and forth. 01:22:17.620 --> 01:22:21.010 even though there's a nice, pretty arrow in Scratch, and there isn't here, 01:22:21.010 --> 01:22:26.310 C knows to do this again, and again, and again, constantly asking this question 01:22:26.310 --> 01:22:28.870 and then updating this value at the end. 01:22:28.870 --> 01:22:33.690 So if I highlight just a few of these steps, the variable starts off at 3. 01:22:33.690 --> 01:22:35.100 And actually, let me simplify 2. 01:22:35.100 --> 01:22:37.980 I claimed earlier that when using single variables, 01:22:37.980 --> 01:22:41.280 people very often just call it i for int, or c for char, 01:22:41.280 --> 01:22:43.480 or s for string unless you have multiple variables. 01:22:43.480 --> 01:22:44.730 So let me tighten the code up. 01:22:44.730 --> 01:22:47.220 And this already makes it look a little more tolerable. 01:22:47.220 --> 01:22:50.320 Let me actually tighten it up further, add one more step. 01:22:50.320 --> 01:22:52.860 So now this is about as tight, as succinct 01:22:52.860 --> 01:22:54.653 as you can make this code at the moment. 01:22:54.653 --> 01:22:56.320 So what's actually going to happen here? 01:22:56.320 --> 01:22:59.550 Well, the first line of code executes, and that initializes i to 3. 01:22:59.550 --> 01:23:00.900 Then we check the condition. 01:23:00.900 --> 01:23:03.840 While i is greater than 0, is i greater than 0? 01:23:03.840 --> 01:23:05.580 Well, per my three fingers, obviously. 01:23:05.580 --> 01:23:07.590 So we print out meow on the screen. 01:23:07.590 --> 01:23:13.110 Then we subtract 1 from i, at which point now we have 2 as the value of i. 01:23:13.110 --> 01:23:15.330 Then the code goes back to the condition. 01:23:15.330 --> 01:23:17.580 And notice, the condition there is in parentheses. 01:23:17.580 --> 01:23:19.420 That's another Boolean expression. 01:23:19.420 --> 01:23:23.340 So loops can use Boolean expressions, just like conditionals use 01:23:23.340 --> 01:23:24.990 Boolean expressions to make decisions. 01:23:24.990 --> 01:23:27.840 The loop, though, is deciding not whether to do this thing or that 01:23:27.840 --> 01:23:31.330 but whether to do the same thing again, and again, and again. 01:23:31.330 --> 01:23:34.200 And as it ticks through the code one line after the other, 01:23:34.200 --> 01:23:40.450 it's ultimately going to get down to 1, and then 0, and then stop. 01:23:40.450 --> 01:23:45.330 So put another way-- came with some props here-- so suppose this ball here 01:23:45.330 --> 01:23:49.410 is your variable, and you initialize it to 3 with three stress balls, 01:23:49.410 --> 01:23:51.570 you can do something three times, right? 01:23:51.570 --> 01:23:53.320 If I want to give out three stress balls-- 01:23:53.320 --> 01:23:56.653 here's your chance for free stress balls without having to answer any questions. 01:23:56.653 --> 01:23:57.400 OK, there we go. 01:23:57.400 --> 01:24:00.180 So here we go, subtracting 1 from my variable. 01:24:00.180 --> 01:24:01.830 I'm left with two. 01:24:01.830 --> 01:24:02.460 Oh my god. 01:24:02.460 --> 01:24:04.845 All right, don't tell Sanders. 01:24:04.845 --> 01:24:07.470 [GRUNTS] Oh, I'm sorry. 01:24:07.470 --> 01:24:08.080 Oh. 01:24:08.080 --> 01:24:08.580 [LAUGHTER] 01:24:08.580 --> 01:24:10.350 OK, that ended poorly. 01:24:10.350 --> 01:24:11.070 Apologies. 01:24:11.070 --> 01:24:11.570 All right. 01:24:11.570 --> 01:24:13.740 But now the educational point, though, is 01:24:13.740 --> 01:24:17.037 that my variable has been decrement did further to just have-- 01:24:17.037 --> 01:24:18.370 I'm not throwing that far again. 01:24:18.370 --> 01:24:19.620 I can't do this. 01:24:19.620 --> 01:24:20.143 Here we go. 01:24:20.143 --> 01:24:21.060 All right, here we go. 01:24:21.060 --> 01:24:22.740 And one final subtraction. 01:24:22.740 --> 01:24:24.880 And now our variable is left empty. 01:24:24.880 --> 01:24:28.380 So we had three stress balls there, and that's all a variable is. 01:24:28.380 --> 01:24:29.475 It's some kind of storage. 01:24:29.475 --> 01:24:32.100 It's actually, of course, implemented in the computer's memory. 01:24:32.100 --> 01:24:35.860 But metaphorically, it's really just a bowl with some values. 01:24:35.860 --> 01:24:37.800 And every time you or, in this case, subtract, 01:24:37.800 --> 01:24:39.840 you're just changing the value of that variable. 01:24:39.840 --> 01:24:43.830 And then the code, meanwhile, of course, in parentheses, is just checking, 01:24:43.830 --> 01:24:44.610 is the bowl empty? 01:24:44.610 --> 01:24:45.360 Is the bowl empty? 01:24:45.360 --> 01:24:46.570 Is the bowl empty? 01:24:46.570 --> 01:24:50.350 AKA, is i greater than 0 or not? 01:24:50.350 --> 01:24:55.210 Any questions on how we've implemented loops in this way? 01:24:55.210 --> 01:24:58.080 And I owe you a stress ball after class. 01:24:58.080 --> 01:24:59.820 Questions on loops? 01:24:59.820 --> 01:25:03.240 All right, so it turns out, this is kind of ugly. 01:25:03.240 --> 01:25:05.580 And this really starts to take the fun out 01:25:05.580 --> 01:25:09.422 of programming when you have to write out this sequence of steps. 01:25:09.422 --> 01:25:11.380 So it turns out, there's other ways to do this. 01:25:11.380 --> 01:25:13.110 But first, let's see, logically, how else 01:25:13.110 --> 01:25:16.410 you might express this because it's a little weird that we keep using zero. 01:25:16.410 --> 01:25:19.890 So the one other way to do this would be to invert the logic. 01:25:19.890 --> 01:25:23.820 You could absolutely start with your variable, call it i equal to 1. 01:25:23.820 --> 01:25:28.290 And then you could ask the question, is i less than or equal to 3? 01:25:28.290 --> 01:25:30.210 And notice a bit of new syntax here. 01:25:30.210 --> 01:25:33.330 On your typical keyboard, there is number less than 01:25:33.330 --> 01:25:35.370 or equal sign or greater than or equal sign 01:25:35.370 --> 01:25:37.870 like you would write in math class with 1 over the other. 01:25:37.870 --> 01:25:42.390 And so in C, you use two characters, less than followed by an equal sign 01:25:42.390 --> 01:25:45.360 or, if appropriate, greater than followed by in equal sign. 01:25:45.360 --> 01:25:47.370 And that logically captures that idea. 01:25:47.370 --> 01:25:50.580 So notice that I'm changing my questions. 01:25:50.580 --> 01:25:53.910 I'm initializing i to 1, and then I'm going to increment it ultimately 01:25:53.910 --> 01:25:55.830 to 2 and then 3. 01:25:55.830 --> 01:25:57.930 But because I'm doing less than or equal to, 01:25:57.930 --> 01:26:00.340 it's still going to go from 1, 2, 3. 01:26:00.340 --> 01:26:01.530 So that works too. 01:26:01.530 --> 01:26:03.810 We could similarly do this yet another way. 01:26:03.810 --> 01:26:10.320 We could initialize i to 0, and then we could say, well, i is less than 3 01:26:10.320 --> 01:26:11.640 and keep incrementing it. 01:26:11.640 --> 01:26:14.940 And I showed this last form is actually the most canonical. 01:26:14.940 --> 01:26:18.420 It might be the most human-like to think in terms of 1 to 3. 01:26:18.420 --> 01:26:22.620 It might be the most stressball-like to think in terms of 3 to 0, 01:26:22.620 --> 01:26:23.740 counting down. 01:26:23.740 --> 01:26:26.730 But typically, the go-to syntax for most programmers 01:26:26.730 --> 01:26:31.440 once you get comfortable counting from 0 is to always start counting from 0 01:26:31.440 --> 01:26:35.610 and count up to less than the value you're counting up to. 01:26:35.610 --> 01:26:40.043 So it would be incorrect, why, to change this to less than or equal to 3 here? 01:26:40.043 --> 01:26:42.960 What would happen if I changed the less than to less than or equal to? 01:26:42.960 --> 01:26:44.340 AUDIENCE: It'll only meow twice. 01:26:44.340 --> 01:26:47.280 DAVID J. MALAN: Yeah, it'll meow an extra-- a fourth time, in fact, total, 01:26:47.280 --> 01:26:47.780 right? 01:26:47.780 --> 01:26:51.150 Because you'll start at 0, then 1, then 2, then 3. 01:26:51.150 --> 01:26:53.220 And less than or equal to 3-- sorry-- 01:26:53.220 --> 01:26:55.420 3 will give you the fourth time. 01:26:55.420 --> 01:26:58.650 So we do want indeed to be just a single less than. 01:26:58.650 --> 01:27:01.198 All right, so now that we have those options, 01:27:01.198 --> 01:27:02.490 let me just give you one other. 01:27:02.490 --> 01:27:04.907 And this one takes a little more, getting used to as well, 01:27:04.907 --> 01:27:07.210 but it's probably the more common way to write this. 01:27:07.210 --> 01:27:11.590 Let me go ahead and propose that we implement this as follows. 01:27:11.590 --> 01:27:13.390 Let me go back to my code here. 01:27:13.390 --> 01:27:20.040 Let me go into my several printfs, getting rid of all but one of them 01:27:20.040 --> 01:27:21.000 ultimately. 01:27:21.000 --> 01:27:22.750 And let's implement this in code. 01:27:22.750 --> 01:27:30.510 So let's do int i get 0, how about then while i is less than 3, 01:27:30.510 --> 01:27:33.960 then let's go ahead and say printf quote/unquote meow-- 01:27:33.960 --> 01:27:36.930 melow-- meow backslash n. 01:27:36.930 --> 01:27:41.310 And then we have to do i minus minus or plus plus? 01:27:41.310 --> 01:27:42.237 AUDIENCE: Plus plus. 01:27:42.237 --> 01:27:44.570 DAVID J. MALAN: So plus plus because we're starting at 0 01:27:44.570 --> 01:27:47.120 and going up to but not through 3. 01:27:47.120 --> 01:27:51.678 So let me go ahead now and make meow after clearing my terminal, ./meow, 01:27:51.678 --> 01:27:52.970 and it's still just as correct. 01:27:52.970 --> 01:27:55.400 But it's a little more-- 01:27:55.400 --> 01:27:56.730 it's a little better designed. 01:27:56.730 --> 01:27:57.230 Why? 01:27:57.230 --> 01:28:00.770 Because now if I want to change it from 3 to 30 times, for instance, 01:28:00.770 --> 01:28:01.850 I can change it there. 01:28:01.850 --> 01:28:03.770 I can recompile my code. 01:28:03.770 --> 01:28:06.020 I can do ./meow, and done. 01:28:06.020 --> 01:28:09.450 I don't have to copy and paste it 27 more times to get that effect. 01:28:09.450 --> 01:28:13.400 And I can even change what the word is by changing it in just one location. 01:28:13.400 --> 01:28:15.920 But it turns out, there's other ways to do this too. 01:28:15.920 --> 01:28:20.502 And let me propose that we introduce you to what's called a for loop as well. 01:28:20.502 --> 01:28:22.460 So if you want to repeat something three times, 01:28:22.460 --> 01:28:25.940 you can absolutely take the while loop approach that we just saw, 01:28:25.940 --> 01:28:27.500 or you can do this. 01:28:27.500 --> 01:28:30.270 And this one takes a little more, getting used to, 01:28:30.270 --> 01:28:34.200 but it kind of consolidates into one line all of the same logic. 01:28:34.200 --> 01:28:36.830 So notice, we have the keyword for here. 01:28:36.830 --> 01:28:40.730 And for is just a preposition in this case that generally implies, 01:28:40.730 --> 01:28:42.110 here comes a loop. 01:28:42.110 --> 01:28:46.097 Inside of parentheses here is not just a Boolean expression. 01:28:46.097 --> 01:28:47.930 And this is where things get a little weird. 01:28:47.930 --> 01:28:50.900 There's three things-- to the left of the semicolon, 01:28:50.900 --> 01:28:54.230 in the middle of the two semicolons, and to the right of the semicolon. 01:28:54.230 --> 01:28:58.198 This is really the only other context we'll see semicolons, and it's weird. 01:28:58.198 --> 01:28:59.990 Normally, it's been at the end of the line. 01:28:59.990 --> 01:29:02.030 Now it's two of them in the middle of the line, 01:29:02.030 --> 01:29:04.920 but this is the way humans decided years ago to do it. 01:29:04.920 --> 01:29:06.080 So what is this doing? 01:29:06.080 --> 01:29:07.850 Almost the same thing. 01:29:07.850 --> 01:29:12.320 It is going to initialize a variable called i to 0. 01:29:12.320 --> 01:29:14.240 It's going to then check. 01:29:14.240 --> 01:29:19.880 If it's less than 3, it's then going to do whatever's in the curly braces, 01:29:19.880 --> 01:29:22.980 and it's lastly going to increment i and repeat. 01:29:22.980 --> 01:29:26.240 So just highlighting those in turn, at first, i 01:29:26.240 --> 01:29:28.340 is initialized to 0, just like before. 01:29:28.340 --> 01:29:30.170 Then this condition is checked. 01:29:30.170 --> 01:29:32.150 This is a Boolean expression. 01:29:32.150 --> 01:29:34.610 Yes or no, true or false will be its answer. 01:29:34.610 --> 01:29:37.970 And if i is less than 3, which it should be once it starts at 0, 01:29:37.970 --> 01:29:40.550 well, then we're going to go ahead and print out meow. 01:29:40.550 --> 01:29:42.350 Then i is going to get incremented. 01:29:42.350 --> 01:29:43.580 So it starts at 0. 01:29:43.580 --> 01:29:45.170 It goes now to 1. 01:29:45.170 --> 01:29:48.150 At that point, the Boolean expression is checked again. 01:29:48.150 --> 01:29:50.840 So you don't keep changing i back to 0. 01:29:50.840 --> 01:29:53.210 That first step happens only once. 01:29:53.210 --> 01:29:56.270 But now you repeat through those three other highlights. 01:29:56.270 --> 01:29:57.770 I check if i is less than 3. 01:29:57.770 --> 01:29:58.320 It is. 01:29:58.320 --> 01:29:59.600 So I print out meow. 01:29:59.600 --> 01:30:00.875 It then increments i. 01:30:00.875 --> 01:30:03.410 I check if i, now 2, is less than 3. 01:30:03.410 --> 01:30:03.980 It is. 01:30:03.980 --> 01:30:05.240 I print out meow. 01:30:05.240 --> 01:30:06.380 i gets incremented. 01:30:06.380 --> 01:30:07.100 I now check. 01:30:07.100 --> 01:30:08.120 Is i less than 3? 01:30:08.120 --> 01:30:11.360 No, it's not, because 3 is not less than 3. 01:30:11.360 --> 01:30:12.800 And so the whole thing stops. 01:30:12.800 --> 01:30:15.950 And whatever code is below this curly brace, if any, 01:30:15.950 --> 01:30:17.420 starts executing instead. 01:30:17.420 --> 01:30:21.470 Just like in Scratch, you break out of the loop and the puzzle pieces 01:30:21.470 --> 01:30:22.610 being hugged. 01:30:22.610 --> 01:30:31.520 Questions, then, about this alternative syntax for loops, AKA, a for loop? 01:30:31.520 --> 01:30:34.195 AUDIENCE: Can you explain again why it doesn't go back to 0? 01:30:34.195 --> 01:30:35.570 DAVID J. MALAN: Sorry, say again? 01:30:35.570 --> 01:30:37.400 AUDIENCE: Can you explain again why it doesn't reset to 0? 01:30:37.400 --> 01:30:38.275 DAVID J. MALAN: Yeah. 01:30:38.275 --> 01:30:40.400 Can I explain again why it doesn't reset to 0? 01:30:40.400 --> 01:30:41.690 Honestly, just because. 01:30:41.690 --> 01:30:43.490 This was the syntax they chose. 01:30:43.490 --> 01:30:45.620 This first part before the first semicolon 01:30:45.620 --> 01:30:47.660 is only executed once just because. 01:30:47.660 --> 01:30:48.740 That's how it's designed. 01:30:48.740 --> 01:30:51.660 Everything else cycles again and again. 01:30:51.660 --> 01:30:54.277 And this is just an alternative syntax to using 01:30:54.277 --> 01:30:55.610 the slightly more lines of code. 01:30:55.610 --> 01:30:57.818 It was, like, six lines of code using the while loop. 01:30:57.818 --> 01:30:59.387 Logically, it's the same thing. 01:30:59.387 --> 01:31:01.220 Programmers, once they get more comfortable, 01:31:01.220 --> 01:31:04.053 tend to prefer this because it just expresses all your same thoughts 01:31:04.053 --> 01:31:05.240 more succinctly. 01:31:05.240 --> 01:31:06.380 That's all. 01:31:06.380 --> 01:31:06.890 Yeah? 01:31:06.890 --> 01:31:07.620 AUDIENCE: That was my question. 01:31:07.620 --> 01:31:08.412 DAVID J. MALAN: OK. 01:31:08.412 --> 01:31:11.210 So let's just work this into my meow example. 01:31:11.210 --> 01:31:12.590 Let me go back to the code here. 01:31:12.590 --> 01:31:14.898 And notice, indeed, if I highlight all these lines, 01:31:14.898 --> 01:31:16.190 I think we can tighten this up. 01:31:16.190 --> 01:31:21.350 Let me get rid of all of those and instead do for int i equals 0. 01:31:21.350 --> 01:31:22.790 And I'm saying equals. 01:31:22.790 --> 01:31:24.260 Most programmers would say gets. 01:31:24.260 --> 01:31:28.130 So int i gets 0 means assignment-- the word get. 01:31:28.130 --> 01:31:32.360 Now I'm going to do i is less than 3 i++. 01:31:32.360 --> 01:31:37.670 Now in here I'm going to do my printf quote/unquote meow backslash n. 01:31:37.670 --> 01:31:39.450 And so it's indeed a little tighter. 01:31:39.450 --> 01:31:41.408 I mean, two of the lines are just curly braces. 01:31:41.408 --> 01:31:43.580 There's really only two juicy lines of code now. 01:31:43.580 --> 01:31:47.460 Let me go ahead and do make meow, ./meow. 01:31:47.460 --> 01:31:51.680 And again, we're back in business with three of them printing only. 01:31:51.680 --> 01:31:54.050 All right, there's one last structure we should explore 01:31:54.050 --> 01:31:56.330 just because it's sometimes useful. 01:31:56.330 --> 01:31:58.010 This was a forever block. 01:31:58.010 --> 01:32:00.170 And this would be a little weird in Scratch 01:32:00.170 --> 01:32:02.750 to just say meow forever, or at least without waiting. 01:32:02.750 --> 01:32:06.290 But there is indeed a forever block in Scratch, which means do the following, 01:32:06.290 --> 01:32:07.490 forever. 01:32:07.490 --> 01:32:10.485 And I proposed, I think, verbally last week at least one example 01:32:10.485 --> 01:32:11.360 where this is useful. 01:32:11.360 --> 01:32:13.040 Meowing forever, a little annoying. 01:32:13.040 --> 01:32:14.990 But can you think of common cases where you 01:32:14.990 --> 01:32:19.100 might want to write code or use a program that loops forever? 01:32:19.100 --> 01:32:19.657 Yeah? 01:32:19.657 --> 01:32:21.740 AUDIENCE: Playing music throughout an entire game. 01:32:21.740 --> 01:32:22.970 DAVID J. MALAN: Yeah, playing music. 01:32:22.970 --> 01:32:25.370 Like Spotify playlists, just repeating again and again 01:32:25.370 --> 01:32:26.495 would be some kind of loop. 01:32:26.495 --> 01:32:28.310 AUDIENCE: Checking for collisions. 01:32:28.310 --> 01:32:29.840 DAVID J. MALAN: Checking for collisions in Scratch, 01:32:29.840 --> 01:32:32.548 so seeing if something's bouncing off the wall or another sprite. 01:32:32.548 --> 01:32:33.590 Yeah? 01:32:33.590 --> 01:32:36.512 AUDIENCE: Oh, checking for input. 01:32:36.512 --> 01:32:37.970 DAVID J. MALAN: Checking for input. 01:32:37.970 --> 01:32:40.900 So yeah, get_string is essentially just waiting there forever 01:32:40.900 --> 01:32:43.300 for me to type in some input until I do. 01:32:43.300 --> 01:32:44.470 AUDIENCE: Checking the time. 01:32:44.470 --> 01:32:45.760 DAVID J. MALAN: Checking the time and actually 01:32:45.760 --> 01:32:47.860 maintaining human time, like a wall clock. 01:32:47.860 --> 01:32:48.550 Behind you? 01:32:48.550 --> 01:32:49.420 Is that the same? 01:32:49.420 --> 01:32:50.590 AUDIENCE: I was going to say checking the time. 01:32:50.590 --> 01:32:52.173 DAVID J. MALAN: OK, checking the time. 01:32:52.173 --> 01:32:52.900 And one more? 01:32:52.900 --> 01:32:53.995 Detecting a key press too. 01:32:53.995 --> 01:32:56.620 Like in Scratch, just waiting for some kind of event to happen, 01:32:56.620 --> 01:32:58.182 just like on a phone or a browser. 01:32:58.182 --> 01:32:59.890 And so there's so many examples where you 01:32:59.890 --> 01:33:01.510 might want to do something forever-- 01:33:01.510 --> 01:33:04.520 just so you've seen the corresponding C building block. 01:33:04.520 --> 01:33:08.290 It's a little weird, but this is probably the most canonical way 01:33:08.290 --> 01:33:11.783 to do it in C. If you want to print meow forever-- 01:33:11.783 --> 01:33:14.950 which would be a little crazy because it would literally print and take over 01:33:14.950 --> 01:33:16.990 your computer printing forever meow-- 01:33:16.990 --> 01:33:18.850 you would generally do it like this. 01:33:18.850 --> 01:33:19.490 Why? 01:33:19.490 --> 01:33:22.810 Well, a while loop expects in parentheses a Boolean expression, 01:33:22.810 --> 01:33:26.020 and a Boolean expression is, again, a yes/no, a true/false question. 01:33:26.020 --> 01:33:29.620 But if you want the answer to that question always to be yes-- 01:33:29.620 --> 01:33:33.490 or really, always to be true, turns out in C and a lot of languages 01:33:33.490 --> 01:33:35.950 will then just say true because true-- 01:33:35.950 --> 01:33:38.800 T-R-U-E-- is never going to change magically to false. 01:33:38.800 --> 01:33:41.570 I mean, it's just a special word in the programming language. 01:33:41.570 --> 01:33:45.680 So by saying while true, it just means do the following forever. 01:33:45.680 --> 01:33:48.580 Another common paradigm before true and false 01:33:48.580 --> 01:33:52.300 became commonplace would be to do this instead-- 01:33:52.300 --> 01:33:54.220 change while 1. 01:33:54.220 --> 01:33:57.820 You might see in online examples and texts and the like, 01:33:57.820 --> 01:33:59.770 while 1 is really the same thing. 01:33:59.770 --> 01:34:04.840 Any value that is 0 is generally interpreted as false by a computer. 01:34:04.840 --> 01:34:09.310 Any value that is 1 or any other non-zero value 01:34:09.310 --> 01:34:11.210 is generally interpreted as true. 01:34:11.210 --> 01:34:15.400 And so this, too, would have the same effect, saying while true or while 1. 01:34:15.400 --> 01:34:18.700 Generally speaking, while true is perhaps a little clearer these days. 01:34:18.700 --> 01:34:20.650 Now, meowing forever is not a good thing. 01:34:20.650 --> 01:34:23.770 But suppose I did that by intent or by accident. 01:34:23.770 --> 01:34:24.950 Well, let's try this. 01:34:24.950 --> 01:34:26.570 So here I'll go into my code. 01:34:26.570 --> 01:34:30.550 I'm going to get rid of for loop and change my while loop to, how about, 01:34:30.550 --> 01:34:32.180 true. 01:34:32.180 --> 01:34:36.100 And in this case here, well, we'll keep it-- let's do this. 01:34:36.100 --> 01:34:38.230 Make meow, Enter. 01:34:38.230 --> 01:34:41.840 And you'll see this, use of undeclared identifier true. 01:34:41.840 --> 01:34:46.360 This is actually hinting at my mention that the old way was 0 and 1. 01:34:46.360 --> 01:34:48.220 Nowadays, you could say true or false. 01:34:48.220 --> 01:34:53.560 But true and false are themselves special words that you have to include. 01:34:53.560 --> 01:34:56.740 And it turns out, if you want to use special Boolean values like this, 01:34:56.740 --> 01:35:00.850 there's another header file we haven't seen called stdbool that essentially 01:35:00.850 --> 01:35:03.640 creates true and false as keywords. 01:35:03.640 --> 01:35:06.550 Alternatively, CS50 includes that same file. 01:35:06.550 --> 01:35:08.980 So it's more common in CS50 is to see it like this. 01:35:08.980 --> 01:35:13.360 Now if I clear my terminal window and do make meow and then ./meow and hit 01:35:13.360 --> 01:35:18.970 Enter, well, unfortunately, this isn't the best thing to do infinitely when 01:35:18.970 --> 01:35:21.350 you're in the cloud using a browser. 01:35:21.350 --> 01:35:24.970 This is indeed a browser, just full-screened here. 01:35:24.970 --> 01:35:29.462 This means I'm sending millions of meows over the internet to my computer here. 01:35:29.462 --> 01:35:32.170 So this will happen to you at some point, probably not with meow. 01:35:32.170 --> 01:35:34.150 But you'll lose control over your terminal window. 01:35:34.150 --> 01:35:34.420 Why? 01:35:34.420 --> 01:35:35.170 Because you screwed up. 01:35:35.170 --> 01:35:36.250 And you have an infinite loop. 01:35:36.250 --> 01:35:37.090 You didn't really intend it. 01:35:37.090 --> 01:35:37.690 Or maybe you did. 01:35:37.690 --> 01:35:39.232 You were curious to see what happens. 01:35:39.232 --> 01:35:41.590 What do you do? 01:35:41.590 --> 01:35:43.930 When does the meowing stop? 01:35:43.930 --> 01:35:45.910 What recourse do we have here? 01:35:45.910 --> 01:35:48.550 Well, Control-C will be your friend. 01:35:48.550 --> 01:35:51.070 Sometimes you have to hit it a bunch in a cloud environment. 01:35:51.070 --> 01:35:55.540 But Control-C for cancel will interrupt a program that's running. 01:35:55.540 --> 01:35:58.660 And I promise that almost all of you will at some point 01:35:58.660 --> 01:36:02.560 accidentally introduce an infinite loop because your math is slightly off. 01:36:02.560 --> 01:36:05.680 When in doubt, click in the terminal window and hit Control-C-- 01:36:05.680 --> 01:36:07.060 sometimes multiple times-- 01:36:07.060 --> 01:36:09.545 and that will indeed cancel whatever is happening there. 01:36:09.545 --> 01:36:11.170 In this case, I might have intended it. 01:36:11.170 --> 01:36:14.330 But sometimes it's not, in fact, intended. 01:36:14.330 --> 01:36:18.010 All right, so we've been taking for granted this whole graphical user 01:36:18.010 --> 01:36:22.557 interface for some time and, indeed, the commands that I'm typing 01:36:22.557 --> 01:36:23.890 and the buttons on I'm clicking. 01:36:23.890 --> 01:36:25.848 And let me just give you a better sense of what 01:36:25.848 --> 01:36:29.290 it is we are using underneath the hood this whole time, 01:36:29.290 --> 01:36:31.630 namely an operating system called Linux. 01:36:31.630 --> 01:36:34.270 So I keep alluding verbally, of course, to Macs and PCs 01:36:34.270 --> 01:36:37.690 because almost all of us are running macOS or Windows on our desktops 01:36:37.690 --> 01:36:38.680 or laptops nowadays. 01:36:38.680 --> 01:36:40.930 But there's lots of other operating systems out there, 01:36:40.930 --> 01:36:43.330 and one of the most popular one is called Linux. 01:36:43.330 --> 01:36:47.680 And Linux is very often used on servers nowadays-- companies 01:36:47.680 --> 01:36:51.610 that host email, companies that host websites or apps, more generally. 01:36:51.610 --> 01:36:53.980 Certain computer scientists or computer science students 01:36:53.980 --> 01:36:56.950 often like to brag that they run Linux just because that's a thing. 01:36:56.950 --> 01:37:01.030 But it is really just an alternative to macOS or Windows 01:37:01.030 --> 01:37:04.150 that provides you with both a GUI, if you want it, 01:37:04.150 --> 01:37:07.480 but also an especially a command line environment. 01:37:07.480 --> 01:37:12.040 Now, fun fact-- Windows and macOS do have terminal windows or the equivalent 01:37:12.040 --> 01:37:12.550 thereof. 01:37:12.550 --> 01:37:16.150 And eventually, you might use it on your own Mac or PC to solve some problem. 01:37:16.150 --> 01:37:19.690 But Linux is really known for, along with other operating systems, 01:37:19.690 --> 01:37:23.530 its command line environment, which, again, I distinguished earlier from GUI 01:37:23.530 --> 01:37:26.500 as a Command Line Interface, or CLI. 01:37:26.500 --> 01:37:29.450 And that refers, really, to the terminal window. 01:37:29.450 --> 01:37:33.790 So if I go back to VS Code here, and let me, in fact, go ahead and close my tab 01:37:33.790 --> 01:37:36.160 and focus entirely on the terminal window, 01:37:36.160 --> 01:37:39.640 this terminal window is really just your command line interface 01:37:39.640 --> 01:37:42.390 to your very own server in the cloud. 01:37:42.390 --> 01:37:44.140 The term of art here is you each will have 01:37:44.140 --> 01:37:47.530 your own container in the cloud, which is like your own computer 01:37:47.530 --> 01:37:51.430 running somewhere on the internet with your own username and password 01:37:51.430 --> 01:37:54.530 to which you have access and your own hard drive, if you will, 01:37:54.530 --> 01:37:57.430 your own home folder that has all of your files for the class. 01:37:57.430 --> 01:38:01.390 And it's only accessible to you unless you enable live sharing thereof. 01:38:01.390 --> 01:38:03.880 So when you're typing commands here, it looks 01:38:03.880 --> 01:38:06.400 like you're typing them, of course, on your own Mac or PC. 01:38:06.400 --> 01:38:09.070 But they're actually being sent over the browser 01:38:09.070 --> 01:38:13.570 to some server in the cloud where you are controlling, really, 01:38:13.570 --> 01:38:15.830 your own account therein. 01:38:15.830 --> 01:38:19.390 So it turns out that there are other commands that are worth knowing. 01:38:19.390 --> 01:38:21.292 And we'll give you just a few of these today. 01:38:21.292 --> 01:38:23.500 And over the coming weeks will you have opportunities 01:38:23.500 --> 01:38:24.710 to play with others as well. 01:38:24.710 --> 01:38:26.260 But these are some of the basics. 01:38:26.260 --> 01:38:29.782 And they're all incredibly succinct because, indeed, for things you're 01:38:29.782 --> 01:38:31.990 typing at the command line, humans generally have not 01:38:31.990 --> 01:38:33.640 wanted to type out long commands. 01:38:33.640 --> 01:38:35.890 So a lot of these are abbreviations here. 01:38:35.890 --> 01:38:38.590 Now, perhaps the most common one I'll start with first 01:38:38.590 --> 01:38:44.480 is ls, a lowercase l and a lowercase s that stands for, succinctly, list. 01:38:44.480 --> 01:38:47.380 So if I go to my terminal window now where up until now, 01:38:47.380 --> 01:38:51.370 I've only typed code, which is a VS Code thing for creating an opening files, 01:38:51.370 --> 01:38:56.110 and make, which triggers the compilation of my code, what if I now type ls? 01:38:56.110 --> 01:39:00.070 This will list all of the files in my current folder-- 01:39:00.070 --> 01:39:02.000 my hard drive in the cloud, if you will. 01:39:02.000 --> 01:39:05.780 So if I hit Enter, you'll see a whole bunch of results. 01:39:05.780 --> 01:39:07.240 Now, they're color coded too. 01:39:07.240 --> 01:39:09.910 The white ones here end in .c. 01:39:09.910 --> 01:39:11.980 Those are the source code files I've written 01:39:11.980 --> 01:39:15.790 during class today-- agree.c, compare.c, hello.c, and meow.c. 01:39:15.790 --> 01:39:19.270 And you can perhaps guess, the green ones here that just by convention 01:39:19.270 --> 01:39:24.382 have an asterisk on the end to denote that they're special represent what? 01:39:24.382 --> 01:39:25.340 One of the four others. 01:39:25.340 --> 01:39:26.315 Yeah? 01:39:26.315 --> 01:39:27.800 AUDIENCE: The machine code? 01:39:27.800 --> 01:39:29.520 DAVID J. MALAN: Yeah, the machine code. 01:39:29.520 --> 01:39:33.710 So those are my actual programs that are identically named minus the .c 01:39:33.710 --> 01:39:34.340 extension. 01:39:34.340 --> 01:39:36.830 And the asterisk means that they're executable. 01:39:36.830 --> 01:39:39.582 That is in the world of macOS or Windows, you would double click. 01:39:39.582 --> 01:39:41.540 But in the world of a command line environment, 01:39:41.540 --> 01:39:46.280 that means you do ./ and then the name without the asterisk to execute or run 01:39:46.280 --> 01:39:47.400 the code therein. 01:39:47.400 --> 01:39:51.560 So if I open up my File Explorer-- and I'm hitting Command-B on my computer 01:39:51.560 --> 01:39:54.990 here just as a keyboard shortcut-- you'll see the exact same thing. 01:39:54.990 --> 01:39:59.210 So ls is the command line interface for listing the files in your account. 01:39:59.210 --> 01:40:03.060 But here, because I'm using VS Code or any program like it, 01:40:03.060 --> 01:40:06.213 I also get a graphical user interface as well. 01:40:06.213 --> 01:40:07.880 So it's just two different places to be. 01:40:07.880 --> 01:40:09.680 You're welcome to use whatever you're comfortable with. 01:40:09.680 --> 01:40:12.260 But over time will you naturally get more comfortable 01:40:12.260 --> 01:40:14.720 and capable with the terminal window alone. 01:40:14.720 --> 01:40:16.773 Well, what else is on this list here? 01:40:16.773 --> 01:40:19.190 Well, during the break, I saw that in at least one of you, 01:40:19.190 --> 01:40:23.330 for instance, had created a file called hello instead of hello.c. 01:40:23.330 --> 01:40:27.230 So you were in a situation where you did this accidentally and hit Enter. 01:40:27.230 --> 01:40:30.420 And then you went ahead and typed in all of your code like this. 01:40:30.420 --> 01:40:32.270 And then down in your terminal window, you 01:40:32.270 --> 01:40:34.760 were trying to do make hello, Enter. 01:40:34.760 --> 01:40:38.960 And this now didn't actually do anything. 01:40:38.960 --> 01:40:40.820 I can't-- I'm hitting-- 01:40:40.820 --> 01:40:42.380 I'm trying to run the command. 01:40:42.380 --> 01:40:44.690 I got permission denied, as at least one of you did. 01:40:44.690 --> 01:40:45.433 Now, why is that? 01:40:45.433 --> 01:40:46.850 Well, let's just do a quick check. 01:40:46.850 --> 01:40:50.690 If I do ls, I see now hello, but hello has 01:40:50.690 --> 01:40:53.180 no asterisk next to it, which means it's not executable. 01:40:53.180 --> 01:40:53.930 That's my code. 01:40:53.930 --> 01:40:54.470 Why? 01:40:54.470 --> 01:40:57.540 Well, notice the top of my tab confirms, oh, I screwed up. 01:40:57.540 --> 01:41:00.740 I didn't name my file hello.c, which it just has to be. 01:41:00.740 --> 01:41:01.920 So what do you do? 01:41:01.920 --> 01:41:05.810 Well, you could very hackishly copy this, create a new file, paste it in. 01:41:05.810 --> 01:41:06.770 Or no, no, no. 01:41:06.770 --> 01:41:09.890 We know how to rename things now here because that's one of our options. 01:41:09.890 --> 01:41:11.100 Let me do this. 01:41:11.100 --> 01:41:17.600 Let me do mv for move, hello, and then hello.c, and hit Enter. 01:41:17.600 --> 01:41:20.250 You'll see the tab closes because hello no longer exists. 01:41:20.250 --> 01:41:25.130 But if I now type ls, you'll see, ah, there is hello.c. 01:41:25.130 --> 01:41:28.910 And if I open that file now, whew, there's all of my same code. 01:41:28.910 --> 01:41:31.010 And now if I do make hello-- 01:41:31.010 --> 01:41:37.350 make hello-- now I do get an executable file where in the world is restored. 01:41:37.350 --> 01:41:40.950 So mv, it's just a command not just for renaming, but it also turns out, 01:41:40.950 --> 01:41:43.020 eventually for moving files as well. 01:41:43.020 --> 01:41:45.230 You can also create directories or folders. 01:41:45.230 --> 01:41:48.950 So for instance, if I go into VS Code again, and suppose 01:41:48.950 --> 01:41:52.760 I hover over here and click not on the plus file icon but plus folder, 01:41:52.760 --> 01:41:56.210 I can create a folder called, for instance, pset1 for problem 01:41:56.210 --> 01:41:57.620 set 1 in the class. 01:41:57.620 --> 01:42:00.290 And you'll see now that it's empty because all of my other files 01:42:00.290 --> 01:42:02.840 are in the default folder of my account. 01:42:02.840 --> 01:42:05.460 But I could also go in there like this. 01:42:05.460 --> 01:42:11.060 And I could click on File, and now I can create a new file called mario.c, 01:42:11.060 --> 01:42:13.430 which is one of the first problems, for instance. 01:42:13.430 --> 01:42:18.960 But you'll notice now that mario.c is inside of the pset1 folder. 01:42:18.960 --> 01:42:23.300 So if I zoom out and I type ls at my terminal window, 01:42:23.300 --> 01:42:26.720 I won't see mario.c anywhere. 01:42:26.720 --> 01:42:28.688 But I do see a pset1 folder. 01:42:28.688 --> 01:42:31.730 And it's in light blue followed by a slash, which you don't have to type. 01:42:31.730 --> 01:42:33.300 It just indicates that's a folder. 01:42:33.300 --> 01:42:37.640 Now, I can visually at top left obviously see pwet1 contains mario.c. 01:42:37.640 --> 01:42:40.610 But if I try to do something like make mario here, 01:42:40.610 --> 01:42:42.800 no rule to make target mario. 01:42:42.800 --> 01:42:44.510 It just doesn't seem to exist. 01:42:44.510 --> 01:42:46.650 And that's because you're in the wrong directory. 01:42:46.650 --> 01:42:49.010 So in a command line interface, it's not quite as simple 01:42:49.010 --> 01:42:51.560 as just clicking on a folder, and voila, it opens. 01:42:51.560 --> 01:42:55.250 You have to change into the directory or folder. 01:42:55.250 --> 01:42:57.660 And cd is going to be the command there. 01:42:57.660 --> 01:43:00.600 So if I want to actually change into that directory, 01:43:00.600 --> 01:43:04.070 I can do cd, space, pset1, Enter. 01:43:04.070 --> 01:43:05.960 And now you'll see my prompt changes. 01:43:05.960 --> 01:43:09.200 And this is just a common convention, but it's not the only one out there. 01:43:09.200 --> 01:43:12.470 Now I still have a dollar sign, which indicates where I can type commands. 01:43:12.470 --> 01:43:16.520 But before it, I see a reminder constantly what folder I'm in. 01:43:16.520 --> 01:43:19.550 And we put that there deliberately, like a lot of Linux users 01:43:19.550 --> 01:43:23.620 do just to remind themselves where they are because unlike macOS or Windows, 01:43:23.620 --> 01:43:26.120 where you have a nice, big window telling you where you are, 01:43:26.120 --> 01:43:29.000 at the command line, you need to be reminded textually. 01:43:29.000 --> 01:43:33.350 But now if I type ls and hit Enter, what should I see? 01:43:33.350 --> 01:43:34.340 AUDIENCE: Mario.c 01:43:34.340 --> 01:43:36.170 DAVID J. MALAN: Yeah, mario.c. 01:43:36.170 --> 01:43:38.460 And now if I want to open it-- 01:43:38.460 --> 01:43:42.140 if I want to actually compile it, I can run make mario in this directory 01:43:42.140 --> 01:43:43.940 once I actually type out all of the code. 01:43:43.940 --> 01:43:46.050 Rest assured that in problem sets and labs, 01:43:46.050 --> 01:43:48.800 we'll almost always-- certainly, in the first weeks of the class-- 01:43:48.800 --> 01:43:50.810 give you exactly the commands to type. 01:43:50.810 --> 01:43:52.880 Odds are because it's new to many of you, 01:43:52.880 --> 01:43:55.100 you will accidentally type the wrong commands. 01:43:55.100 --> 01:43:56.000 No big deal. 01:43:56.000 --> 01:43:58.850 Just remember that you have different ways to solve these problems. 01:43:58.850 --> 01:44:00.740 You've got the graphical File Explorer, which 01:44:00.740 --> 01:44:02.198 should feel a little more familiar. 01:44:02.198 --> 01:44:04.940 But in time you'll start to know and, honestly, 01:44:04.940 --> 01:44:08.630 probably prefer commands like these-- so cd for Change Directory, 01:44:08.630 --> 01:44:14.420 cp for copy a file, ls for list, mkdir to make a directory-- 01:44:14.420 --> 01:44:17.630 create a new folder at the command line instead of with the button-- 01:44:17.630 --> 01:44:21.924 mv for move or rename, rm for-- 01:44:21.924 --> 01:44:22.770 AUDIENCE: Remove. 01:44:22.770 --> 01:44:23.728 DAVID J. MALAN: Remove. 01:44:23.728 --> 01:44:24.960 So be careful with that one. 01:44:24.960 --> 01:44:26.520 Rmdir, remove directory. 01:44:26.520 --> 01:44:28.860 And there's dozens, hundreds of other commands. 01:44:28.860 --> 01:44:30.780 You won't need many of them, but we'll start 01:44:30.780 --> 01:44:33.310 to scratch the surface all the more over time. 01:44:33.310 --> 01:44:35.280 But ultimately, this command line interface 01:44:35.280 --> 01:44:38.630 is going to be a more powerful mechanism, a more capable mechanism, 01:44:38.630 --> 01:44:40.380 and ultimately, a more efficient mechanism 01:44:40.380 --> 01:44:43.980 for writing code, running commands, solving problems, analyzing data more 01:44:43.980 --> 01:44:46.050 generally, even though know there's going 01:44:46.050 --> 01:44:49.680 to be some growing pains early on just because it's 01:44:49.680 --> 01:44:51.880 probably so new for many of you. 01:44:51.880 --> 01:44:55.020 So with that said, we have some problems still to solve, 01:44:55.020 --> 01:44:56.475 but we promised cookies today. 01:44:56.475 --> 01:44:58.350 So let's go ahead and take a 10-minute break. 01:44:58.350 --> 01:45:00.150 Cookies are now served in the transept. 01:45:00.150 --> 01:45:02.910 And we'll be back here in 10. 01:45:02.910 --> 01:45:04.740 All right, we are back. 01:45:04.740 --> 01:45:08.400 And up until now, each of the code examples in C we've done 01:45:08.400 --> 01:45:10.740 have been designed to show one specific topic. 01:45:10.740 --> 01:45:14.190 But we thought we'd try to take a step back and solve a more general problem 01:45:14.190 --> 01:45:17.880 and give you a sense of when given a problem set, for instance, or just 01:45:17.880 --> 01:45:20.670 a programming problem more generally, where you even begin 01:45:20.670 --> 01:45:23.280 and how you go about approaching it when it's not obvious 01:45:23.280 --> 01:45:25.260 what the point of the exercise is. 01:45:25.260 --> 01:45:27.330 So one of my favorite games from yesteryear 01:45:27.330 --> 01:45:30.510 is this one here, "Super Mario Brothers" that has come in so many 01:45:30.510 --> 01:45:31.500 different forms since. 01:45:31.500 --> 01:45:35.250 But in this original two-dimensional side scroller game, 01:45:35.250 --> 01:45:37.450 there was a lot of artwork like this. 01:45:37.450 --> 01:45:40.260 So for instance, up here in the sky were four question marks. 01:45:40.260 --> 01:45:44.370 And we'll find that in C and a lot of programming languages initially, 01:45:44.370 --> 01:45:48.030 it's a lot easier, a lot more accessible to focus really on black and white type 01:45:48.030 --> 01:45:49.920 interactive programs textually as opposed 01:45:49.920 --> 01:45:51.900 to full-fledged graphics and the like, but more 01:45:51.900 --> 01:45:55.830 on the more graphical acoustic type of programs before long. 01:45:55.830 --> 01:45:58.500 But for now let me go over and propose that we 01:45:58.500 --> 01:46:00.720 try to just implement in ASCII art-- 01:46:00.720 --> 01:46:03.150 ASCII, again, being the code that maps numbers 01:46:03.150 --> 01:46:08.250 to letters, at least for English, into a textual version of these for question 01:46:08.250 --> 01:46:09.120 marks in the sky. 01:46:09.120 --> 01:46:11.130 So for this, let me go over to VS Code. 01:46:11.130 --> 01:46:13.680 I'll create my own version of mario.c that 01:46:13.680 --> 01:46:16.923 will be different from the one you're challenged with in problem set 1. 01:46:16.923 --> 01:46:18.840 Indeed, in problem set 1, you'll be challenged 01:46:18.840 --> 01:46:22.860 to build a little something like this, albeit with hashtags 01:46:22.860 --> 01:46:24.810 for ASCII art instead of graphics. 01:46:24.810 --> 01:46:28.120 And in mario.c, I want to just solve this simple problem first. 01:46:28.120 --> 01:46:29.710 So it's all involving output. 01:46:29.710 --> 01:46:33.090 So I'll do include stdio.h so I can use printf. 01:46:33.090 --> 01:46:37.043 I'll do my int main(void)-- more on why we keep doing that in future weeks. 01:46:37.043 --> 01:46:39.210 And I'm just going to do something simple initially, 01:46:39.210 --> 01:46:42.210 like 1, 2, 3, 4, backslash n. 01:46:42.210 --> 01:46:46.530 This is about the simplest way I can implement four question 01:46:46.530 --> 01:46:50.410 marks in the sky like these here using pure text like this. 01:46:50.410 --> 01:46:54.180 So let me go ahead and do make mario, ./mario, and voila. 01:46:54.180 --> 01:46:55.830 We have those four question marks. 01:46:55.830 --> 01:46:58.830 But we've seen, of course, that there are better ways to do this. 01:46:58.830 --> 01:47:03.150 And if you wanted to generalize this to be five question marks, six, 01:47:03.150 --> 01:47:06.450 60 different question marks, loop was always the answer 01:47:06.450 --> 01:47:08.100 for not repeating ourselves. 01:47:08.100 --> 01:47:12.570 So maybe I should rewrite this a little bit more flexibly and say something 01:47:12.570 --> 01:47:17.100 like this, for in i get 0, i less than 4, i++. 01:47:17.100 --> 01:47:21.900 And then inside of a for loop, now I can just do a single question mark, 01:47:21.900 --> 01:47:25.800 but I don't think what I've just done is correct. 01:47:25.800 --> 01:47:29.280 Any one spot the aesthetic bug already? 01:47:29.280 --> 01:47:34.200 Yeah, why is this wrong if I want to print the same thing? 01:47:34.200 --> 01:47:34.710 Yeah? 01:47:34.710 --> 01:47:38.275 AUDIENCE: The backslash n, you said to use it into [INAUDIBLE].. 01:47:38.275 --> 01:47:39.150 DAVID J. MALAN: Yeah. 01:47:39.150 --> 01:47:41.800 So I don't think I want a backslash n after every question mark 01:47:41.800 --> 01:47:44.760 because the goal is, again, this row of question marks in the sky. 01:47:44.760 --> 01:47:50.700 So if I now recompile this, make mario, ./mario, OK, it's almost there. 01:47:50.700 --> 01:47:54.820 But now I have that regression to where the dollar sign is not on its own line. 01:47:54.820 --> 01:47:58.265 So I think I need a new line, but I don't think I want it here 01:47:58.265 --> 01:47:59.890 because that was not going to end well. 01:47:59.890 --> 01:48:01.015 Where do I want to instead? 01:48:03.310 --> 01:48:03.960 Any instinct? 01:48:03.960 --> 01:48:05.610 Yeah? 01:48:05.610 --> 01:48:07.380 Yeah, so outside for loop. 01:48:07.380 --> 01:48:11.640 So indeed, I can just go below line 8 and above line 9, creating a new one. 01:48:11.640 --> 01:48:15.273 And now it's totally fine to just print a new line like that. 01:48:15.273 --> 01:48:17.190 You don't have to print anything else with it. 01:48:17.190 --> 01:48:18.970 It's indeed a character unto itself. 01:48:18.970 --> 01:48:21.900 So let's do make mario one last time, ./mario. 01:48:21.900 --> 01:48:24.010 OK, so now we're back in business there. 01:48:24.010 --> 01:48:28.020 Well, what if we wanted to do some other scene from "Mario," such as this one 01:48:28.020 --> 01:48:31.380 here where there's a lot of vertical obstacles like these bricks here? 01:48:31.380 --> 01:48:34.410 If I wanted to print out now a column of three bricks-- 01:48:34.410 --> 01:48:38.160 and I'll use hashtags for these instead of anything graphical-- well, 01:48:38.160 --> 01:48:40.650 I think we're almost there, right? 01:48:40.650 --> 01:48:42.240 I think I can now-- 01:48:42.240 --> 01:48:44.080 it's almost maybe a little easier. 01:48:44.080 --> 01:48:46.342 I can go back here, change the question mark 01:48:46.342 --> 01:48:49.050 to something that looks more like a brick, like this hash symbol. 01:48:49.050 --> 01:48:52.890 And I think now I do want the new line character because when I now do make 01:48:52.890 --> 01:48:56.368 mario, ./mario, OK, there's my wall of four. 01:48:56.368 --> 01:48:56.910 Oh, but wait. 01:48:56.910 --> 01:48:58.050 I didn't want four. 01:48:58.050 --> 01:49:01.150 I wanted to be consistent just with this particular scene here, 01:49:01.150 --> 01:49:02.320 so I just want three. 01:49:02.320 --> 01:49:04.780 So I can still change it in one place. 01:49:04.780 --> 01:49:06.330 And here, again, is that paradigm. 01:49:06.330 --> 01:49:08.970 Even whether you're using 4 or 3, if you get 01:49:08.970 --> 01:49:11.670 into the habit of starting counting from 0, 01:49:11.670 --> 01:49:15.870 you go on up to but not through the value you want to count up to. 01:49:15.870 --> 01:49:20.055 So that's why I'm using less than instead of less than or equal to there. 01:49:20.055 --> 01:49:22.680 So this would be the common paradigm, though you could count it 01:49:22.680 --> 01:49:25.360 like we saw earlier in different ways. 01:49:25.360 --> 01:49:27.965 But what if things escalate one level further? 01:49:27.965 --> 01:49:30.840 And when you're in the underground version of "Super Mario Brothers," 01:49:30.840 --> 01:49:32.840 there's a lot of these underground obstructions, 01:49:32.840 --> 01:49:35.400 including grids of bricks like this. 01:49:35.400 --> 01:49:38.400 And let me conjecture that if you slice this up, it's roughly a 3 01:49:38.400 --> 01:49:43.560 by 3 grid of bricks that all interlock prettily to give us just one 01:49:43.560 --> 01:49:45.400 big, large brick like this. 01:49:45.400 --> 01:49:50.160 So if I want to print out a 3 by 3 grid, now things are getting a little more 01:49:50.160 --> 01:49:54.510 interesting because up until now, I've printed either one row horizontally 01:49:54.510 --> 01:49:56.580 or one column vertically. 01:49:56.580 --> 01:49:58.380 But we haven't really seen any code where 01:49:58.380 --> 01:50:02.670 I'm printing or living in two different dimensions like the game would imply. 01:50:02.670 --> 01:50:05.560 But let me propose that we could do this. 01:50:05.560 --> 01:50:08.640 Let me go ahead and say, all right, suppose I want to print a 3 01:50:08.640 --> 01:50:10.500 by 3 grid of bricks. 01:50:10.500 --> 01:50:16.590 It's really that I want to print, what, three rows of bricks. 01:50:16.590 --> 01:50:18.063 A grid is three rows. 01:50:18.063 --> 01:50:19.980 So if I take the high-level idea and reduce it 01:50:19.980 --> 01:50:22.345 to something a little simpler, how do I do that? 01:50:22.345 --> 01:50:24.720 Well, let me get rid of the printf for a moment as I did. 01:50:24.720 --> 01:50:27.090 And let me just stipulate that this for loop, 01:50:27.090 --> 01:50:29.230 even though it doesn't do anything useful yet, 01:50:29.230 --> 01:50:33.390 will do something how many times just by design? 01:50:33.390 --> 01:50:34.530 All right, three times. 01:50:34.530 --> 01:50:35.850 This for loop is good to go. 01:50:35.850 --> 01:50:39.390 It will do something three times by just using i to do the counting. 01:50:39.390 --> 01:50:44.070 All right, well, if I want to print out now a row of three bricks all 01:50:44.070 --> 01:50:46.710 on the same line, that's pretty similar to what 01:50:46.710 --> 01:50:49.170 we did earlier when I just wanted to print out 01:50:49.170 --> 01:50:51.090 four question marks in the sky. 01:50:51.090 --> 01:50:52.960 So we've seen a solution there. 01:50:52.960 --> 01:50:55.450 And I daresay we can compose one into the other. 01:50:55.450 --> 01:50:58.590 So if I want to print out a row of bricks, 01:50:58.590 --> 01:51:05.310 I could just do this for in i get 0 i less than 3 i++, 01:51:05.310 --> 01:51:08.310 and then inside of this inner loop, if you will, 01:51:08.310 --> 01:51:11.700 let me print out a single brick like this. 01:51:11.700 --> 01:51:16.862 And then I don't like where this is going but, I think I've taken two ideas 01:51:16.862 --> 01:51:17.820 and I've combined them. 01:51:17.820 --> 01:51:23.080 But what might be problematic about lines 5 and 7 at the moment? 01:51:23.080 --> 01:51:24.700 What might be bad here? 01:51:24.700 --> 01:51:25.345 Yeah, in back? 01:51:25.345 --> 01:51:27.665 AUDIENCE: You used the same integer i. 01:51:27.665 --> 01:51:30.040 DAVID J. MALAN: Yeah, I'm using the same integer i, which 01:51:30.040 --> 01:51:32.080 I feel like could get me into trouble. 01:51:32.080 --> 01:51:34.480 If I'm trying to count three things here, 01:51:34.480 --> 01:51:38.470 but then I'm hijacking this variable and using it inside of the loop, 01:51:38.470 --> 01:51:41.560 I feel like I should avoid this collision of names. 01:51:41.560 --> 01:51:43.930 And so what's a good alternative to i? 01:51:43.930 --> 01:51:46.390 Well, a programmer, if nesting loops in this way, 01:51:46.390 --> 01:51:47.980 would pretty commonly go with j. 01:51:47.980 --> 01:51:50.975 You could certainly change this to be rows and columns 01:51:50.975 --> 01:51:52.600 if you want more descriptive variables. 01:51:52.600 --> 01:51:54.940 But i and j is pretty canonical. 01:51:54.940 --> 01:51:59.020 So I'm going to go ahead and do this, j++ instead of i++ everywhere. 01:51:59.020 --> 01:52:00.280 And let me try compiling this. 01:52:00.280 --> 01:52:04.330 So make mario, Enter, ./mario. 01:52:04.330 --> 01:52:06.560 OK, so a couple of things are wrong here. 01:52:06.560 --> 01:52:08.480 This is not a 3 by 3 grid. 01:52:08.480 --> 01:52:12.855 But if you count these things, how many did I indeed print at least? 01:52:12.855 --> 01:52:14.485 You can probably just guess logically. 01:52:14.485 --> 01:52:15.110 AUDIENCE: Nine. 01:52:15.110 --> 01:52:17.110 DAVID J. MALAN: Yeah, there's nine hashes there. 01:52:17.110 --> 01:52:18.940 Unfortunately, they're all on the same line 01:52:18.940 --> 01:52:21.340 instead of on three different lines. 01:52:21.340 --> 01:52:24.910 So where logically can I fix this? 01:52:24.910 --> 01:52:26.535 I'm definitely printing all the bricks. 01:52:26.535 --> 01:52:28.077 They're just not on the right levels. 01:52:28.077 --> 01:52:28.646 Yeah? 01:52:28.646 --> 01:52:31.078 AUDIENCE: If you put a new line at the first loop, 01:52:31.078 --> 01:52:32.620 then you'll get three separate lines. 01:52:32.620 --> 01:52:33.495 DAVID J. MALAN: Yeah. 01:52:33.495 --> 01:52:36.580 So put a new line after the first loop, this inner loop, if you will, 01:52:36.580 --> 01:52:38.000 the nested loop, if you will. 01:52:38.000 --> 01:52:41.030 So let me go ahead and print out just a backslash n here. 01:52:41.030 --> 01:52:42.073 And what's this doing? 01:52:42.073 --> 01:52:43.990 Well, I think that's going to solve it by just 01:52:43.990 --> 01:52:47.270 moving the cursor to the next line after you've done one row. 01:52:47.270 --> 01:52:50.770 So let me go ahead and do make mario, Enter, ./mario, 01:52:50.770 --> 01:52:52.070 and now we're in business. 01:52:52.070 --> 01:52:54.850 So it's a very simplistic version of this same graphic, 01:52:54.850 --> 01:52:57.400 but I'm leveraging two different ideas now-- 01:52:57.400 --> 01:52:59.350 or the same idea twice rather now. 01:52:59.350 --> 01:53:03.970 I'm using one loop to control my cursor going row, by row, by row. 01:53:03.970 --> 01:53:06.100 But then within that loop, I'm doing left to right, 01:53:06.100 --> 01:53:08.290 dot, dot, dot, dot, dot, with printing out 01:53:08.290 --> 01:53:10.960 each of these individual bricks like this. 01:53:10.960 --> 01:53:13.600 Now, there's a little sloppiness here still. 01:53:13.600 --> 01:53:16.630 If I want this to always be a square just because that's 01:53:16.630 --> 01:53:20.800 what it looks like in the game, well, I could change it to be a 4 by 4 01:53:20.800 --> 01:53:24.430 square by doing this or a 5 by 5 grid-- 01:53:24.430 --> 01:53:26.420 whoops-- by doing this. 01:53:26.420 --> 01:53:30.010 Why is this perhaps not the best design to just keep changing the numbers when 01:53:30.010 --> 01:53:33.330 I want to change the size? 01:53:33.330 --> 01:53:34.440 Where could this go awry? 01:53:34.440 --> 01:53:35.010 Yeah? 01:53:35.010 --> 01:53:38.255 AUDIENCE: If it's a square, [INAUDIBLE] 01:53:38.255 --> 01:53:39.130 DAVID J. MALAN: Yeah. 01:53:39.130 --> 01:53:40.630 If it's always going to be a square and height 01:53:40.630 --> 01:53:43.060 is going to be the same as width, I'm just inviting trouble here, right? 01:53:43.060 --> 01:53:44.110 Eventually, I'm going to screw up. 01:53:44.110 --> 01:53:45.680 I'm going to change one but not the other. 01:53:45.680 --> 01:53:48.070 Then it's going to come out to be a rectangle instead of a proper square. 01:53:48.070 --> 01:53:50.410 So I should probably solve this a little differently. 01:53:50.410 --> 01:53:51.160 So let me do that. 01:53:51.160 --> 01:53:54.700 At the top of my main function here, let me go ahead and give myself 01:53:54.700 --> 01:53:59.980 a variable called maybe n for the number of bricks I want horizontally 01:53:59.980 --> 01:54:01.000 and vertically. 01:54:01.000 --> 01:54:03.550 And I'll just initialize that to 3 initially. 01:54:03.550 --> 01:54:06.610 And instead of putting 3 here, I'll literally just use n. 01:54:06.610 --> 01:54:09.100 But I'll do it in both places so that now, henceforth, 01:54:09.100 --> 01:54:13.000 if I ever want to change this and change it to 4, or 5, or anything else, 01:54:13.000 --> 01:54:13.845 I'm all done. 01:54:13.845 --> 01:54:16.720 It's better designed because there's a lower probability of mistakes. 01:54:16.720 --> 01:54:19.840 But I could technically still screw up somehow. 01:54:19.840 --> 01:54:24.460 I could technically accidentally write a line of code like n++, 01:54:24.460 --> 01:54:28.360 or I could just change the value of that variable even though I don't want it 01:54:28.360 --> 01:54:28.985 to ever change. 01:54:28.985 --> 01:54:31.693 And maybe it's because I'm a bad programmer, I copy/pasted wrong, 01:54:31.693 --> 01:54:34.240 I'm working with someone who doesn't know what n represents, 01:54:34.240 --> 01:54:38.440 I can defend myself and my code against human error 01:54:38.440 --> 01:54:41.020 like that by going up here to line 5. 01:54:41.020 --> 01:54:44.170 And instead of just declaring a simple variable like we did in Scratch, 01:54:44.170 --> 01:54:47.360 I can further harden my code, so to speak, 01:54:47.360 --> 01:54:50.740 by declaring it to be a constant using the keyword const. 01:54:50.740 --> 01:54:53.980 Now, this is just a feature of C and some other languages 01:54:53.980 --> 01:54:57.220 to protect you against yourself by proactively saying, 01:54:57.220 --> 01:55:02.320 n is a constant, specifically the number 5 or, previously, the number 3. 01:55:02.320 --> 01:55:05.530 You cannot accidentally write code elsewhere that changes it. 01:55:05.530 --> 01:55:08.420 The computer will throw an error and catch that error. 01:55:08.420 --> 01:55:12.160 So it's just a way of programming a little more defensively. 01:55:12.160 --> 01:55:13.235 Some languages have this. 01:55:13.235 --> 01:55:14.110 Some languages don't. 01:55:14.110 --> 01:55:15.970 But in general, it's a good practice. 01:55:15.970 --> 01:55:18.790 It makes your code better designed because it's just 01:55:18.790 --> 01:55:22.570 as less vulnerable to mistakes by you, colleagues, or anyone else 01:55:22.570 --> 01:55:23.570 using the code. 01:55:23.570 --> 01:55:26.420 So let me change this back to 3 just to be our default. 01:55:26.420 --> 01:55:28.580 But now I'm using n in both places. 01:55:28.580 --> 01:55:33.250 And if I do make mario, ./mario, we're back to where we originally started. 01:55:33.250 --> 01:55:35.560 But the code is a little more better designed. 01:55:35.560 --> 01:55:37.330 And let me note this too. 01:55:37.330 --> 01:55:40.720 All this time, I've been mentioning that correctness is important. 01:55:40.720 --> 01:55:41.740 Design is important. 01:55:41.740 --> 01:55:43.700 There is also this matter of style. 01:55:43.700 --> 01:55:46.107 I've been very deliberately writing pretty code, 01:55:46.107 --> 01:55:48.940 if you will-- not just the syntax highlighting, which, is automatic. 01:55:48.940 --> 01:55:52.060 But notice that I keep indenting everything nicely. 01:55:52.060 --> 01:55:55.450 Any time I have curly braces, like on lines 4 and 14, 01:55:55.450 --> 01:55:57.400 everything is indented one level. 01:55:57.400 --> 01:56:01.420 When I have additional curly braces on lines 7 and 13, 01:56:01.420 --> 01:56:04.520 everything is nicely indented as well. 01:56:04.520 --> 01:56:09.250 Technically speaking, the computer does not care about that kind of whitespace, 01:56:09.250 --> 01:56:10.090 so to speak. 01:56:10.090 --> 01:56:12.280 And you could really make a mess of things 01:56:12.280 --> 01:56:15.205 like this because you have a strange sense of style 01:56:15.205 --> 01:56:17.080 or just because you're being a little sloppy. 01:56:17.080 --> 01:56:20.170 But this code is actually still correct. 01:56:20.170 --> 01:56:23.260 If I recompile it-- let me open up my terminal window-- 01:56:23.260 --> 01:56:28.270 make mario, no errors, ./mario, it works perfectly fine. 01:56:28.270 --> 01:56:30.910 But you can imagine just how annoying this now 01:56:30.910 --> 01:56:34.693 is to read, certainly for a TA, but certainly for you the next day, 01:56:34.693 --> 01:56:36.860 certainly for a colleague who has to read your code. 01:56:36.860 --> 01:56:38.020 This is just bad style. 01:56:38.020 --> 01:56:42.670 It still works, and it's well designed in that you're writing code 01:56:42.670 --> 01:56:44.230 defensively, you're using a constant. 01:56:44.230 --> 01:56:46.420 But, my god, the style is atrocious. 01:56:46.420 --> 01:56:48.310 Now, you'll often find that there's tools 01:56:48.310 --> 01:56:50.440 that can help you format your code for you 01:56:50.440 --> 01:56:53.710 in a manner consistent with a courses or a company's style. 01:56:53.710 --> 01:56:57.220 But this is the kind of muscle memory you'll want to develop over time too. 01:56:57.220 --> 01:57:00.940 Take these VS Code suggestions as it's outputting lines of code for you 01:57:00.940 --> 01:57:03.565 because it's trying to format your code in a readable way. 01:57:03.565 --> 01:57:06.940 And, oh, my god, if and when you do have bugs in your code 01:57:06.940 --> 01:57:08.717 and things aren't even indented properly, 01:57:08.717 --> 01:57:11.800 there's no way you the human are going to be able to wrap your mind around 01:57:11.800 --> 01:57:13.690 what's happening and where. 01:57:13.690 --> 01:57:16.060 You're just making the problem harder for yourself. 01:57:16.060 --> 01:57:21.190 So do get into this habit too of manifesting good style as well. 01:57:21.190 --> 01:57:24.880 All right, well, let me propose that we don't only want a 3 by 3 grid. 01:57:24.880 --> 01:57:26.840 We want this to be a little more dynamic. 01:57:26.840 --> 01:57:32.020 So suppose we moved away from a constant to just using an integer called n. 01:57:32.020 --> 01:57:35.230 And let's ask the user for the size of this grid 01:57:35.230 --> 01:57:38.320 as by prompting them with get_int, as we've done before. 01:57:38.320 --> 01:57:40.150 And I'll store it in n here. 01:57:40.150 --> 01:57:42.880 And then I can go ahead and, more dynamically, 01:57:42.880 --> 01:57:46.450 run make mario to compile it-- whoops. 01:57:46.450 --> 01:57:49.930 Oh, I screwed up accidentally. 01:57:49.930 --> 01:57:53.785 What is it suggesting I do, albeit cryptically? 01:57:53.785 --> 01:57:56.660 AUDIENCE: You have to include the cs50.h. 01:57:56.660 --> 01:57:59.930 DAVID J. MALAN: Yeah, I forgot to include the CS50 header file up top. 01:57:59.930 --> 01:58:03.420 And that's why it doesn't know that get_int is, in fact, valid. 01:58:03.420 --> 01:58:04.880 So that's an easy fix. 01:58:04.880 --> 01:58:07.730 I'm just going to go up here and include cs50.h. 01:58:07.730 --> 01:58:10.790 Now I'm going to clear my terminal and rerun make mario. 01:58:10.790 --> 01:58:12.800 Now we're good-- ./mario. 01:58:12.800 --> 01:58:14.550 And now notice I'm prompted for size. 01:58:14.550 --> 01:58:16.490 So if I type in 3, it's the same as before. 01:58:16.490 --> 01:58:20.900 If I type in 10, it's even bigger, but it happens all now automatically. 01:58:20.900 --> 01:58:23.360 But there are some things that we're not detecting. 01:58:23.360 --> 01:58:25.940 For instance, suppose I type in cat. 01:58:25.940 --> 01:58:28.770 Well, that's handled by the get_int function, as I claimed earlier. 01:58:28.770 --> 01:58:30.687 That's one of the features of using a library. 01:58:30.687 --> 01:58:32.570 You don't have to deal with erroneous input. 01:58:32.570 --> 01:58:36.200 But we only designed a function called get_int to get you an integer. 01:58:36.200 --> 01:58:39.050 We don't know if you want it to be positive, negative, zero, 01:58:39.050 --> 01:58:40.680 or some combination thereof. 01:58:40.680 --> 01:58:43.940 And it's kind of weird to allow the user to type in negative 1 01:58:43.940 --> 01:58:48.440 for the size of the grid or negative 3 for the size of the grid. 01:58:48.440 --> 01:58:51.230 And indeed, your code does nothing, so at least it's not crashing. 01:58:51.230 --> 01:58:52.730 But that's kind of stupid, right? 01:58:52.730 --> 01:58:54.530 It'd be nice to force the user if they want 01:58:54.530 --> 01:58:57.150 a grid to give us a positive value. 01:58:57.150 --> 01:58:58.530 So how could we do this? 01:58:58.530 --> 01:59:03.920 Well, I could go up here and I could say something like if n is less than 1-- 01:59:03.920 --> 01:59:08.190 so if it's 0 or negative, which I don't want, what could I do? 01:59:08.190 --> 01:59:12.380 Well, I could say, well, prompt the user again for the size. 01:59:12.380 --> 01:59:16.613 And now notice, I'm not declaring n again because once it exists, 01:59:16.613 --> 01:59:18.530 you don't have to mention the data type again. 01:59:18.530 --> 01:59:19.790 We said that earlier. 01:59:19.790 --> 01:59:21.510 But this is kind of stupid. 01:59:21.510 --> 01:59:22.010 Why? 01:59:22.010 --> 01:59:25.190 Because now when you've given the user a second chance, OK, now maybe 01:59:25.190 --> 01:59:29.720 I'll do-- all right, if this version of n is less than 1, well, 01:59:29.720 --> 01:59:33.020 let's just go and prompt the user a third time. 01:59:33.020 --> 01:59:35.240 I mean, you can see where this is stupidly going. 01:59:35.240 --> 01:59:38.510 This can't be the right solution to keep typing recursively 01:59:38.510 --> 01:59:39.860 the same thing again and again. 01:59:39.860 --> 01:59:40.790 Where would it stop? 01:59:40.790 --> 01:59:42.873 You'd have to give them a finite number of chances 01:59:42.873 --> 01:59:44.810 or just make a mess of your code. 01:59:44.810 --> 01:59:48.170 So what would be intuitively a better solution here? 01:59:48.170 --> 01:59:49.128 AUDIENCE: A while loop. 01:59:49.128 --> 01:59:50.920 DAVID J. MALAN: Yeah, so some kind of loop. 01:59:50.920 --> 01:59:52.160 We've seen a while loop. 01:59:52.160 --> 01:59:54.240 We've seen a for loop, so maybe one of those. 01:59:54.240 --> 01:59:55.290 So let me try this. 01:59:55.290 --> 01:59:58.760 Let me delete this messiness and just go back to the first question. 01:59:58.760 --> 01:59:59.790 And let me do this. 01:59:59.790 --> 02:00:02.780 So while n is less than 1-- 02:00:02.780 --> 02:00:05.190 so while the number is not what we want-- 02:00:05.190 --> 02:00:09.560 let's just prompt the user in a loop this time for the size again. 02:00:09.560 --> 02:00:15.470 Now, here too, this is better because it's only two requests for information. 02:00:15.470 --> 02:00:19.640 But clearly, lines 6 and 9 are pretty much identical other than the int. 02:00:19.640 --> 02:00:23.120 And if I went in and changed the size, if I 02:00:23.120 --> 02:00:26.300 add this, if I change the wording here, change it to a different language, 02:00:26.300 --> 02:00:27.350 I have to change it in two places. 02:00:27.350 --> 02:00:27.850 That's bad. 02:00:27.850 --> 02:00:29.330 Copy/paste, bad. 02:00:29.330 --> 02:00:31.040 So what might be better? 02:00:31.040 --> 02:00:33.890 Well, it turns out, there's another paradigm in C 02:00:33.890 --> 02:00:37.730 that you can use that gets around this problem, this duplication of code. 02:00:37.730 --> 02:00:41.210 It would be much nicer if I just write the code once. 02:00:41.210 --> 02:00:45.510 And I can do that using a third type of loop called a do while loop. 02:00:45.510 --> 02:00:48.000 So it turns out, in C, you can do this. 02:00:48.000 --> 02:00:50.210 If you want to get the value of a variable like n, 02:00:50.210 --> 02:00:53.370 first just to create the variable without an initial value. 02:00:53.370 --> 02:00:56.870 So int n semicolon means we don't know what value it has, yes. 02:00:56.870 --> 02:00:57.590 But that's OK. 02:00:57.590 --> 02:00:59.840 We're going to add a value to it eventually. 02:00:59.840 --> 02:01:02.870 Then I'm going to say this, do, literally. 02:01:02.870 --> 02:01:04.460 I'm going to open my curly braces. 02:01:04.460 --> 02:01:05.930 And what do I want to do? 02:01:05.930 --> 02:01:09.920 I want to assign to n the return value of get_int, 02:01:09.920 --> 02:01:11.750 prompting the user for size. 02:01:11.750 --> 02:01:14.040 Well, when do you want to do that? 02:01:14.040 --> 02:01:17.900 I want to do that while n is less than 1. 02:01:17.900 --> 02:01:21.410 And this code now achieves the exact same goal, 02:01:21.410 --> 02:01:23.570 but by never repeating myself. 02:01:23.570 --> 02:01:24.230 Why? 02:01:24.230 --> 02:01:29.210 Well, notice on these lines of code now, I'm literally saying on line 6, 02:01:29.210 --> 02:01:31.175 give me a variable called n of type integer. 02:01:31.175 --> 02:01:33.300 It doesn't have a value initially, but that's fine. 02:01:33.300 --> 02:01:34.640 You can do that. 02:01:34.640 --> 02:01:36.380 Line 7 says, do the following. 02:01:36.380 --> 02:01:39.890 What do you want to do? get_int, prompting the user with the word size, 02:01:39.890 --> 02:01:41.660 and just store that value in n. 02:01:41.660 --> 02:01:45.210 But because C code runs top to bottom, left to right, 02:01:45.210 --> 02:01:49.040 now it's reasonable on line 11 to ask that question, OK, is 02:01:49.040 --> 02:01:53.670 the current value of n, which it definitely got on line 8, less than 1? 02:01:53.670 --> 02:01:56.420 And if the user didn't cooperate-- they typed in 0, or negative 1, 02:01:56.420 --> 02:01:58.400 or negative 3-- what's going to happen? 02:01:58.400 --> 02:02:02.510 It's going to go back up here and repeat, repeat, repeat everything 02:02:02.510 --> 02:02:04.530 in the do while loop. 02:02:04.530 --> 02:02:06.438 So a do while loop in C-- 02:02:06.438 --> 02:02:08.480 which is not something some other languages have. 02:02:08.480 --> 02:02:10.730 Python, if you know it, does not have a do while loop. 02:02:10.730 --> 02:02:13.310 This is perhaps the cleanest way to achieve this, 02:02:13.310 --> 02:02:16.790 even though it's a little weird that you have to declare your variable, 02:02:16.790 --> 02:02:20.570 create your variable up top, and then check it down below. 02:02:20.570 --> 02:02:22.980 But otherwise, it's similar to a while loop. 02:02:22.980 --> 02:02:26.150 It just flips the order in which you're asking the question. 02:02:26.150 --> 02:02:28.820 Any questions on this construct? 02:02:28.820 --> 02:02:30.827 And do while, in general, is super useful when 02:02:30.827 --> 02:02:32.660 you want to get input from the user and make 02:02:32.660 --> 02:02:35.640 sure it meets certain requirements. 02:02:35.640 --> 02:02:39.530 So all right, so now that we have this building block after that interlude. 02:02:39.530 --> 02:02:41.750 How can I go about cleaning up this code? 02:02:41.750 --> 02:02:45.230 And then let's conclude by taking a look at things that our code can't do 02:02:45.230 --> 02:02:47.720 or can't do very well or correctly. 02:02:47.720 --> 02:02:50.930 Let me propose that in a final version of Mario, 02:02:50.930 --> 02:02:53.520 let me just add what are called now some comments. 02:02:53.520 --> 02:02:56.880 So it turns out, in code in C, you can define 02:02:56.880 --> 02:02:59.173 what are called comments, which are just notes to self. 02:02:59.173 --> 02:03:00.840 Some of you discovered these in Scratch. 02:03:00.840 --> 02:03:02.590 There's little yellow sticky notes you can 02:03:02.590 --> 02:03:04.680 use to add citations or explanations. 02:03:04.680 --> 02:03:07.020 In C, there's a couple of ways to write comments. 02:03:07.020 --> 02:03:09.960 And in general, comments are notes for yourself, for your TA, 02:03:09.960 --> 02:03:13.860 for your colleague as to what your code is doing and why or how. 02:03:13.860 --> 02:03:15.660 It's a little explanatory note in English 02:03:15.660 --> 02:03:17.860 or whatever your human language might be. 02:03:17.860 --> 02:03:23.220 So for instance, what I might do here in my implementation 02:03:23.220 --> 02:03:27.870 of this version of mario, I might first ask myself a question like-- 02:03:27.870 --> 02:03:30.420 I might first make a note to self like this on a new line, 02:03:30.420 --> 02:03:34.350 above this first block of code, Get size of grid. 02:03:34.350 --> 02:03:38.100 It's just an explanatory remark in any terse English 02:03:38.100 --> 02:03:41.820 that generally explains the next six or so lines, the next chunk 02:03:41.820 --> 02:03:43.560 or block of code, if you will. 02:03:43.560 --> 02:03:46.500 It would be a little excessive to comment every single line. 02:03:46.500 --> 02:03:49.680 At some point, the programmer should know what individual lines of code do. 02:03:49.680 --> 02:03:53.700 But it's nice to be able to glance at this comment on line 6 02:03:53.700 --> 02:03:56.818 that starts with two slashes, and it gets grayed out 02:03:56.818 --> 02:03:58.110 because of syntax highlighting. 02:03:58.110 --> 02:03:59.070 It's not logic. 02:03:59.070 --> 02:04:00.440 It's just a note to self. 02:04:00.440 --> 02:04:02.190 It generally gives me a little cheat sheet 02:04:02.190 --> 02:04:05.160 as to what the following lines of code should be doing and/or why. 02:04:05.160 --> 02:04:07.910 And then down here, well, there's a second block of code 02:04:07.910 --> 02:04:08.910 that's a bunch of lines. 02:04:08.910 --> 02:04:14.130 But together, this just, what, prints grid of bricks. 02:04:14.130 --> 02:04:16.350 And so it's another comment to myself that 02:04:16.350 --> 02:04:18.540 just makes it a little more understandable what 02:04:18.540 --> 02:04:20.880 these 20-some-odd lines of code are doing by adding 02:04:20.880 --> 02:04:23.760 some English explanations thereof. 02:04:23.760 --> 02:04:26.970 But now that I have these, wouldn't it be nice 02:04:26.970 --> 02:04:31.140 if I could abstract these pieces of functionality away, this 02:04:31.140 --> 02:04:33.600 getting of the size and this printing of the grid? 02:04:33.600 --> 02:04:37.590 In other words, suppose that you didn't know where to begin with this problem. 02:04:37.590 --> 02:04:39.960 And the problem at hand were literally implement 02:04:39.960 --> 02:04:43.530 a program that prints a grid of bricks of some variable size-- 02:04:43.530 --> 02:04:46.440 3, or 4, or 5, or whatever the human types in. 02:04:46.440 --> 02:04:48.810 If you have really no idea where to start, 02:04:48.810 --> 02:04:51.540 comments are actually a good way of getting 02:04:51.540 --> 02:04:55.680 started because comments can be an approximation of what we call last week 02:04:55.680 --> 02:04:56.310 pseudocode. 02:04:56.310 --> 02:05:00.360 Pseudocode is terse English that gets your point across, like for the phone 02:05:00.360 --> 02:05:02.080 book searching like last time. 02:05:02.080 --> 02:05:04.050 So if you didn't really know where to begin, 02:05:04.050 --> 02:05:06.910 you could do something like this. 02:05:06.910 --> 02:05:11.730 I could, for instance, just say, Get size of grid as my first step 02:05:11.730 --> 02:05:14.610 and then Print grid of bricks as my second step. 02:05:14.610 --> 02:05:16.410 And that's it for my program thus far. 02:05:16.410 --> 02:05:18.690 This is now implemented in pseudocode. 02:05:18.690 --> 02:05:20.910 I have some massive placeholders there. 02:05:20.910 --> 02:05:22.380 I still have work to be done. 02:05:22.380 --> 02:05:26.050 But at least I have a high-level solution to the problem in comments. 02:05:26.050 --> 02:05:28.230 And now I can even go this far. 02:05:28.230 --> 02:05:32.010 I could say, well, let's suppose that there's just a function already 02:05:32.010 --> 02:05:34.650 that exists called get size. 02:05:34.650 --> 02:05:36.220 I could do something like this. 02:05:36.220 --> 02:05:38.790 I could do int n equals get_size. 02:05:38.790 --> 02:05:41.010 And now I just have to assume for the moment 02:05:41.010 --> 02:05:43.000 that some abstraction called get_size exists. 02:05:43.000 --> 02:05:43.500 It doesn't. 02:05:43.500 --> 02:05:45.420 This does not come with the CS50 library. 02:05:45.420 --> 02:05:47.520 But I could invent it, I bet. 02:05:47.520 --> 02:05:49.110 How else might I proceed? 02:05:49.110 --> 02:05:51.930 Well, let's just assume for the moment that there's also 02:05:51.930 --> 02:05:57.060 a function called print_grid that just prints a grid of that size n. 02:05:57.060 --> 02:05:58.950 So here too is an abstraction. 02:05:58.950 --> 02:06:00.330 These puzzle pieces don't exist. 02:06:00.330 --> 02:06:01.800 These functions don't yet exist. 02:06:01.800 --> 02:06:06.240 But in C, just like in Scratch, I can create my own functions. 02:06:06.240 --> 02:06:07.600 How do I do that? 02:06:07.600 --> 02:06:09.630 Well, let me go down later in the file. 02:06:09.630 --> 02:06:12.810 And by convention, you generally want to leave main at the top of your code. 02:06:12.810 --> 02:06:13.110 Why? 02:06:13.110 --> 02:06:15.235 Because it's the main function, and it's just where 02:06:15.235 --> 02:06:18.090 the human eye is going to look to see what some file of code does. 02:06:18.090 --> 02:06:19.360 And let me do this. 02:06:19.360 --> 02:06:23.910 I want to create a function of my own called get_size whose purpose in life 02:06:23.910 --> 02:06:26.010 is to get the size that the user wants. 02:06:26.010 --> 02:06:28.380 I want this function to return an integer. 02:06:28.380 --> 02:06:30.420 And the syntax for doing that is this, right, 02:06:30.420 --> 02:06:34.920 similar to a variable, the data type that this function returns. 02:06:34.920 --> 02:06:37.450 I don't need this function to take any inputs. 02:06:37.450 --> 02:06:40.500 And so I'm going to use a new keyword that we've actually been using thus 02:06:40.500 --> 02:06:42.292 far-- more on it another time-- just called 02:06:42.292 --> 02:06:45.810 void, which just means this get_size function does not take any inputs. 02:06:45.810 --> 02:06:46.950 It does have an output. 02:06:46.950 --> 02:06:48.138 It outputs an int. 02:06:48.138 --> 02:06:50.430 And this is just the weird order in which you write it. 02:06:50.430 --> 02:06:54.000 You write the output format, the name of the function, and then the inputs, 02:06:54.000 --> 02:06:55.920 if any, inside of parentheses. 02:06:55.920 --> 02:06:57.727 And now I can implement get_size. 02:06:57.727 --> 02:06:59.310 But I've already implemented get_size. 02:06:59.310 --> 02:07:01.140 Or at least now at this point in the story, 02:07:01.140 --> 02:07:03.180 I at least know concretely what to do. 02:07:03.180 --> 02:07:05.730 And I could figure out eventually, with some trial and error 02:07:05.730 --> 02:07:08.040 perhaps, all right, if I declare a variable 02:07:08.040 --> 02:07:12.270 and I do the following n equals get_int, prompting the user for size, 02:07:12.270 --> 02:07:17.910 and I keep doing that while n is less than 1, once that block of code 02:07:17.910 --> 02:07:22.830 is done, here is a new keyword in C where you can return that value n. 02:07:22.830 --> 02:07:27.330 So I keep referring to these values that some functions return as return values. 02:07:27.330 --> 02:07:30.870 In C, there's literally a keyword called return 02:07:30.870 --> 02:07:33.930 that will hand back to any function that uses 02:07:33.930 --> 02:07:36.970 that function the value in question. 02:07:36.970 --> 02:07:41.220 So in a nutshell, between lines 15 and 21 now, 02:07:41.220 --> 02:07:45.270 here is some code identical to our solution earlier that gets a value 02:07:45.270 --> 02:07:47.280 n from the user that is positive. 02:07:47.280 --> 02:07:48.720 It's 1, or 2, or higher. 02:07:48.720 --> 02:07:51.180 It's not 0, or it's not less than 1. 02:07:51.180 --> 02:07:56.360 And as soon as we've got that value, we hand it back as a return value. 02:07:56.360 --> 02:07:58.990 Notice how I'm using this function on line 7. 02:07:58.990 --> 02:08:01.630 Just like with get_int, just like with get_string, 02:08:01.630 --> 02:08:04.650 I'm calling the function-- nothing in the parentheses in this case. 02:08:04.650 --> 02:08:06.400 But then I'm using the assignment operator 02:08:06.400 --> 02:08:09.970 to copy whatever its return value is into my variable n. 02:08:09.970 --> 02:08:13.570 And so now I have a function that didn't use 02:08:13.570 --> 02:08:19.090 to exist called get_size that gets me a positive integer no matter what. 02:08:19.090 --> 02:08:21.710 And now for the grid, how do I do this? 02:08:21.710 --> 02:08:23.860 How do I invent a function called print_grid 02:08:23.860 --> 02:08:27.160 that takes a single argument, a number and prints a grid of that size? 02:08:27.160 --> 02:08:29.180 Well, let's go down here. 02:08:29.180 --> 02:08:32.050 I'm going to write the name of this function print_grid. 02:08:32.050 --> 02:08:33.590 This function just needs to print. 02:08:33.590 --> 02:08:35.440 It has a side effect, as we keep saying. 02:08:35.440 --> 02:08:38.230 So I'm just going to say it has no return value. 02:08:38.230 --> 02:08:39.040 It's just void. 02:08:39.040 --> 02:08:40.820 It doesn't have an output, per se. 02:08:40.820 --> 02:08:42.670 It's just an aesthetic side effect. 02:08:42.670 --> 02:08:44.660 But it does take in an argument. 02:08:44.660 --> 02:08:47.830 An argument is an input, and the syntax for this in C 02:08:47.830 --> 02:08:52.337 is to name the type of the input it takes and the name of the variable. 02:08:52.337 --> 02:08:53.920 And I could call this anything I want. 02:08:53.920 --> 02:08:54.940 I'll call it size. 02:08:54.940 --> 02:08:56.140 I could call it n. 02:08:56.140 --> 02:08:58.840 And it's OK to use the same variable in different functions, 02:08:58.840 --> 02:09:01.030 but I'll call it size just to be distinct. 02:09:01.030 --> 02:09:03.010 And then in this function, I'm just going 02:09:03.010 --> 02:09:07.210 to copy from memory the same code is before. for int i get 0, 02:09:07.210 --> 02:09:09.250 i less than size-- 02:09:09.250 --> 02:09:18.790 instead of 3-- i++, inside of this, for int j gets 0, j is less than size j++, 02:09:18.790 --> 02:09:23.500 and inside of that, print out with printf a single hash, 02:09:23.500 --> 02:09:28.660 print out after that loop a single new line, and that's it. 02:09:28.660 --> 02:09:30.370 Now, I did this fast, admittedly. 02:09:30.370 --> 02:09:32.860 But it's the same code that I wrote earlier. 02:09:32.860 --> 02:09:34.750 But now, just like I did with Scratch, let 02:09:34.750 --> 02:09:36.910 me just arbitrarily hit Enter a bunch of times 02:09:36.910 --> 02:09:39.190 to move the code out of sight, out of mind. 02:09:39.190 --> 02:09:40.900 Now I have abstractions. 02:09:40.900 --> 02:09:44.350 I have puzzle pieces that now exist called get_size and print_grid, 02:09:44.350 --> 02:09:48.160 syntax for which takes some getting used to, but they now just exist. 02:09:48.160 --> 02:09:50.590 Except I do need to do one thing. 02:09:50.590 --> 02:09:56.260 Because C is a little naive, if I try to do make mario now and hit Enter, 02:09:56.260 --> 02:09:59.500 implicit declaration of function get_size is invalid. 02:09:59.500 --> 02:10:03.460 And we've seen that before when I hadn't included a file. 02:10:03.460 --> 02:10:06.362 When I hadn't included CS50 library, get_int didn't work. 02:10:06.362 --> 02:10:09.070 But that's not the issue here because this is not from a library. 02:10:09.070 --> 02:10:10.270 I just invented this. 02:10:10.270 --> 02:10:12.580 C takes you literally. 02:10:12.580 --> 02:10:15.610 And if you define these functions at the bottom of your file, 02:10:15.610 --> 02:10:18.910 they don't exist on line 7 or 10. 02:10:18.910 --> 02:10:20.690 So I could do this. 02:10:20.690 --> 02:10:23.590 I could, all right, fine, well, let me just highlight all of this, 02:10:23.590 --> 02:10:26.342 cut to my clipboard, and paste it up here. 02:10:26.342 --> 02:10:27.550 This would solve the problem. 02:10:27.550 --> 02:10:30.280 I could just move all of those functions at the top of my file. 02:10:30.280 --> 02:10:33.380 That's annoying because now main is at the bottom of the file. 02:10:33.380 --> 02:10:34.930 It's going to take longer to find it. 02:10:34.930 --> 02:10:36.560 That's not a clean solution. 02:10:36.560 --> 02:10:39.170 So let me put it back where it was at the bottom. 02:10:39.170 --> 02:10:40.730 And let me do this. 02:10:40.730 --> 02:10:44.110 This is the only time in CS50 and, really in C programming 02:10:44.110 --> 02:10:46.060 where copy/paste is reasonable. 02:10:46.060 --> 02:10:50.320 If you copy and paste the first line of code from each function 02:10:50.320 --> 02:10:55.000 and then end it with a semicolon, you can tease the compiler 02:10:55.000 --> 02:10:58.270 by giving it just enough of a hint at the top of the file 02:10:58.270 --> 02:11:01.010 that, OK, these functions don't exist till down later. 02:11:01.010 --> 02:11:03.190 But here's a hint that they will exist. 02:11:03.190 --> 02:11:07.660 This is how you can convince the compiler to trust you. 02:11:07.660 --> 02:11:11.830 So those other functions can still be lower in the file, below main. 02:11:11.830 --> 02:11:14.440 But now when I do make mario-- 02:11:14.440 --> 02:11:15.190 oh, damn it. 02:11:15.190 --> 02:11:17.260 Oh, I said print instead of printf. 02:11:17.260 --> 02:11:20.860 That's my bad-- printf. 02:11:20.860 --> 02:11:26.665 So if I do make mario, ./mario, now I can type in 3, 02:11:26.665 --> 02:11:27.790 and we're back in business. 02:11:27.790 --> 02:11:30.190 Now, this was a very heavy-handed way in long way 02:11:30.190 --> 02:11:32.800 to get to a much more complicated solution. 02:11:32.800 --> 02:11:35.240 But this solution, in some sense, is better designed. 02:11:35.240 --> 02:11:35.740 Why? 02:11:35.740 --> 02:11:38.050 Because now, especially without the comments, 02:11:38.050 --> 02:11:40.060 I mean, look how short my code is. 02:11:40.060 --> 02:11:42.430 My main function is literally two lines of code. 02:11:42.430 --> 02:11:42.940 Why? 02:11:42.940 --> 02:11:46.338 Well, I factored out the juicy stuff into its own functions. 02:11:46.338 --> 02:11:48.880 And now, especially if I'm working with colleagues or others, 02:11:48.880 --> 02:11:52.297 you could imagine splitting up large programs into smaller parts, 02:11:52.297 --> 02:11:54.380 having different people implement different parts, 02:11:54.380 --> 02:11:58.750 so long as you all agree in advance on what those inputs and those outputs 02:11:58.750 --> 02:12:00.410 actually are. 02:12:00.410 --> 02:12:04.300 All right, so let's now consider what computers can do well and not so well. 02:12:04.300 --> 02:12:07.360 C indeed supports a whole bunch of operators, mathematically, 02:12:07.360 --> 02:12:10.610 via which we can do addition, and subtraction, multiplication, division, 02:12:10.610 --> 02:12:14.025 and even calculate the remainder when you divide one number by another. 02:12:14.025 --> 02:12:16.900 In fact, why don't we go ahead and use these in a very simple program 02:12:16.900 --> 02:12:19.130 and make our very own calculator? 02:12:19.130 --> 02:12:21.400 So let me go over here to VS Code. 02:12:21.400 --> 02:12:25.030 Let me go ahead and create a new file called calculator.c. 02:12:25.030 --> 02:12:27.550 And in this file, let's go ahead and first include 02:12:27.550 --> 02:12:33.670 a couple of now familiar header files-- cs50.h as well as stdio.h. 02:12:33.670 --> 02:12:37.540 Let's go ahead then and declare main with int main(void). 02:12:37.540 --> 02:12:40.250 And then inside of main, let's do something relatively simple. 02:12:40.250 --> 02:12:42.790 Let's declare an int and call it x, and set 02:12:42.790 --> 02:12:45.670 it equal to whatever the return value is of get int, 02:12:45.670 --> 02:12:48.040 prompting the user for a value for x. 02:12:48.040 --> 02:12:50.240 Let's then give ourselves a second variable. 02:12:50.240 --> 02:12:51.490 We'll call it, say, y. 02:12:51.490 --> 02:12:55.230 Set that equal to the return value of another call to get_int, 02:12:55.230 --> 02:12:57.780 prompting the user this time for that value y. 02:12:57.780 --> 02:13:00.360 And then let's very simply go ahead at the very end 02:13:00.360 --> 02:13:05.080 and just print out, say, the sum of x plus y, a super simple calculator. 02:13:05.080 --> 02:13:08.640 So I'll use printf, quote/unquote, %i for integer, 02:13:08.640 --> 02:13:10.930 backslash n to give me the new line. 02:13:10.930 --> 02:13:14.640 Then I'm going to go ahead and do x plus y to indeed print out the sum. 02:13:14.640 --> 02:13:16.710 Let me go down to my terminal window now. 02:13:16.710 --> 02:13:20.340 Let me do make calculator in order to compile the code. 02:13:20.340 --> 02:13:22.080 No error messages, so that's good. 02:13:22.080 --> 02:13:23.880 Let me do ./calculator. 02:13:23.880 --> 02:13:28.500 And let's do something like 2 plus 2, which, of course, should equal 4. 02:13:28.500 --> 02:13:29.340 And it does. 02:13:29.340 --> 02:13:33.660 But it turns out that sometimes there are going to be limitations 02:13:33.660 --> 02:13:34.677 that we bump up against. 02:13:34.677 --> 02:13:36.510 And let me get a little more ambitious here. 02:13:36.510 --> 02:13:37.890 Let me clear my terminal window. 02:13:37.890 --> 02:13:39.990 And let me go ahead and rerun calculator again. 02:13:39.990 --> 02:13:47.280 And this time, let's, oh, 2 billion for x, and let's type in the same for y. 02:13:47.280 --> 02:13:49.740 And, of course, now the answer of 2 billion plus 2 billion 02:13:49.740 --> 02:13:52.560 should, of course, be 4 billion. 02:13:52.560 --> 02:13:53.970 And yet, it's not. 02:13:53.970 --> 02:13:56.790 So curiously, we see, of all things, a negative number 02:13:56.790 --> 02:14:00.060 here, which suggests that somehow the plus operator doesn't quite 02:14:00.060 --> 02:14:02.070 work as well as we might like. 02:14:02.070 --> 02:14:04.240 Now, why might this actually be? 02:14:04.240 --> 02:14:07.770 Well, it turns out that inside of your computer is, of course, memory, or RAM, 02:14:07.770 --> 02:14:08.850 Random Access Memory. 02:14:08.850 --> 02:14:11.160 And depending on the size of your computer and the type of computer, 02:14:11.160 --> 02:14:13.410 it might very well look a little something like this-- 02:14:13.410 --> 02:14:15.930 a little circuit board with these black little modules on it 02:14:15.930 --> 02:14:19.320 that actually contain all of the bytes of your computer's memory. 02:14:19.320 --> 02:14:22.200 Unfortunately, you and I only have a finite amount 02:14:22.200 --> 02:14:25.080 of this memory inside of our computers, which 02:14:25.080 --> 02:14:27.250 means no matter how high we want to count, 02:14:27.250 --> 02:14:29.670 there's ultimately going to be a limitation on how high we 02:14:29.670 --> 02:14:32.790 can count because we only have a finite amount of memory. 02:14:32.790 --> 02:14:35.800 We don't have an infinite number of zeros and ones to play with. 02:14:35.800 --> 02:14:38.640 We have to actually be bounded ultimately. 02:14:38.640 --> 02:14:40.072 So what's the implication of this? 02:14:40.072 --> 02:14:42.030 Well, it turns out that computers typically use 02:14:42.030 --> 02:14:46.110 as many as 32 bits in zeros or ones to represent something 02:14:46.110 --> 02:14:48.120 like an integer, or in C, in int. 02:14:48.120 --> 02:14:50.010 So for instance, the smallest number we could 02:14:50.010 --> 02:14:53.830 represent using 32 ints, of course, using 32 bits, of course, 02:14:53.830 --> 02:14:55.020 would be zero-- 02:14:55.020 --> 02:14:56.970 32 zeros like this here. 02:14:56.970 --> 02:14:59.100 And the biggest number we could represent 02:14:59.100 --> 02:15:03.180 is by changing all of those zeros to ones, which, in this case, 02:15:03.180 --> 02:15:07.200 will ideally give us a number that equals roughly 4 billion in total. 02:15:07.200 --> 02:15:15.390 It's actually 4,294,967,295 maximally if you set all 32 of those bits to ones 02:15:15.390 --> 02:15:17.160 and then do out the actual math. 02:15:17.160 --> 02:15:20.520 The catch, though, is that we humans and computers in general 02:15:20.520 --> 02:15:24.730 also sometimes want to and need to be able to represent negative numbers. 02:15:24.730 --> 02:15:28.230 So if you want to represent negative numbers as well as positive numbers 02:15:28.230 --> 02:15:30.960 in 0, you can't really just start counting at 0 02:15:30.960 --> 02:15:33.360 and go all the way up to roughly 4 billion. 02:15:33.360 --> 02:15:35.280 You've got to split the difference and maybe 02:15:35.280 --> 02:15:39.390 allocate half of those patterns of zeros and ones two negative numbers 02:15:39.390 --> 02:15:41.890 and the other half roughly to positive numbers. 02:15:41.890 --> 02:15:46.260 So in fact, in practice, when you're using even as many as 32 bits, 02:15:46.260 --> 02:15:49.740 the highest most computers could count, certainly in a program like this in C 02:15:49.740 --> 02:15:52.500 using an int, would be roughly 2 billion. 02:15:52.500 --> 02:15:57.180 That is 2,147,483,647. 02:15:57.180 --> 02:15:59.880 But the flip side of that is that we could also now, 02:15:59.880 --> 02:16:03.420 using different patterns of bits, represent negative numbers as low 02:16:03.420 --> 02:16:06.630 as negative 2 billion, give or take. 02:16:06.630 --> 02:16:09.240 But the implication then, of course, is that if we only 02:16:09.240 --> 02:16:13.530 have a finite number of bits and can only count so high, at some point, 02:16:13.530 --> 02:16:16.360 we're going to run out of bits, so to speak. 02:16:16.360 --> 02:16:20.280 In other words, we encounter what's generally known as integer overflow 02:16:20.280 --> 02:16:23.080 where you want to use more bits than you have available. 02:16:23.080 --> 02:16:26.767 And as a result, you overflow the available space. 02:16:26.767 --> 02:16:28.600 What does this mean, in fact, in real terms? 02:16:28.600 --> 02:16:30.683 Well, let's suppose that you only have three bits, 02:16:30.683 --> 02:16:32.910 but I'm going to gray out a fourth bit just 02:16:32.910 --> 02:16:37.080 to convey where we'd like to put an additional bit ultimately. 02:16:37.080 --> 02:16:40.230 If this of course, is 0, per week 0's discussion, 02:16:40.230 --> 02:16:45.360 this is 1, 2, 3, 4, 5, 6, 7. 02:16:45.360 --> 02:16:50.100 Now, ideally, in binary, if you want to add one more to this value 7, 02:16:50.100 --> 02:16:53.070 you're going to have to carry the 1 mathematically, 02:16:53.070 --> 02:16:56.250 and that would ideally give 1000. 02:16:56.250 --> 02:17:00.420 But if you don't have four bits and your computer is only sophisticated enough 02:17:00.420 --> 02:17:03.270 to have three bits, not even 32, but three, 02:17:03.270 --> 02:17:07.799 the implication is that you're effectively representing not 1000, 02:17:07.799 --> 02:17:10.620 but rather, 000. 02:17:10.620 --> 02:17:13.770 There's just no room to store that fourth bit 02:17:13.770 --> 02:17:17.850 that I've grayed out here, which is to say that your integer might overflow. 02:17:17.850 --> 02:17:21.540 And as soon as you get to 7, the next number once you add 1 02:17:21.540 --> 02:17:24.299 is actually going to be 0, or worse, as we've seen here 02:17:24.299 --> 02:17:27.129 in my code, a negative value instead. 02:17:27.129 --> 02:17:30.209 So what could we do to perhaps address this kind of concern? 02:17:30.209 --> 02:17:32.490 Well, C does not have just integers or ints. 02:17:32.490 --> 02:17:34.559 It also has longs, which, as the name suggests, 02:17:34.559 --> 02:17:38.469 are just longer integers, which means they have more bits available to them. 02:17:38.469 --> 02:17:40.080 So let me go back into my code here. 02:17:40.080 --> 02:17:41.430 I'll clear the terminal window. 02:17:41.430 --> 02:17:43.590 And let me go ahead and change my integers to 02:17:43.590 --> 02:17:47.010 literally long here, long here. 02:17:47.010 --> 02:17:51.600 I'm going to have to change my function in CS50's library 02:17:51.600 --> 02:17:53.228 to be not get_int, but get_long. 02:17:53.228 --> 02:17:55.770 And that's indeed another function we provide in the library. 02:17:55.770 --> 02:17:57.809 Let me change this get_int to get_long as well. 02:17:57.809 --> 02:18:01.480 I'll keep my variable names the same, but I do need to make one other change. 02:18:01.480 --> 02:18:05.190 It turns out that printf also supports other format codes-- 02:18:05.190 --> 02:18:09.629 so not just %i for integers or %s for strings, but also, for instance, 02:18:09.629 --> 02:18:15.780 %li for a long integer, as well as %f for floating-point values with 02:18:15.780 --> 02:18:16.379 decimals. 02:18:16.379 --> 02:18:20.280 So with that said, let's go ahead and change my printf line to be not %i, 02:18:20.280 --> 02:18:21.690 but %li. 02:18:21.690 --> 02:18:26.219 Now let me go ahead and do make calculator again, Enter-- 02:18:26.219 --> 02:18:29.160 no apparent errors now-- ./calculator. 02:18:29.160 --> 02:18:31.740 And 2 plus 2 still equals 4 as before. 02:18:31.740 --> 02:18:36.910 But now if I do calculator again, and let's do 2 billion 02:18:36.910 --> 02:18:41.170 again as well as 2 billion for y, previously, we 02:18:41.170 --> 02:18:44.629 overflowed the size of an integer and got some weird negative number 02:18:44.629 --> 02:18:47.830 because the pattern was misinterpreted, if you will, as a negative number 02:18:47.830 --> 02:18:48.340 instead. 02:18:48.340 --> 02:18:51.340 But a long, instead of using 32 bits, conventionally 02:18:51.340 --> 02:18:55.240 uses 64 bits, which means we have more than enough spare bits 02:18:55.240 --> 02:18:57.850 to go when we add 2 billion plus 2 billion. 02:18:57.850 --> 02:19:01.190 And now, in fact, we get the correct answer of 4 billion, 02:19:01.190 --> 02:19:04.840 which does fit inside of the size of a long. 02:19:04.840 --> 02:19:07.459 Now, a long can count up quite high. 02:19:07.459 --> 02:19:12.340 And, in fact, it can count as high as this, 9 quintillion. 02:19:12.340 --> 02:19:14.889 And so that will give us quite a bit more runway. 02:19:14.889 --> 02:19:17.837 But, of course, it too is ultimately going to be finite. 02:19:17.837 --> 02:19:20.170 So if you have numbers that need to go bigger than that, 02:19:20.170 --> 02:19:22.930 you might still very well have a problem. 02:19:22.930 --> 02:19:25.430 Now, there's another problem that we might run into as well. 02:19:25.430 --> 02:19:28.660 And we can see it in the context of even this simple calculator. 02:19:28.660 --> 02:19:32.520 Computers also suffer from potentially what's called truncation, 02:19:32.520 --> 02:19:35.770 where especially when you're doing math involving floating-point values-- that 02:19:35.770 --> 02:19:40.420 is numbers with decimals-- you might accidentally unknowingly truncate 02:19:40.420 --> 02:19:43.610 the value-- that is lose everything after the decimal point. 02:19:43.610 --> 02:19:45.549 So in fact, let me go back to VS Code here. 02:19:45.549 --> 02:19:46.900 I'll clear my terminal window. 02:19:46.900 --> 02:19:49.630 And let's still use longs, but let's go ahead and use 02:19:49.630 --> 02:19:52.520 division instead of addition here. 02:19:52.520 --> 02:19:55.090 So let me change this plus to a divide operator. 02:19:55.090 --> 02:19:59.020 Let me go ahead and recompile the code down here with make calculator. 02:19:59.020 --> 02:20:02.620 Let me go ahead and run ./calculator, and let me go ahead and do something 02:20:02.620 --> 02:20:06.370 like 1 for x and 3 for y. 02:20:06.370 --> 02:20:07.547 And we'll see that-- 02:20:07.547 --> 02:20:08.380 well, wait a minute. 02:20:08.380 --> 02:20:11.500 1 divided by 3, I learned, should be 1/3. 02:20:11.500 --> 02:20:18.348 But in a floating-point value, that should 0.33333, maybe 02:20:18.348 --> 02:20:20.140 with a little line over it in grade school, 02:20:20.140 --> 02:20:21.890 but, really, an infinite number of threes. 02:20:21.890 --> 02:20:26.140 And yet, we seem to have lost even one of those threes after the decimal point 02:20:26.140 --> 02:20:30.040 because the answer is coming back here as just 0. 02:20:30.040 --> 02:20:31.700 So why might that be? 02:20:31.700 --> 02:20:35.740 Well, if I know that two integers, when divided one by the other, 02:20:35.740 --> 02:20:38.920 is supposed to give me a fraction, a floating-point value 02:20:38.920 --> 02:20:42.640 with a decimal point, I can't continue to use integers or even, 02:20:42.640 --> 02:20:46.370 in this case, longs, which do not have support for decimal points. 02:20:46.370 --> 02:20:51.040 So let me go ahead and change this format code here from %li to %f, 02:20:51.040 --> 02:20:55.090 which is, again, going to represent a floating-point value instead of a long 02:20:55.090 --> 02:20:56.560 integer or even an integer. 02:20:56.560 --> 02:21:03.400 And let me go ahead further and define maybe a third variable, z, as a float 02:21:03.400 --> 02:21:04.100 itself. 02:21:04.100 --> 02:21:07.300 So I'll give myself a variable z equals x divided by y. 02:21:07.300 --> 02:21:10.720 And now rather than print x divided by y, let's just go ahead and print z. 02:21:10.720 --> 02:21:13.060 So now I'm operating in a world of floating-point values 02:21:13.060 --> 02:21:17.230 because I proactively that a long or an int divided 02:21:17.230 --> 02:21:20.260 by another such value, if it's meant to have a fraction, 02:21:20.260 --> 02:21:24.710 needs to be stored in a floating-point value, something with a decimal point. 02:21:24.710 --> 02:21:27.730 Well, let me go down to my terminal window here and rerun make 02:21:27.730 --> 02:21:31.120 of calculator-- seems to work OK-- ./calculator, 02:21:31.120 --> 02:21:34.180 and let's do 1 divided by 3 again. 02:21:34.180 --> 02:21:36.868 And still here, we see all zeros. 02:21:36.868 --> 02:21:39.910 So we do at least see a decimal point, so we've made some progress Thanks 02:21:39.910 --> 02:21:41.350 to the %f and the float. 02:21:41.350 --> 02:21:46.570 But it seems that we've already truncated the value 1 divided by 3. 02:21:46.570 --> 02:21:48.520 So how do we actually get around this issue? 02:21:48.520 --> 02:21:50.050 Well, if you the programmer know that you're 02:21:50.050 --> 02:21:52.467 dealing in a world that's going to give you floating point 02:21:52.467 --> 02:21:54.760 values with decimal points, you might very well 02:21:54.760 --> 02:21:57.340 need to use what's called a feature known 02:21:57.340 --> 02:22:02.050 as typecasting-- that is convert one data type to another by explicitly 02:22:02.050 --> 02:22:04.390 telling the compiler that you want to do so. 02:22:04.390 --> 02:22:05.480 Now, how do I do this? 02:22:05.480 --> 02:22:07.100 Well, let's go back to my code here. 02:22:07.100 --> 02:22:11.260 And if the issue fundamentally is that C is still 02:22:11.260 --> 02:22:14.920 treating x and y as integers-- or technically, 02:22:14.920 --> 02:22:18.310 longs with no decimal point-- and dividing one by the other, 02:22:18.310 --> 02:22:22.330 therefore has no room, so to speak, for any numbers after a decimal point, 02:22:22.330 --> 02:22:24.830 why don't I proactively do this? 02:22:24.830 --> 02:22:28.030 Let me, using a slightly new syntax with parentheses, 02:22:28.030 --> 02:22:33.910 specify that I want to convert x proactively from a long to a float. 02:22:33.910 --> 02:22:39.100 Let me specify proactively that I want to convert y from a long to a float 02:22:39.100 --> 02:22:39.950 as well. 02:22:39.950 --> 02:22:42.910 And now let me go ahead and trust that nz 02:22:42.910 --> 02:22:46.870 should be the result of dividing not a long by a long or an int by an int, 02:22:46.870 --> 02:22:49.330 but rather, a float by a float. 02:22:49.330 --> 02:22:52.630 Let me clear my terminal window, run make calculator again-- 02:22:52.630 --> 02:22:55.300 seems to work OK-- ./calculator. 02:22:55.300 --> 02:23:00.760 And now 1, 3, and hopefully now we actually see 02:23:00.760 --> 02:23:05.380 that my code has outputted 0.333333. 02:23:05.380 --> 02:23:08.380 And I think if we kept showing more numbers after the decimal point, 02:23:08.380 --> 02:23:11.710 we'd theoretically see as many of those threes as we want. 02:23:11.710 --> 02:23:13.900 But there is still one more catch. 02:23:13.900 --> 02:23:16.240 And especially when we're manipulating numbers 02:23:16.240 --> 02:23:19.090 in this way in a computer using a finite amount of memory, 02:23:19.090 --> 02:23:22.180 another challenge we might run up against-- besides integer 02:23:22.180 --> 02:23:27.100 overflow, besides truncation-- is this known as floating-point imprecision. 02:23:27.100 --> 02:23:31.480 Just as we can't represent as big of an integer as we want using int 02:23:31.480 --> 02:23:34.060 or long alone because there is going to be an upper bound, 02:23:34.060 --> 02:23:39.220 there's similarly going to be a bound on just how precise our numbers can be. 02:23:39.220 --> 02:23:41.560 And indeed, let's go back to VS Code here. 02:23:41.560 --> 02:23:43.430 I'll clear my terminal window yet again. 02:23:43.430 --> 02:23:46.900 And this time, let me use some slightly unlikely syntax to specify that I 02:23:46.900 --> 02:23:49.970 don't want to see the default number of numbers after the decimal point, 02:23:49.970 --> 02:23:52.250 which %f gives us automatically. 02:23:52.250 --> 02:23:57.520 Let's go ahead and show me 20 decimal point numbers after the decimal point. 02:23:57.520 --> 02:24:00.700 And the weird syntax for this is to do not %f, 02:24:00.700 --> 02:24:05.950 but %.20 to indicate to see that I want to see 20 digits, 02:24:05.950 --> 02:24:08.440 not the default after, now, the decimal point. 02:24:08.440 --> 02:24:10.390 Let me rerun make calculator. 02:24:10.390 --> 02:24:12.550 Let me do ./calculator again. 02:24:12.550 --> 02:24:14.890 And let's do 1, let's do 3. 02:24:14.890 --> 02:24:17.560 And now this is even weirder, right? 02:24:17.560 --> 02:24:20.590 From grade school, you presumably learned that 1 divided by 3 02:24:20.590 --> 02:24:21.580 is, of course, 1/3. 02:24:21.580 --> 02:24:26.890 But that should be 0.33333, infinitely many times, or, on paper, 02:24:26.890 --> 02:24:28.180 with a little line over it. 02:24:28.180 --> 02:24:31.660 But the computer is doing some weird approximation here. 02:24:31.660 --> 02:24:37.480 It's a whole bunch of 3's and then 4326744079590. 02:24:37.480 --> 02:24:39.380 Well, what's really happening under the hood, 02:24:39.380 --> 02:24:42.100 well, again, is this issue of floating-point imprecision. 02:24:42.100 --> 02:24:45.220 If you only have a finite number of bits and, in turn, 02:24:45.220 --> 02:24:48.100 a finite amount of memory, the computer can really only 02:24:48.100 --> 02:24:52.300 be so precise intuitively. 02:24:52.300 --> 02:24:55.000 Equivalently, the computer is decided on some way 02:24:55.000 --> 02:24:57.190 of representing floating-point values. 02:24:57.190 --> 02:24:59.470 But the catch is, per grade school math, there's 02:24:59.470 --> 02:25:02.800 an infinite number of numbers out there and an infinite number 02:25:02.800 --> 02:25:06.460 of floating-point values because you can keep adding more and more digits if you 02:25:06.460 --> 02:25:07.040 want. 02:25:07.040 --> 02:25:10.120 So the computer, given the way it's implementing these floating point 02:25:10.120 --> 02:25:14.500 values, is essentially giving us the closest approximation that it can. 02:25:14.500 --> 02:25:17.740 Now, how can we go about improving the situation? 02:25:17.740 --> 02:25:19.180 Well, there is one alternative. 02:25:19.180 --> 02:25:21.115 Instead of using float, I can use something 02:25:21.115 --> 02:25:22.990 called a double, which, as the name suggests, 02:25:22.990 --> 02:25:24.760 uses twice as many bits as a float. 02:25:24.760 --> 02:25:27.820 So instead of 32 typically, it will use 64. 02:25:27.820 --> 02:25:30.570 And that's just like the difference between a long and an int, 02:25:30.570 --> 02:25:31.570 which gave us more bits. 02:25:31.570 --> 02:25:34.480 But in this case, this will be used for more precision. 02:25:34.480 --> 02:25:36.850 Let's go ahead and cast x to a double. 02:25:36.850 --> 02:25:38.740 Let's cast y to a double. 02:25:38.740 --> 02:25:41.530 And now let's go ahead and, using the same format code-- 02:25:41.530 --> 02:25:45.220 %.20f is still OK for doubles. 02:25:45.220 --> 02:25:46.990 Let me do make calculator. 02:25:46.990 --> 02:25:48.970 Let me do ./calculator. 02:25:48.970 --> 02:25:51.460 And now let me do 1 divided by 3. 02:25:51.460 --> 02:25:53.770 And we still have some of that imprecision. 02:25:53.770 --> 02:25:56.590 And it's even more of it if we looked at more than just 20 digits. 02:25:56.590 --> 02:25:59.900 But now we have more threes after the decimal point. 02:25:59.900 --> 02:26:03.640 So it's at least more, and more, and more precise, but it's not perfect. 02:26:03.640 --> 02:26:06.520 But it's at least more precise. 02:26:06.520 --> 02:26:08.500 So these kinds of issues, then, are going 02:26:08.500 --> 02:26:10.360 to be necessary to keep in mind any time you 02:26:10.360 --> 02:26:12.640 do something numerically, scientifically, at least 02:26:12.640 --> 02:26:14.980 with a language C where you're going to bump up 02:26:14.980 --> 02:26:18.910 against these real-world limitations of hardware and, in turn, language. 02:26:18.910 --> 02:26:21.952 Now, later in the semester, we'll transition to a language called Python. 02:26:21.952 --> 02:26:24.660 And that's actually going to solve at least one of these problems 02:26:24.660 --> 02:26:26.950 for us by just automatically giving us more bits, 02:26:26.950 --> 02:26:29.470 so to speak, as we need them, at least for integers. 02:26:29.470 --> 02:26:33.140 But even the issue of floating-point imprecision is going to remain. 02:26:33.140 --> 02:26:35.170 Now, just how real-world are these issues? 02:26:35.170 --> 02:26:37.780 Well, back in the year 1999, we got a taste 02:26:37.780 --> 02:26:40.840 of this when the world realized in the years leading up to that date 02:26:40.840 --> 02:26:45.010 that it might not have been the best idea to implement computers 02:26:45.010 --> 02:26:48.910 and software therein by storing gears using just two digits. 02:26:48.910 --> 02:26:53.440 Like, instead of storing 1999 to represent the year 1999, 02:26:53.440 --> 02:26:56.470 a lot of computers, for reasons of space and cost, 02:26:56.470 --> 02:26:59.200 were in the habit of cutting a corner and just using 02:26:59.200 --> 02:27:01.400 two digits to keep track of the year. 02:27:01.400 --> 02:27:06.850 The problem with that is that if systems were not updated by the year 1999 02:27:06.850 --> 02:27:11.560 to support the year 2000, 2001, and so forth, is that, just like before 02:27:11.560 --> 02:27:14.290 with integer overflow, some computers might 02:27:14.290 --> 02:27:16.990 add 1 to the year in their memory, '99. 02:27:16.990 --> 02:27:19.540 It should be the year 2000, but if they're only 02:27:19.540 --> 02:27:22.090 using two digits to represent years, they 02:27:22.090 --> 02:27:25.330 might mistake the year-- as some systems may very well have-- 02:27:25.330 --> 02:27:28.390 for the year 1900 instead, taking literally 02:27:28.390 --> 02:27:30.740 a big step backwards, if you will. 02:27:30.740 --> 02:27:32.622 Now, you'd like to think that kind of issue 02:27:32.622 --> 02:27:34.330 is behind us, especially as we understand 02:27:34.330 --> 02:27:37.240 all the more about the limitations of code and computing. 02:27:37.240 --> 02:27:40.390 But we're actually going to run up against this very same type of issue 02:27:40.390 --> 02:27:42.160 again in just a few years. 02:27:42.160 --> 02:27:48.850 On January 19 in the year 2038, we will have run out of bits in most computers 02:27:48.850 --> 02:27:50.800 right now to keep track of time. 02:27:50.800 --> 02:27:55.330 It turns out, years ago, humans decided to use a 32-bit integer 02:27:55.330 --> 02:27:58.870 to keep track of how many seconds had elapsed over time. 02:27:58.870 --> 02:28:01.090 They chose a somewhat arbitrary date in the past-- 02:28:01.090 --> 02:28:03.350 January 1, 1970-- 02:28:03.350 --> 02:28:06.860 And they just started counting seconds from there on out. 02:28:06.860 --> 02:28:09.100 And so if a computer stores some number of seconds, 02:28:09.100 --> 02:28:11.350 that tells the computer how many seconds have 02:28:11.350 --> 02:28:14.710 passed since that particular date, January 1, 1970. 02:28:14.710 --> 02:28:17.380 Unfortunately, using a 32-bit integer, as we've 02:28:17.380 --> 02:28:20.480 seen, you can only count so high, at which point, 02:28:20.480 --> 02:28:23.470 you overflow the size of that variable. 02:28:23.470 --> 02:28:27.250 And so potentially, if we don't get ahead of this as humans, as a society, 02:28:27.250 --> 02:28:32.080 as computer scientists, on the date January 19, 2038, 02:28:32.080 --> 02:28:36.910 that bit might flip over, thereby overflowing the size of those integers, 02:28:36.910 --> 02:28:42.460 bringing us back computationally to December 13, 1901. 02:28:42.460 --> 02:28:45.970 So this is to say now, with all of this computational ability and code 02:28:45.970 --> 02:28:48.560 comes a responsibility to actually write correct code. 02:28:48.560 --> 02:28:50.560 Next week, we'll peel back some of these layers. 02:28:50.560 --> 02:28:54.550 But for now, this was week 1, and best of luck on problem set 1. 02:28:54.550 --> 02:28:57.850 [APPLAUSE] 02:28:57.850 --> 02:29:01.500 [MUSIC PLAYING]