ROB BOWDEN: This is the more comfortable section, but that doesn't mean that if you feel like you're not more comfortable you won't learn things here. So let's get started. Do you have slides going right into things. Am I about to just take it right now? Switching laptops. ALLISON: You don't want to introduce yourself, Rob? ROB BOWDEN: Oh, I'm Rob. This is my fifth year TF-ing CS50. GABRIEL: I'm Gabriel. I'm head TF of CS50. I was TF last year and this year. ALLISON: And I'm Alison, and this is my second year TF-ing CS50. ROB BOWDEN: All right, so this thing on the left, hopefully you've seen it before. If not because you download it for yourself, you should have seen it in lecture. So this is the CS50 appliance, and he did a somewhat of a description of it in lecture. But basically it's just you are running an operating system within your operating system so that we can give you programs without needing to worry, oh is this going to work on both Windows and Mac, or if some of you are already using Linux, Linux. It's just supposed to be a common playing field so everyone has the same exact environment. So if you haven't downloaded this already, you should download it, because you're going to need it for the problem set. And it is a two gigabyte download, so it might take awhile. On the Harvard it'll go fast. So CS50 appliance. Now in the beginning, we're going to talk about just a bunch of command line stuff, and so by that, I mean working in this little environment over here. And notice all of things I say right here right now are going to work if you're inside of a terminal inside of the appliance, or if you are inside of the gedit terminal window inside of the appliance. So those environments are identical. But I'm going to go a third route. And notice down here this little IP address right here. So you don't have to do this, but this IP address-- now if I-- except it's blocked by this thing. OK, so that IP address over in a terminal here-- so this terminal over here is a terminal in my Mac. So this is in no way currently associated with the appliance at all. And if you're on Windows, then you're going to need to download something specifically for this, in particular people tend use Putty, P-U-T-T-Y. So what I'm going to do is type SSH and then that IP address. Well, jharvard at that IP address. So 192.168.24.220. This scary message, ignore it. Just type yes. This is CS50 in a box. It asks for your password. And so in a lot of these contexts where it asks for the password, [INAUDIBLE]. We've got a lot of questions where it says it's not actually typing. It doesn't show you the characters of the password as you type, if anything, for a security feature, because if someone is looking over your shoulder and they see star star star star, then they know that your password is four characters. So the idea is it will ask you for your password, type. It's not going to show you the characters, but it's actually accepting them. In this case, any time you ever see a password prompt dealing with the appliance, the password is going to be crimson. So crimson. And now here inside of this window that is in my Mac, I am basically having the same exact view as inside of a terminal in the appliance. So you don't have to do this. You can do everything you want inside of the appliance. I almost never actually do anything in the appliance. I almost always minimize that and now I'm working SSH into the appliance. If anything, if you have a slower computer, you might notice a difference. I do this because I prefer this terminal window. It has some features like I can split the window, and now I can SSH in through the appliance. I got two SSH's going on at once. If your computer is particularly slow and you're working in the appliance, and you realize this is really laggy, whatever. Tends to be much faster if you're SSH-ed in. But otherwise you can work either way. AUDIENCE: What does SSH mean? ROB BOWDEN: Secure shells, something like that? What does SSH mean? GABRIEL: Secure shell. ALLISON: It's just secure shell. ROB BOWDEN: Secure shell. It's a protocol that you-- it's a secure protocol, so encrypted. People can't snoop the network and see what you're saying to anything you're SSH-ed to. And in fact, in the olden days of CS50, so in 2009 when I was a freshman, the way that you worked on CS50 problem sets, was you SSH-ed to some server that we gave you access to, and you worked on there. So you didn't have this graphical appliance. You didn't have gedit. You didn't have all these things that you could visually point and click. You had to work in this interface. I prefer to work in this interface. So part of what we're going to be going to over right now are a bunch of the commands that you should start to get familiar with as you go along in the course. And honestly, once you get used to them, it is so much faster to work in this environment than it is to work with finder, dragging and clicking things. So here we are. Now I just SSH-ed in, and so the default location-- you saw some of these commands in class, but we'll go over all of them again. The default location we're in is the home directory. And directory, just another word for folder. So we're in the home directory. Type ls, list the files in this directory. Evidently I created a blah.c earlier. So we have a desktop directory. You notice the syntax highlighting? The light blue highlighting indicates a directory and the straight white indicates just a plain file. So there are going to be some other colors you see. An executable file is probably going to be green or something like that. OK, so we are in the home directory. Now if I want to go into a different directory, cd is the command I want. So change directory, and then you pass the name of the directory that you want to go into. So here we have four options. I can go into downloads, and now we see here it has updated this parenthetical to say I'm in ~/downloads. So what is tilde? It's a shorthand for your home directory. So almost everything you do is going to be with respect to your home directory, and pwd is just a command I use once in a year that just prints the current directory. And so you see here that ~/downloads really resolves to /home/jharvard/downloads. So /home/jharvard is my home directory. So we can cd dot dot. Now dot dot is a special directory that always refers to the one directory up. So if I'm in ~/downloads, then cd dot dot is going to bring me to tilde. What do we think cd dot dot is going to bring me to now? It'll bring me to /home. So tilde by print working directory, I'm in now /home/jharvard. one directory up from that, now it says here /home. Now cd dot dot. Now I'm in the root directory, and you can't do it again. You'll just stay in the root directory forever. The root directory has a whole bunch of things that, if you want to look into, you can. For example, if I go into bin, that contains all these binaries, such as ls, and cd, and all of those things. So these commands need to exist somewhere in the system, and it's in the /bin directory. But almost everything you do is going to be from your home directory. And cd without any arguments whatsoever, you could say cd ~, don't need to. cd is going to bring you back to your home directory. One last one. cd - is going to bring you back to the last directory that you were in. So I just cd'd twice in a row, so my last directory was the home directory. If I go to slash bin, and now let's go up and into user. User share. Let's go to user share. Now I'm now in user share. cd -, back in bin. So this gets particularly useful when you have-- and it'll toggle. So user share, back bin, share bin. So this gets useful. You may find yourself having many, many, many nested directories. And you want to do something real quick in an upper directory. You go to that directory, make changes and stuff like that, and now you want to go back to where you were. cd -. I'm always frustrated when I happen to go to that directory I wanted to do work in. I always get frustrated when I did it in two steps instead of one step, because that means that cd - is going to bring into that intermediate location instead of where I want to go. So we see all the list files. We know how to get around so far. So now let's talk about editing files. So in this course, you're almost always expected to use gedit. If you want, you can take the next step and start learning a command line text editor. So various options exist. And the ones that are probably going to be relevant to you, we have Nano, Vim, and Emacs. So Nano is the beginners command line text editor. So Nano let's go on blah.c I created earlier. It's just this standard C file. And you see a whole bunch of stuff going on at the bottom of the screen, and apparently blah.c contains this C code. So in this particular editor, what it's saying at the bottom-- now this caret symbol, we see this ^G, ^X, ^O. So that in almost all context that you see, you might see that caret symbol in other places online, on Stack Overflow, something like that. It almost always refers to control. So to exit I want to do Control X. Control X, exits. And I can use my arrow keys to move around. Notice I cannot point and click readily. You need use your arrow keys to move around. There might be a setting to point and click. But let's make some changes. Now Control X to go exit. It's going to say save modified buffer. Now the prompt, y for yes, n for no. Control C for cancel. I'll just say yes. File name to write. The default is the file that it already is. Hit Enter. OK. Now I've just edited that file, saved it, and it is changed. So Nano is the easiest text editor get used to. The alternatives are Vim and Emacs. Those are higher level text editors that have a very steep learning curve. So my personal preference is Vim. And it has a wide variety of options. And once you get used to it, you'll never want to go to any other text editor because you just have so many things available to you in these, but it takes a really long time to learn. So maybe you just want to force yourself right now to get used to it, but I would say it's worth it. But it is hard. And then Emacs. I always struggle in Emacs because I know how to do absolutely nothing. Apparently Emacs is not by default installed on the appliance. We will probably add that as a default installations. Once you learn one of Vim or Emacs, there's no compelling reason to ever learn the other, but it's a completely different style. OK so that's editing text files. AUDIENCE: If you were stuck in Vim right now, how do we-- ROB BOWDEN: There are multiple modes in Vim, and there are entire tutorials on learning Vim. So if you happen to be in insert mode in order to type text, which you can enter that in various ways, but i is how you get into insert mode. In or get out of any special mode that you're in, just Escape. And you just bash Escape to get out of any nested modes your in. Just OK, now I'm back in normal mode. And so in normal mode, a colon. You see it appear at the bottom. And then q. So q will quit if you've made changes, which I-- have I made changes? I have made changes apparently. So if you've made changes, it'll say you can put an exclamation mark. I'm going to call it a bang. So you can put a ban to just quit without doing anything, or colon wq will save and quit. So w in general is write. So write the file. I can write and quit. Or you could have just qx slam, q bang just to get out of there regardless of any changes that you've made. All right, so now let's go-- we can create files. Let's start removing files. And I'll just throw in one quick new command, touch. So touch foo. Touch bar. Touch baz. If I ls, now we see that those files exist. They're completely empty. So touch is just an easy way of one, [INAUDIBLE]. Two, technically just to state it, it updates the timestamps. So any file that you create has a timestamp associated with it. So baz was created on September 14 at 16:21. It's now 16:22, so if I touch baz again, we see that baz was most recently modified at 16:22. But otherwise I almost never look at the timestamps on files. So touch, here I'm just using it to create some quick files. All right, so now rm is the command that we care about here. And we can rm boo. Say remove regular empty file boo. And we can type y, and now it's removes. rm baz. Remove regular empty file baz and type n for no. Now it's not removed. So bar and baz still exist. Foo is gone. GABRIEL: Keep talking. ROB BOWDEN: Great. So the annoying message here, remove regular empty-- what are you doing down there? Remove regular empty file. So if we don't want to be bothered by that message, we can throw in this -f flag, and so that's force. And now if I rm -f, it's not going to say do you want to remove this file. It'll just do it. And ls, I don't see bar there anymore. Now that is a potentially dangerous command. It tends not to too bad. We'll come back in a second how it can get really dangerous. And let's create some temp directory. mkdir, another command. So mkdir is a command that makes a directory. And now by ls we see this nice light blue highlighted temp directory. I can cd into temp. And I can mkdir foo. cd into foo. mkdir bar. cd into bar. So we see we can easily get into some pretty deep nesting. Now how do I remove a directory? rmdir. So if I just straight try to rm, like we did with a regular file, rm bar is going to say cannot remove bar. It is a directory. There's a special command for removing directories, kind of. So rmdir bar. Now bar is gone. OK, so rmdir I pretty much never use. The reason being-- now let's make a regular file bar in here. So rmdir boo. rmdir. Failed to remove foo. Directory not empty. So you cannot use remove dir on a directory that has things in it. So you have some options. You can go into that directory, remove everything manually, and then come out and rmdir the directory. That obviously sounds annoying. What if there are thousands of files in there? Well, you could rm *. We'll talk about * in a second. It basically means all the things. But better yet, so rm -r. So rm -r-- in a lot of contexts, -r means recursive, which we'll talk about what recursive means in several weeks. But it basically means traverse the entirety of this directory and remove everything. So rm -r foo is going to say descend into directory foo? Yes. Remove regular empty file foo/bar? Yes. Remove directory foo? Yes. So now foo and everything within it has been removed. Now that can get particularly annoying when-- let's touch 1, touch 2, touch 3. Could have a whole bunch of files. If I wanted, I could create thousands of files in here. And rm -r foo is going to be pretty annoying. Yes, yes, yes, yes, yes, yes. With a lot more files you quickly see how many times I would have to type yes. Well, we just saw before how we can get rid of needing to type yes, -f. So mkdir foo cd foo touch 1 2 3. OK, so rm -rf foo is going to blindly remove foo entirely. No prompt. No anything. Foo is gone. So I tend to use this command all the time. That said, it is a very dangerous command, because if I do something like this, it will not prompt you. It will be gone. And it happens pretty frequently, and even in higher level CS courses. Sometimes we'll see something where someone says I accidentally our rm rf-ed my home directory and all of my P set is gone. And it's devastating, but there's no trash can. There's no there's nothing for you to retrieve. It's just gone. Even worse would be something like rm -rf/. So we just discussed that root directory. It holds all of the files on your system. Things tend to get pretty messy when you remove things like ls, and cd, and all of those. AUDIENCE: What's the difference between rm, rf, and rm* ROB BOWDEN: So rm*-- ALLISON: Question was what's the difference between rm, rf, and rm*. ROB BOWDEN: So rm*. Star in general means all of the contents of this directory. Trying to think of other ways of showing star. Well, star actually generally means match any pattern. So if I have a file called dog1, touch dog2, touch cat1, touch cat2. So ls*1 is going to print cat1 and dog1, because that star can be filled in with-- the one needs to be there, but star can be either cat or dog. It's a wild card. That's the word I'm looking for. Wild card. Or I could ls dog*, and I'm got to see dog1, dog2. So those are listing the files that match that particular pattern. You can use ls in this way. Ls* star matches anything. So it's going to print all of the contents of this directory since all of them match. It's not going to print anything in upper level directories. If I have a sub directory, foo, and touch 1 2 3-- so now if rm* star, remove cat1, cat2, dog1, dog2. Cannot remove foo. It is a directory. So star expands to all the files in the directory. So technically rm* is like saying rm cat1, cat2, dog1, dog2, foo. Whereas rm -rf, technically star would accomplish what we want, but rm -rf-- if I go out of this directory, rm -rf temp, that's going to go into temp and recursively remove everything. So star is separate in that that is understood by-- so this thing that I'm running in, this thing that is prompting me for commands and then executing and doing them, I call this my shell. And so this shell is itself a program. And if I wanted, I could run in /bin/bash. The shell is called bash. And now we notice something has slightly changed, and that's because my settings for the shell are somewhat different. But now I'm technically running a shell within my original shell, and I can exit that shell, and now I'm back to my top level shell. The purpose of saying that is-- the star. So the star is something understood by bash. So rm -rf, -rf flag is understood by just rm. It knows that when you pass a -rf that you want it to recursively remove all files without prompting. The star is something understood by bash that when you say rm*, bash isn't going to say hey rm*, remove star. Bash is going to say rm* remove cat1, cat2, dog1, dog2. It's automatically going to expand all of the files in the directory. And similarly tilde is another symbol that bash understands. When you say cd ~, bash expands that to your home directory. Other questions so far? OK so we're going to start going quick. Tab completion. Just to throw it out there. A lot of people don't realize this exists. So if I type cd dow, I want to go into downloads. I do not need to type nloads. I can just hit Tab. So it recognizes that dow is a prefix that doesn't match anything else in this directory, so it will complete that for you. Now I can enter. I also do that recursively. So mkdir foo. Let's go into foo. mkdir bar. So going back to my home directory, I can see downloads. Now hitting tab again, automatically going to fill in foo. It's the only directory. Hitting tab again, automatically going to fill in bar. So now I'm in (~Downloads/foo/bar). So this tab completion, whenever I got to office hours, and I'm standing over someone's shoulder, and they're going rm D-O-W-N-L-O-A-D-S, I'm dying. Just tab, tab, tab, tab. So definitely used tab. And similarly up and down, a lot of people just that happened to never have hit up and down. It'll go through the previous commands, so if you just ran something, and you want to run it again, just hold up till you get to it. OK. So quick, some other things. Let's go back into temp. Let's create some files. So in here, I'm just going to list some words. dog, cat, meow. Let's do dog, fish. So now rep is a very useful commands that you use to search throughout files for a particular text, and technically you can do really complex expressions for it to match. So here, if I grep, and what do I want to search for? Let's say I'm searching for cats, and I want to search all of these files. So how do I do all of these files? Star. So in file one, I have cat. I probably could have called it something better, because that looks like line numbers or something. But in file one I have a line with cat. In file two I have a line with cat. So now I can look inside file one and see oh yeah, that file did have cat. Notice file three was not matched because cat isn't in there. I can grep for meow. Only file two has meow. So this you can combine, again, with -r, which as I said before frequently means recursive. And so I can come up here, grep -r for any instance of-- let's edit this one just to throw a cat in there. So grep -r for any instance of cat throughout this directory. And it will recursively search any subdirectories. So in baz, there's cat. In temp/2, there's cat. And in temp/1 there's cat. So that's searching within files. Now you can also use a find. And so find is specifically about looking for files with a given name. So let's make some more. Let's go into downloads. Touch dog1. Touch cat2. Touch cat_dog. Touch catcat. So I want to find all files with dog in the name. So find, and for the longest time I never remembered how find worked, until I finally read something that made it so clear. So find, automatically recursive. You don't need to pass a -r. So find dot. We haven't talked about dot yet. Whereas dot dot always means one directory up. Dot always means the current directory. So I could rm -r dot in the same way I can rm -rf *. Ultimately they accomplish the same thing. rm -rf dot is going to remove the entire current directory. OK, which I don't want to do there. But find dot. So recursively search the current directory, and now everything after this are a bunch of flags that you use to exclude things from the return. So find dot returns everything that it can find from the current directory. Those are all the files recursively searching. We'll see some of those in a second. But in case you're wondering how I do that, so Command K, at the very least in my terminal in the Mac clears it. Control L generally clears it for any sort of terminal. You can also type clear. And if you ever get into a weird scenario-- it's happened to me a couple time-- where the colors of your prompts are all messed up, or you aren't able to see anything being typed when you're typing, because sometimes like background color is set the same as the foreground color and now you can't see the fonts. Reset is something that just resets you to the default black background, white front, or whatever you set them to. So where were we? Find dot. So now everything past this point restricts the results to something that matches the given pattern. So here I want to search everything with the name cat. I got nothing. Why is that the case? Well, I'm just searching for something with exactly the name cat. If I want to search something that has some pattern, and cat-- the quotes technically aren't necessary, but I'm throwing them in there. So now it finds catcat because that's the only thing that has some arbitrary pattern followed by cat. I can put cat*, and now find catcat, cat_dog, cat2, because those are all things with cat at the beginning followed by anything. You can combine this. If you want to search for all C files that you have, you might do *.c. We have blah.c here. So that's a find works. You can search. It has a whole bunch of flags for further restrictions. And one on them, let's say -d. So deprecated. Oh, that's not what I want. Not -d. Type d. So find dot - type d. So what that just did is I'm searching for all files in the current directory with a-- d stands for directory-- directory type. This returns all directories in the current directory. And type F is all regular files, all non directories. So that's just an example of other ways you can restrict the search other than just the name of the file. It's been 30 minutes. Still going. ALLISON: I'll breeze through. It'll be fine. ROB BOWDEN: So some other things. Now bang, exclamation mark. So that generally means-- well, let's see an example. So !f, what is that going to do? Well it seems to have repeated find dot -type f. What about !g? That just grep -r cat*. So bang you can use to repeat a recently done command. So if I type !gre, it's going to re-run the commands that began with gre most recently. And you can see all these commands with history. So history. These are all the commands I've run today. And well, it's not literally restricted to today, but I've only used this appliance as of today. It's your entirety of the history of your bash shell, except it cuts off at some point. AUDIENCE: What happens if you do history [INAUDIBLE] command and an error in the result will still print the-- ROB BOWDEN: Yeah, if there is an error in one of these commands-- so let's say, that is an error command not found. Still appears in the history. All right. Other questions on anything? So that's bang. Now, really useful command, man. So that gives you the manual for a given command. So let's say man ls, so this is showing me ls. It lists directory contents. And this is where I see that there are these various flags that exist. So we see that ls -l exists if we were to read that. ls -l gives me this full listing of the directory with who owns the file, the size of the file, the the modified timestamp. So ls -a is another one that you might actually use somewhat frequently. -al is my most common flag this past ls. So -a, notice there's a lot more files than just ls. ls -a. What's in common with all these files? They start with a dot. So this is a convention in Linux that files that begin with a dot are hidden. So it just means that when we just straight ls, or we're searching this directory using the finder equivalent, or the Windows Explorer equivalent, that we don't want to see these dot files. They just pollute the view of things. So they are hidden unless you specifically request them with something like -a. So I can cd into .local, and I see that that is itself a directory with a shared directory, and applications, and blah blah blah. So dot, files they're just hidden. OK, so other important ones. I have a couple I can skip. Let's just real quick talk about the file redirection things. So there's a whole complex series of things you can do with these, but just to see them, let's say, echo. Another command. Really dumb command. All it does is print what I tell it to. So echo hello. It just echoed hello to the screen. Hello world. Echoes hello world. So one command or one symbol that bash understands is this greater than symbol, and that is the output to a file symbol. So if I output this to foo, there's now a file called foo, inside of which is hello world. So notice that when I echo hello world pipe into foo, it didn't echo hello world. Instead it was put into file foo. And another command just to throw it at you, cat. That's an easy way to just completely list the contents of the file so that I don't have to open a text editor to view it. So the contents of the foo file are hello world. And I could cat blah.c, the contents are this. Again, these are commands that, don't expect you have them all memorized. The idea is you've seen them. Maybe you're working on something, and you're like I'm sick of opening this file. I wish I could just look at the contents real quick. You could do that, then look back and say oh I remember something like that exists, and it's cat. So that is going to a file. Now there isn't really any good example of reading from a file yet. What's something that takes something from standard in? Any simple Linux command? When we get to it, in a couple weeks all the piece-- well, this week you have a piece where you start taking input from the user. And so usually you type that input at the keyboard. Instead of typing that input at the keyboard, you can instead pipe in from a file so that when you do Mario, ./mario, pipe in from any given file, and that's going to run the mario program. Not expecting input at the keyboard, instead it's just going to read the lines from the foo file. So greater than foo puts it into the foo file, and less than foo takes stuff from the foo file and uses that as input to this program. And just to see it, we could also echo foo bar baz, and then instead of one greater than, let's do two into foo. What does that do? It just appends to the file. So instead notice if I do echo blah into foo and then cat foo, it's just blah. So when you output to a file, it completely overwrites that file. If you just want to append, double [? grader. ?] And last is pipe. Pipe Gets much more complicated, where it takes the output of one command and feeds it into the next command. So some common thing, history. So, ugh, I don't want to look at this. Show me all commands in my history where I grep-ed for something. No, that's confusing. Show me all commands where I find. All find commands I ever ran. So history. Now history outputs to the screen this list of commands, but I don't want to output it to the screen. Instead I'm going to pipe it into grep. So let's grep for all instances of find. So now instead of grep taking the input, instead of-- grep is able to handle as input-- we're using grep slightly differently here. So instead of typing the list of things we wanted to search for and said grep is taking as input. So if I do just grep find, it waits for me to type things. So cat hello find. Hello. Find. Notice every time I type find it recognizes that I typed find. So instead of this, will search files for find. So history is now going to output a list of all commands. We're putting that output, and we're feeding it to grep, and so it's spitting out all instances of find. The reason I said it'd be confusing is if I-- it's still confusing. If I grep for grep. Notice it's pretty much always showing the command I just ran because that command itself has grep inside of it. OK, so any questions on anything? And I'll transfer it over at this point. Hopefully this is a nice overview of all commands that you don't need to have memorized, but these make up a solid 95% of what I do at the command line. Also keep in mind that the command line itself, bash is a programming language, and so when you get down to it, you might want to do really complex things. And so it has things like loops, and ifs, and all of those that you're going to get used to with your programming languages. But that is beyond the scope of this section. OK, so no questions? ALLISON: None? GABRIEL: Are you going to-- ALLISON: I can do it on mine if you want. We can see what happens. ROB BOWDEN: Off to Allison. ALLISON: Woo. You're a hard act to follow, Rob. Do you want me to switch with you? Or you got, OK. I'm going to try and not quite be as lengthy there. Let's see if this will work the way I want it to. Maybe? Haha! Yes. So I'm just going to very quickly go through variables, loops, conditionals, and a little bit on the compiler. If you have questions at any time, please stop me. These guys will remind me to repeat your question in case I forget, but shouldn't be too bad. So variables, yeah. We have no one of your Scratch pieces here. I'm sure most of you, if you had some sort of game that you created with Scratch, you had to keep track of something like score, or time, or something like that. So those bright orange pieces that we see there are just the Scratch form of variables, and you will definitely be using variables throughout your programs. If you're not, I'm not really sure what you're doing. But anyway, big thing, defining variables. With C every variable has to have a type declared, so I gave you a very general one at the top. So you'll have your type and then whatever you decide to call your variable. So in this case, type in your variable list. We have three examples. Char of some grade, of an A, which is what I'm sure you all want to get in this class. You can define multiple variables on one line as long as they're all the same type, which is our second example there where you have three variables, x, y, and z. They're all floats. And then you can also, in this last example with int score and number of teams, you can initialize them right there. So in the middle example where we just have float of x, y, and z, those are not initialized yet. They have no value. Or they have garbage values. And if you try and use them, the compiler will yell at you. You have to both declare and initialize your variables. So in this last one, we're doing both. We are declaring variables of score and number of teams, and we are initializing them, giving them their initial values of 7 and 4 respectively. Cool. Everyone good? Awesome. OK, so some conventions. If you guys have read through style 50, these are just things that we'd like for you to implement in your style. So meaningful names. If you start calling things just x, y, and z, especially as you get into lengthier programs, you're probably going to confuse yourself and be like what is this variable referring to. I have no idea what this means. So if it's meant to hold a score, call it score. If it's meant to hold some answer or result, give it a name like that. For loops, which we will get into in the next slide, single letter variables are fine. ROB BOWDEN: I, j, and k are just conventions for for loops that everyone expects them to be called i, j, and k. You can call them-- I see row column or row call sometimes for two nested loops, and that's also kind of standard. But i and j is completely understood. ALLISON: Yeah, i and j you're totally fine. For sake of clarity like in some of your P sets, it might make sense to have more descriptive things in there just to keep track of it. But I think i, j, and k I think the vast majority of us all use. ROB BOWDEN: With these conventions, so style is important. It's one of the four axes on which you're graded, and it is so easy to just go over your P set at the end and make sure that there aren't stylistic mistakes. So make sure you're tabbing correctly. Make sure your variables are named. Leave some comments. It is very easy to get those points. You don't have to think about anything in order to get those points. You don't have to figure anything out. It's just making it look pretty. ALLISON: In fact, we have style 50, which will tell you where you're messing up if you're messing up on style and will tell you exactly what you need to fix and how you need to fix it. It's also just good to mention that it's course policy that if you're at office hours and your code is a mess, we can decline to help you until it looks nicer. So start out right, keep consistent style, you're also just going to make your lives a whole lot easier when you're trying to go through debug. If you're trying to figure out where you're missing a curly brace and they are all over the place, you're just making your own life harder. So be consistent with style. I promise it'll make your life easier. It'll make our lives easier. Everyone will be much happier. And that's what you want. GABRIEL: Your grade will be higher. ALLISON: Yes, and your grade. If your TF's like you, tends to be favorable. All right, and then just the second point here. Consistent initializations. So as we saw, you can declare and initialize things. Multiple variables on the same line. One thing we would like you not to do is to declare some variables and not initialize them on the same line that you are initializing others. So in case that made no sense whatsoever, we have the example here where we're declaring ints in variables of quarters dimes and pennies, but quarters and pennies have no initial value. We haven't initialized them, but right in the middle there we already initialized dimes to 0. So either do quarters, dimes, pennies. Or do quarters equal 0. Dimes equal 0. Pennies equal 0, or whatever those initial values are. Big thing with style, be consistent. When in doubt, be consistent. But follow our style guide too. Cool. Everyone good there? AUDIENCE: Where's the style guide? ALLISON: The style guide is on-- what's the website? GABRIEL: I think it's manual.cs50.net/-- ALLISON: Style? GABRIEL: Style. Yep. ALLISON: Yes. So question, where is style 50. manual.cs50.net/style. Yes? AUDIENCE: If we're defining variables, is it OK if we put like [INAUDIBLE] like int score and then int goal. So would you say that now we've got to define them together? ALLISON: So question, should you have redundant code when you are defining variables such as int score and on the next line int game? ROB BOWDEN: There are definitely cases where redundant code is bad. I would not consider that redundant code. I almost never declare multiple variables on the same line ever. And if anything, it's because usually I leave some sort of comment explaining what the variable is for. So I'll say int score slash slash. Keeps track of whatever. In total slash slash. So it's much grosser in that way to put them all on the same line. I just never put them on the same line. ALLISON: I feel like it's personal preference at this point. AUDIENCE: Does that go for for loops and stuff too? ROB BOWDEN: Like inside? Like int i equals 0 comma length equals something? That you don't have a choice. With for loops the initialization part-- so you might have only seen int i equals 0 semicolon i less than whatever semicolon i plus plus. That int i equals 0, technically you can also do what we saw before with the comma syntax. int i equals 0 comma j equals 3 comma k equals 5. You don't have a choice to split that up into multiple lines, and that's standard. Seeing it there is fine. ALLISON: Awesome. Well, convenient segue into loops. So yeah, here we have some examples of loops that you guys saw in Scratch. And of course all of these can just be recreated in C. And they basically allow you to repeat some section of code until a certain condition is met, which we'll get into right after talking about loops with conditionals. So we have three main types. For, while, and do while, which we will all go through right now. So first one is for loops. So for some condition, execute this block of code. We have this cool little diagram here at the bottom. But basically you have in your for, that first line, you're going to initialize your variables. So as we talked about, i is equal to 0 or i is equal to 10. Whatever you need that variable to be it's going to be initialized there, declared and initialized to some value. So then we have some condition that's going to be checking our variable against something. So in the case the typical case where maybe you want this section of code to execute five times. So we'd have int i equals 0, and we want it to be when i is less than 5. So that condition is just going to check that every time. If that condition evaluates to true, it's going to run the code, which is exactly what this little diagram is showing. And so it executes it. It updates a variable, which is what we see in the last part of our for loop initialization there. So it'll just keep doing this until that condition is not met, and then it will exit the loop and continue moving on with the rest of your program. Everyone good there? Cool. So here's an example, very similar to something I just talked about. So we just want to print this is CS50 10 times. So you see here we have our for, and then we initialize the variable i to be equal to 0. Our condition is checking that it's less than 10. So evaluate to true when we first start, and then updates our variable each time that it actually executes and prints out this is CS50. And will terminate after 10 times. Cool. So while loops are up next. And as you see here, we just have some while this condition-- question? AUDIENCE: How can I jump actually just not one number, but two numbers [INAUDIBLE] i plus plus plus? ALLISON: So the question was how can you update your variable by more than one at a time. So i plus plus will update by one each time. If you wanted to update it by two, you could do i plus equals 2. ROB BOWDEN: Have you seen plus equals in lecture yet? AUDIENCE: [INAUDIBLE]. ALLISON: It's effectively the same thing as i equals i plus 2. So it's going to take it and update it by two each time. Plus equals is just something we call syntactic sugar. ROB BOWDEN: Yeah, those exist for pretty much all arithmetic operators. So i times equal to would double the number. j divide equals 3 is the same as j equals j divided by 3. ALLISON: Or minus equals 2 would decrement i by two each time. ROB BOWDEN: Even mod equals. You haven't seen bitwise operators, but caret equals and ampersand equals, all of those exist. ALLISON: So a lot of times, especially with your first couple of P sets, you'll be probably incrementing by one, so i plus plus, j plus plus are all things you're going to typically be using. But that update condition is fully within your control. You can update it by whatever increments or in whatever way you decide to. Maybe you even want it to be a random number sometimes. But yes, there are lots of things you can do with that. You're not restricted to i plus plus. ROB BOWDEN: Just so you know it exists, it also exists in another form, plus plus i. So if you're ever searching online and happen to see plus plus i, pretty much means the same thing. ALLISON: Cool. Good? Awesome. So while loops. Very similar. You have some condition. The main thing to notice here is instead of having three different parts to set up, we have one. We just have some condition that's being checked. And in the same way, as long as that condition evaluates to true, your code is going to run. And if it's false, it will terminate, move onto the next part of your program. So this is kind of like-- what's a good example of checking for some normal condition? GABRIEL: While true. ALLISON: You could do while true. Well, 1 is equal to 1. ROB BOWDEN: You can do while-- just instead of using a for loop, you can always code a for loop in a while loop, so i greater than 0 or while i less than 10. ALLISON: Awesome. And then we have do while loops, which is great for user validation, where you want to get something from your user, see if it's valid, and then continue from there. So one of the things to know is with a do while is that it's going to execute, and then it will re-execute if this condition is met. So probably the best way to do this is just to see an example here. So as I just mentioned, user validation is really useful-- or do whiles are really useful with user validation. So this is just going to re-prompt some user until they enter a positive number, which might be useful for your P set this week. And so in this case, when we initially run this program, it's going to print enter a positive number. It's going to get some input from the user, and then it's going to check that input against the condition that you've set for it. So in this case it's going to check. It's going to say, OK, is our input negative, or is it 0 or negative, which would be invalid. So then it would re-prompt. Question? AUDIENCE: Is this the same then as a while loop if you just copied that code and put it [INAUDIBLE] while loop? ALLISON: So question was would this be the same as just a while loop if we were to just copy the while loop above. So in this case, your while loop is going to check the condition first. So in this case, if we tried to write as just a while loop, it would say while input is less than one. But we don't have an input for it. AUDIENCE: If you [INAUDIBLE] while loop including this code, but then you coped the code above the while loop also. You just had this code [INAUDIBLE] while loop. ALLISON: It would be the same thing, yes. So you could just write-- instead of having a do-- yes. GABRIEL: But that's more elegant. ALLISON: Yeah, that's more elegant. You can get into design and whatnot, but yes, you can totally do that. Any other questions? OK, cool. So we've talked a lot about conditions with all these loops that we have, so we're actually getting into conditions in Boolean expressions. Again, you use these in C, so just kind of transitioning from more graphic interface to actually coding. Cool, so big one, if. Basically just allows us to introduce some logic into our program and check sys conditions. So in this case, OK, is n greater than 0? Yes it is, so you can execute this. It's just checking some condition that you've set, which I think we're all comfortable with checking conditions. Cool. So if else is your other one, you can say OK, if this is true, do this first thing. Otherwise I want you to default and do something else. Like in this case, you either pick a positive number or a negative number. You only have two options. You need it to execute regardless of what your user inputs. So you can say well, is it greater than 0? Cool. Print a positive number. If it's not, print a negative. Everyone good? And then one thing to recognize is that if the if condition is met, the else will never also execute. Only one of these will execute at a time. So it's a trade off. You don't get to have both. You either have the first condition. You either have the if or the else, not both. Which then can make things even more complicated, because you can do if, else it, and then else. So in this case, we have three conditions. And again, only one of these is going to end up being executed. So you might be wondering well, what if you have something that can meet two of these. Maybe whatever you're inputting meets both the condition for if and the else if. Only thing that's going to run ALLISON: As soon as it finds something that it meets the condition for that evaluates to true, that's what it's going to run and nothing else. So if you had is this number between 0 and 5 for your first one, or is this number between 3 and 5 for the else if part, and you input the number-- I said 0 and 5 and-- 4. It's going to hit the first one. It's going to say OK, this number is between 0 and 5. Execute and leave. It will never hit that second option. Cool? Awesome. OK we also have switch statements if you want to get even more-- or sorry, switch is next. I'm getting ahead of myself here. Again, multiple if blocks where as I just said is as soon as you find a condition that's met and an if else if else, it leaves. If you need to check multiple things, you're going to want to use this because it will check every time here. So this will run through and if it's greater than or equal to 90, it's going to print that. And it will run through and check every single one of these. AUDIENCE: So this would be more buggy than [INAUDIBLE]. Would this be like [INAUDIBLE]? ALLISON: The question is would this be buggy or does this do what you want. It really depends on what you want from your program. AUDIENCE: I mean like if you put 90 in. ALLISON: If you put 90-- AUDIENCE: [INAUDIBLE]. GABRIEL: You're going to get two things. ALLISON: You're going to get two things. Yes, two. ROB BOWDEN: Two? ALLISON: No. ROB BOWDEN: Four. If you put 90, it's going to say you got an A, you got a B, you got a C, you got a D. AUDIENCE: [INAUDIBLE]. ALLISON: Right. So I depends on what you want from you program. Sometimes you need to check multiple things. You'll get much deeper into what good design is as you go forward. The important thing to realize is that this will check all four conditions here. Whereas if this were an if else if else if else, it would hit that first case, it would print you got an A and be done. ROB BOWDEN: Even if we decided to change this to if and greater than or equal to 90, if and greater than or equal to 80, and less than or equal to 89, if n greater than or equal to 70, and n less than or equal to 79, so that will be correct. That will do what we want, but it still checks every single it. So whereas in the first scenario, if we enter 90 with just if else if else if, and we enter 90, then it's going to correct. It will check the first one, print you got an A, skip everything, because it already found one that works. All cases are mutually exclusive based on if else if else if. So it'll execute the first if, then it's done. It'll go to the end. Whereas if we change this to be what I was saying with less than or equal to 89. It's going to check the first one. It'll print. It'll check the second one. It's not going to print. Check the third one. Not going to print. Check the fourth one. Now going to print. So in that case, the else if version, since these cases are mutually exclusive, it's better use if else if else if, because that is going to have fewer checks of the conditions than this version. ALLISON: Awesome. So another thing we can do is switch statements. Basically a switch statement takes in some variable, in this case it's n, and determines which case to execute. So this is also one where your cases should be kind of mutually exclusive. So in this case, if we we get a one, it's going to match whatever that variable-- whatever the value of n is to one of these cases, so 1, 2, or 3, and print out the corresponding line. And then if you notice here, we also have a default, which you can of think of as your else. So if you pick any other number besides 1, 2, and 3 in this case it's just going to print invalid. Deciding when to use ifs versus if elses versus switches is going to be something that you guys will see design wise as you start writing more complicated programs, and there's no hard and fast rules of when to use them. It really depends on your context. ROB BOWDEN: And just to throw it out there since it is more comfortable section. Switches, they tend to be-- so you're limited in the number of ways you can use them, because ifs, the condition can be pretty much anything you want. With switches the cases have to be numbers, or technically they can be chars, but chars, as we'll see, are just numbers. So they have to be numbers, but switches are really more efficient than if else if else if, because even taking the example before-- well, the grade example seems good. Well let's say here, we instead do this as an if else if else if scenario. So if n equals equals 1, print you picked a low number. If else if n equals equals 2, you picked a medium number. Else if equals equals 3, high. Else invalid. So let's say that was our scenario. So let's say we enter 4, so we expect invalid. The way that if else if else if approach is going to work is checks the first condition. It's not satisfied. So we check the second condition. It's not satisfied. Check the third condition. Not satisfied. So we go to the else and print invalid. The way the switch works is it compiles down into what we're going to call a jump table. The main idea being that when you enter 4, it can immediately go to the default. It doesn't need to check am I case 1? Nope that's not it. Case 2? Nope. Case 3? Nope. Default. OK, this must be where I want, and then execute that. No, it immediately jumps to the default. Or it I enter 2, it's immediately going to go to the 2 without needing to go through case 1. So in that way, realistically nowadays that's not that much of an efficiency gain. Usually computers are pretty fast, and that's not that great. But it is the case that switches are faster. If you're really trying to optimize, use a switch. ALLISON: Cool. And then we have ternary operator. So I know I mentioned earlier the word syntactic sugar. So it's just things that make your code much more concise. So this is one of those cases. So ternary operator is question mark colon as we see in the line string s equals n greater than 100 question mark high colon low. So basically how this works is it's the n greater than 100 is a condition. So I think it can make sense. It's like asking a question. It's saying oh, is n greater than 100. Who knows? And if it evaluates to true, it's going to give you the first thing that's listed there, which is high. Otherwise it's going to give you low. So this is just a really simple and efficient way to do like an if else. That's all this is. And if we were to write this as an if else conditional, it would be if n is greater than 100, return high. Else, return low. This is just a much more concise way of writing it. ROB BOWDEN: So this particular example is whenever you're doing something like this, this is the pattern where I use ternary very frequently. So we haven't talked about scope yet, but I hate seeing string s semicolon. If n greater than 100, s equals high. Else, s equals low. So that pattern, those five lines of code literally 100% of the time can be transferred into what was up there with a ternary. So the ternary, one line of code. The if else, five. That's an example I point out every single time. This would great place for a ternary operator. It's so clean. But people tend to never use it. ALLISON: Take it away Gabe. GABRIEL: So now you guys all learned in lecture this week that everything in a computer is binary, right? Just like the lamps here. You can be either turned on and off. And by everything, I mean literally everything. Some numbers, and chars, and strings, and even the code that you write when it gets compiled to machine code and stuff like that, so it all boils down to 0's and 1'. And so when we're dealing with integers, which is something that's technically very simple, we should be able to do stuff like adding them, which is probably one of the simplest things you can do to two integers, right? So addition and subtraction works just like it works in decimal notation, except here it's binary, right? So it's in base two. So add 1 plus 1. That gives 0, and 1 carries over. And just keep doing that, So now comes the more interesting question. We know how to represent all positive integers in the computer, but let's make this an exercise. Pretend you guys are all in 1960 or something trying to create a computer, and you have to come up of a way of storing minus 1, for example, or minus any integer for that matter. How would you do that? Any ideas? Just throw anything at me. Yes? AUDIENCE: [INAUDIBLE] designate a special if your [INAUDIBLE]. GABRIEL: You can designate a special bit, which will be 0 or 1. Let's say one if it's positive and 0 if it's negative. And then the rest of the bit is just to store the number. Cool. So that's a very good idea. We have, I don't know, 200. And if the first bit is turned on, then it's plus 200. If it's turned off, it is minus 200. Cool. There is only one small problem with this, which is if we try to sum things up. So imagine we have 11111 here, and we're summing this with 00100 whatever. If those two are positive, that's fine. But then if one of them is negative, like let's say that this bit here is the one that's responsible for-- I'm going to make a separate-- so this one means that this number here is positive. This one means that this number here is negative, right? But then when you're going to sum them, you need an if statement saying oh if this is 0, then my sum will be something different, right? So there's a slightly more clever way to do that, which is called two's complement. So basically what we do is we define minus 1 to be the thing that if we add up to 1 gives us 0. Let me repeat that. So let's say that this here is 1. What is the thing that naturally in positive integers added to that gives us 0? What if we try to add it to this number? We're going to have-- OK, so let's add. We're going to have 1 plus 1 is 0, and then it carries over. And then we're going to get 0 again. I'm getting confused. And you're going to get 0 and 0 and 0 and 0 and 0 and 0. Lots of 0's. At the very last one, we're not going to be able to carry it over, because let's say we're only dealing with one byte, so only 8 bits. So what the computer does by default is just forgets about that [INAUDIBLE], OK? So this is what is called the two's complement. We simply define minus 1 to be the thing here that if you add that to 1 would give you 0. And that's pretty cool because we don't really need late to implement a different type of sum depending on whether that's a negative or a positive number. Does that make sense? So one thing that we do here in order to convert between a positive and a negative integer is then we flip everything, and then we add 1 to that number. If you try to do it yourself on a piece of paper, you're going to see that makes sense. But if I take this number here, this is five. So if I flip everything here, so 1, 1, 1, 1, 1. Flip, flip, flip. And then I add 1 to it. I'm going to have exactly minus 5. OK? This kind of makes sense because if you try to sum this with the number that we had before, which was-- let's flip this again. It was 101 and lots of 0's. If you try to add these two numbers together, you're going to have exactly 0. OK. Any questions? AUDIENCE: [INAUDIBLE] GABRIEL: What do you mean? AUDIENCE: Negative to positive [INAUDIBLE]. GABRIEL: No, you flip and you add 1 always. Yeah. OK, so characters also encoded binaries. We have ASCII table, as you also saw in lecture, right? So it's basically a mapping of things. And here I can't emphasize enough that for a computer, a and 65 are literally the same thing. So if I write something like char c equals a, I could at the same time just write 65 here, and it would be exactly the same, OK? There's no difference whatsoever. We usually tend to put characters in variables of type. Char, not because they're essentially made for that, but because of human convention. But you can just deal with integers instead of variables of type char, and you'll be fine. The only actual difference between a char c and an int i is that an int has four bytes in most systems, while a char has one byte. They're essentially the same thing in terms of data. So what will print here? Here we're printing a digit using printf with a plus 1, and just like integers, chars can be summed, so characters can also be summed. So this is exactly 65. So there's going to be 66, and here we have 65 plus little a minus big A, which will be, I don't really know. But it will be exactly the gap between the capital letters and and the smaller letters, so we're going to get small a, right? Yeah. So this is going to print a character which is exactly this one. Good? Any questions? Here we have a bunch of different types for numerical variables. We already talk about int. Float is just a way to-- this is really funny, because when I first learned to program back in the day with Python, the first program I ever tried to write, I saw that there was a type called in and a type called float. And the float was for all real numbers. So then I asked why should I ever use an int then? Because if I can use all real numbers with a float, I would just stop using ints, right? Because real numbers are much like more generic. It turns out that this is not the case in computers because they're essentially different things. So integers and floats, the operations that you do to them are essentially different because of the way that they are stored, OK? We're going to talk a little bit more about that in a second. So double is just a bigger float. Usually in most systems, a float is four bytes, just like an int. And a double is eight bytes. A long long is actually just a symbol that you append to a type like int. You say long long int like this. Long long int x to make it longer. So in most systems, that will give eight bytes instead of the usual four. And you can actually drop the in, so it can just say long long, and that works too, OK? You can also do other things like unsigned int, or again just unsigned would also work. And that would make x be a variable like everything is positive, so you can't really have negative numbers in the way that we saw up here. So following wonderful floating point and precision. That's one of the reasons why you want to use ints instead of floats, because ints are 100% precise, right? It's exactly that number. For floating points, if you say answer equals 1 over 10-- I happen to have this exact program here, float.c. That prints to 20 decimal places. 1 divided by 10, and that usually is 0.1, right? But here if we make float and then we run it, we see that it's not exactly 0.1. It's 0.149 something. And why is that? Because you can't really represent every single possible real number in memory because there are uncountably many of them. So we're technically only able to represent a finite amount of them with a finite amount of data. But it's really interesting. Now this begs the question of how you would go about representing this with bits, right? So how are floats stored? With integers it was easy. But with floats you want to maximize the range, and you want to be able to represent huge numbers and very tiny numbers like 0.000001 at the same time. So again, same game. Does anyone have any idea how we could go about representing float in memory? Just throw anything. Yes, please. AUDIENCE: [INAUDIBLE] as if it was two ints and one being the [INAUDIBLE] and one being everything after the decimal point. GABRIEL: OK, cool. So two different integers. You can have 12.45, so that's 12 and 45. Nice. What ere you going to say? The same thing? Yeah? AUDIENCE: [INAUDIBLE] notation where you separate the base. GABRIEL: Scientific notation, yeah that's usually what happens. So this is what is called the mantissa. That's what is actually the number, and then the exponent is just where the comma is, right? So this is going to be something of the form 1, 2, 3, 4, 5 times 10 to the minus 4. I just realized that-- yeah, exactly. And then this 10 to the minus 4 is going to define where the comma is, OK? In Brazil we use comma. Here you guys use a dot. So a dot. And this is cool, because then you can focus lots of your bits on this guy here, on the mantissa, and then that's going to be your actual precision. And you can do this either in decimal or in the binary based system. There are different ways to implement this. Questions? Yes? AUDIENCE: How many places after the decimal [INAUDIBLE]? GABRIEL: That's a complicated question, because it's never really 100% precise, because as you see here, for some numbers it is 100% precise. I believe if we put 0.5 here, it's going to be 100% precise. It's going to be 0.500000. So in that case, it's perfect. But in other cases, it's much less perfect. In my experience, like up to four, five decimal places is pretty precise. If you use a double, it's going to be way more precise than that, OK? ROB BOWDEN: So just to throw some more context at floats, I never remember 100% how the spec of floats actually works, but I do you always remember that floats start getting messy. So the idea is that when you get really, really big numbers or really, really small numbers, we start getting worse and worse at differentiating between two close floats. So how I like to think about is with floating point imprecision, there are two floats that if I try to specify them in C, despite the fact that they're different numbers, they're going to be interpreted as the same number, because we can't store them differently. We need to use the same bits. And so when we get to really, really large numbers, talking like 10 to the 300 or something, it's at that point that 10 to the 300 or 5 times 10 to the 300 can't be differentiated from 7 times 10 to the 300. So that's a pretty big difference between the two numbers. But then when you get down to the normal range things, you tend to be pretty good at differentiating. And then when you get down really small, you're also getting pretty bad again. So like a whole bunch of 0.0000, it gets pretty bad. GABRIEL: Yeah, so a quick note. Never do this. Never try to compare floats using equals equals, because even if they're almost the same, almost the same is not the same. So what you usually do is you subtract them, take the absolute value of that, and see if that's smaller than 0.0001 or something like that, OK? And cool. I know a lot of people have some background in Java, especially the ones who did AP computer science, right? And Java is a language that mostly based on C, it has a couple very big differences. But for loops, and ifs, and stuff like that, they're all the same syntax. I have a few programs here to show this. So for example, a simple hello world. This is hello world in C, which you guys are definitely familiar with, and this and this one is in Java. So in Java we have this public class, hello world, and public static void main, and string args. The string args are going to appear in C very shortly. But let's not go there yet. Right now we have void here, which means that main is not take any arguments. And then we have system.out.println, the and that's kind of the equivalent for printf. Here we don't really need the backslash n because print ln does that for you. It appends the backslash n at the end of the line. But if you go into something like a for, you can see that they're pretty much the same thing. So initialization, and the condition, and the update is-- I missed a space here-- they're pretty much the same thing, except Java has as a few more high level stuff. Here we can do plus I and Java will automatically make this i here, which is an integer, into a string, and then append the two strings together. Here in C we need to do the &%d. The line here, the for looks exactly the same. And if we look at if, the ifs also look exactly the same, right? So the real big differences are in those things that you see here. Public static, void, and then public class if. So Java has what is called a virtual machine. And it is very heavily based on what is called object oriented programming, which is a very, very common paradigm for programming nowadays. And this class thing is what you see, something from object orientation, is you create a class and then you can derive objects from that class. We're not going to talk too much about that in CS50, but that's definitely something really cool, especially if you want to go into more sophisticated web development at the end of the course, like submit your final project and some nice frameworks and stuff. So basically the idea is that you don't want to re-implement something, so you create something that's very generic, like the shape, and then you create different shapes from it, and then from each of these shapes, you create some more specific shapes in three dimensions or something like that. And they have this hierarchy they inherit from the other ones, so all functions and all variables that the big shape here has, all of these are going to have, and all of these are going to have, and so on and so forth. So that's the basic idea. C doesn't have that, but C++ does have that kind of feature. And Java is heavily influenced by object orientation, so that's why you see class here all the time. And the other thing is this Java virtual machine. So this, I think, is a very smart idea . So what the folks who invented java did is they didn't want to compile their code twice if they had to run it in a Windows, or a Mac, or Linux, so what they do is they literally run something like the appliance, but you don't really see it happening. So they run a virtual machine inside of your computer, which is basically like a mini operating system. And that operating system's purpose in life is just to run what is called byte code. So instead of in C, the way we would compile this is make if, and then run ./if. I forgot the backslash in. In Java, you would do first Java C to compile it, if.c. It's not C. It's dot java. And then you have to run not ./. You get this new file if.class, but you can't really run if.class now just like we did before. This is not an executable. You have to run. You have to feed it into a program called Java, and that program is the virtual machine, and then you do if.class, or if. Yes. And then it works. OK so this is kind of the virtual machine happening. C does not have that, so if I were to put this program in a Windows machine, it would not work in C. In Java it does. Questions? Cool. That's if for super section for today.