[ Music ] >> [Background sound effects] Noah. Thou shalt build thyself an ark measuring 300 cubids in length. >> [Background sound effects] 300 cubids give or take. >> [Background sound effects] Exactly 300 and thou shalt takest two of every creature. >> Two creatures. >> [Background sound effects] Two of every creature. >> Even stink beetles? >> [Background sound effects] Especially stink beetles. >> [Background sound effects] Whoa. Cool. God is so in your face. >> Yeah he's my favorite fictional character. >> Oh, it's so late you kids have to go to bed. >> But the flood's only knee high. At least let us watch until the midgets drown. >> Yeah mom come on. You let us stay up to watch Try McLauren and such other bible epics such as David versus and Super Goliath and Suddenly Last Supper. >> Go Lis. Way to site precedent. [Sound effects] >> Well alright. You can stay up late tonight but tomorrow everyone's going to bed at 5 o'clock. [Sound effects] >> [Background sound effects] Go forth Noah and remember, the key to salvation is -- >> You've seen the movie now be a real life Noah only this Noah has been accused of killing two of every animal. Coming up next on AM Springfield. >> Oh, my goodness. That was a long movie. [ Sound effects ] >> Lighten up Lis. >> Finland, let's see that native dance. [ Sound effects ] >> I head they sent a rocket to the sun once at night and there was that submarine with screen door. >> No, no, no, no. no. Young man you need to do some serious boning. [Sound effects] >> Oh grow up Lis. >> Okay Libya exports. >> Yes sir you American pig. >> [Laughter] Nice touch. >> [Sound effects] Let's see, the exports of Libya are numerous in amount. One thing they export is corn, or as the Indians call it, maize. Another famous Indian was Crazy Horse. In conclusion Libya is a land of contrast. Thank you. >> Ow, I can't breath. Please stop em. >> I'd like to, but I'm afraid you need diplomatic immunity. >> Point of order, if you want to learn anything we must respect -- >> Point of odor, Lisa stinks. [Laughter] >> Leave her alone. >> You leave her alone. [ Sound effects ] >> [Background sound effects] Order, order, order. Do you kids want to be like the real UN or do you just want to squabble and waste time? [Music] >> [Background music] Have a great weekend kids. Be nice to the underprivileged countries. >> Good luck Ralphie. If you're nose starts bleeding, it means you're picking it too much, or not enough. >> Okay kids, Otto's in charge. Remember Otto, we're trusting you with our greatest natural resource, the school bus. [Music] >> Water bill, third notice. Jury duty, third notice. Mortgage bill, ewh, second notice. Flant Crest Enterprises. >> Oops, that's for me. Flant Crest Enterprises is my home business. >> You liar. You don't have a home a business, why would you make up a lie like that? >> No it's true. Mom and I sell religious hook rugs over the internet. >> Internet eh? >> Yes indeedy. I get some good scratch too. >> Scratch eh? >> Yep. >> More, eh? >> Yep. [ Sound effects ] >> Homer what are ya doin? >> No time to answer that Marge. I'm setting up a home office for my new business enterprise. >> What business enterprise? >> [Background sound effects] Ever heard of a little thing called the internet? >> The internet, eh? >> Oh yeah. Everybody's making money off the internet except us. We falling behind, way behind? >> Is that my good butter? >> Can't discuss that now Marge. I have to write another delicious memo. Memo. [ Sound effects ] >> [Background sound effects] This song is driving me crazy. [Sound effects] >> I don't know why I bought this stupid cake. [Sound effects] >> All right and that is the connection to CS50. [ Sound effects ] >> Alright, welcome back to CS50, this is the end of week two. So a couple of announcements -- So if you did the hacker edition of Pset 0 and still have a sensor board, that's fine. Make sure your name, user name and ID number are on a piece of paper in the Ziploc bag and just hand it to one of the teaching fellows on your way out today. We've gotten plenty of responses regarding lunch with me and CA's and TF's and we will follow up by email sometime tomorrow to figure out the logistics. And it turns out if you're nice enough to one of the houses on campus, they invite you to dinner. So now have a dinner with David and team next Wednesday. It's part of their senior common room event. Space for that is very limited. The idea is to get together around dinner in the Mather SCR as well as the dining hall and to chat and get to know some of the TF's and CA's and fellow students in the class as well as some fellow Matherites. So if that is of interest, next Wednesday as a one-time thing, cs50.net/dinner to RSVP. Speaking of David there's no need certainly for formalities in this course. It is perfectly fine to call me David and as fact, sweet as you are, at the end of these lectures to do this things like this, it's really just a computer science lecture. So there's no need for that either. Sections have -- sectioning has happened thanks to Jansu and Yukie [Assumed spelling] to use their computer science skills to take a very large dataset from FAS and also from our own database, mash them together and email 300 plus emails out automatically. If you ended up by algorithmic chance in a section you're not comfortable in, whether it's too much or too little comfort, that's fine. Just go ahead and email sectionCS50.net no later than this Friday. Or if you simply can't make your assigned section time, email us as well. Office hours continue to be in progress, especially now as Friday's deadline is coming up for Pset 1. If you're having any discomfort or you're kind of freaking out because you really just don't know how to do C or program, it's totally fine. Realize that there will be plenty of one-on-one help in the science center. You take a look at CS50.net/officehours for the current Google calendar and this is an opportunity to, as you can see it all barely fits, because there's so many people who will be there in attendance. But for me at least ask this, Marta this past Sunday did deliver the first walk-through for Pset 1. You can find the video for that or the MP3 on the problem sets page on the courses website. So if you you're asking yourself this question, "I have no idea where to begin. How do I do so?" Do at least start with that video as it's meant to answer precisely that question. And I realize that we go quickly in the course and that I've put up you know a dozen or more programs in C already. And a lot of it might very well feel like this, but honestly if not yet sat down to problem set one and plan to tonight or tomorrow, I think you'll find once you spend some time with this getting your hands dirty, it will all begin to sink in and not feel so cryptic. Finally, it turns out it's a big mistake to say something off the cuff to say something in lecture like, "Gee maybe you should all check the map to make sure you submitted problem set 0" because this induced innumerable personal emails to me and I then had to go through our survey data checking whether or not everyone in fact submitted. Or if it was a Google problem, version one of our map had a couple of bugs, one of which was Google induced because we tried to hammer their servers a little too fast. They don't like it when we send 350 plus requests within in like five seconds for GPS coordinates. So they essentially blacklisted us once in a while. That meant some of you didn't make the map and so forth. So anyhow, sat down last night and redid the whole thing and what we now have is a full-fledged little application here, much prettier I think than the original version, because I also addressed some other issues. I also realized though perfect this initial version originally was, last night around 1:00 a.m. on like my 8-core, 3 Gigahertz, MacPro, I then pulled out my laptop, which is far slower and the thing sucked; like it took multiple seconds just for the page to load. We had this map on our home page, didn't feel like the best idea for people's first experience to the site to be a little spinning globe or what not as the thing loads up. So we re-wrote the whole thing and now what you see are little hot spots. One of the reasons for the speed degradation was that when you try to put 350 of these little cartoon markers on a map, that takes a lot of CPU cycles. It's a lot of Java script codes to make that happen, but now it's a little fancier. So now you can zoom in and then as soon as you are closer to the earth, it then shows you more granularity, where things are. I can keep zooming and zooming and here we can finally get into the downtown Boston area. And in fact John and David J. are in fact from Boston, Massachusetts. So this too was an interesting bug. At first I didn't realize that if you try to plant multiple markers, i.e. multiple students or staff, at the exact same GPS coordinates, Google just pretty much shows the last person you put there. So this felt a little sad because David J. was the last one put there. And I realized, "Damn, I'm about to get an email from John, quote, unquote if I leave him off the map." So we fixed that too. We figured out what kind of algorithm it would take, though only a few lines of code to make a comma separate an English list of names like John and David J. putting the word -- the commas in at the end. So there was actually a lot of little bite size programming projects that arose as a result. But do feel free to play and I think you'll find that CS50 students do hail from all over the world. And what you can also do now, if you don't see yourself or if you're smack dab in the middle of the ocean where there's in fact no land because of a typo, click on Log-In at the top of the page. You can then click About Me and you can now change your own hometown and no need for all of the emails anymore. So, we've hopefully empowered you for that. Any questions, logistical or otherwise? I'll admit it's actually really kind of neat to just point and click around and just see from how all over students in this class actually are. So, have fun with that if you will. So, I thought we'd take a look at a little bite sized program that I actually whipped up right before class to address a questions or challenge that a number of you have run into, and that's this problem with imprecision. So we've been -- or you've been looking at problems that one, or starting tonight or tomorrow will be looking at some matters of imprecision. And remember that that just boils down to this problem of C and a lot of languages only using a finite number of bits to represent some value, some number. So if you've only got a finite number of bits, clearly there's an upper bound on just how precise you can be, how many numbers after the decimal point you can express. And a really simple way of seeing this as a footnote in problems that one says is to try to represent and a float, a very simple value of one one-hundredth. So .01, such a small number. It feels like it should be represented perfectly cleanly underneath the hood, because my God it's such a common, simple, relatively small number. But what you see here is that's not in fact the case. So I wrote this really quick program. A float F is initialized to 0.01 and realized that some of these things are just conventions. That's equivalent to leaving off the leading 0. This is not equivalent obviously mathematically, but I really wanted to see this value. So instead of just printing the value with percent F, I used .10 F, which even though it feels like I just transposed 01, it actually means something different. What does it mean if I say percent, .10 F? [Inaudible background discussion] Yeah, so 10 decimal places. So the point just means after the decimal point in this program, show me 10 decimal places. So what that means is I'll actually be able to see exactly how, or more exactly, how this program is represented underneath the hood. So let me go ahead and run GCC on imprecision dot C. I'm now going to run the default name of A dot out. So what I see is, "Ah hah." So I the programmer have been completely clear about what number I want to express. C just can't quite give it to me because of the judgments it has to make as to exactly which numbers it can represent precisely and which it's going to have to represent almost. And you can see it here. But had I done this realized, had I just printed it out, as a percent F notice that that kind of detail is kind of lost. So this actually looks much better by default. If you don't specify the point, something F you just get some number of decimal places. It looks like the number is in fact correct, but as some of you have realized intentionally per the problem set you start to trip over some subtle bugs. If you're trying to make change, especially in problem set 1 you realize that occasionally you're giving the wrong number of coins back because the rounding is off. Some of you have already had or solved this question already, well how do you round? Well if you can imagine the name of a function existing it might very well exist. In fact, so there is in fact a function called round. So what I wanted to demonstrate here is the following. I just want an int so I'll call it the generic I and I want to initialize I to the result of the mathematically rounding the process of eps decimal point two places to the right. And this is very similar of course to what you're doing in the problem set. So I have .01 I want to move the decimal point one, two positions to the right and hopefully the answer I'm going to get back is in fact, 1. But let's see what happens if I do this simple way. So let me actually undo the fix that I ultimately put in place. So I'm going to get rid of this rounding altogether. And I'm just going to leave it at this, so I gets F times 100. It's so simple, just move the decimal points. I know I'm going to lose the rest of the decimal points because if I change from a flow to an int, remember you passed all the way after the decimal point. Now notice I'm using percent D, so that's in fact correct. So let me go ahead and recompile it, rerun it and you know what, if I take .01 and move the decimal point on paper two places. I'm pretty sure I don't get 0, I get 1. But that's because notice if we move the decimal point in reality the value I'm getting is really 000.999999998. So if you then change that value to an int, by throwing away everything after the decimal point, obviously you lose all of those numbers and all have left are the things to the left of the decimal point, which was in fact, a zero. So let's go ahead and fix this. So it turns out there is a function called rounds. I express it simply by doing this. It's in a header -- it's declared in a header file not surprising perhaps called math dot H. We haven't used it before but that does in fact exist. It doesn't matter usually what order I include these files in, I just tend to be a little anal and do things alphabetically so I can find things more quickly when I get more of these things. But it's in math dot H so it looks like I have a solution. So GCC imprecision dot C enter, damn so close. But even though you might not have written this code yet, what is clearly the problem? Yeah so I haven't linked in so to speak the library. So even though standard IO as the name suggests is just so standard that you don't have say something like dash L STDIO. Because C links in the standard library automatically but the math even thought it's not standard so to speak, so I actually have tell GCC where to find the header file math dot H but I also have to tell to link in the math library. So I'm going to go with my gut. I'm going to say dash L math and realize there is in fact no space after this, and weird though it looks, hit enter. Hmh, cannot find dash L math, but remember the RTFM proverb from last week, let's just check the man page. So man round. So hopefully there's a manual, so yeah. The round function, it's apparently in chapter three of the manual. Notice I got this part right just by guessing. I see that there's new versions of round. The one I used is called round. You pass in a double or a float, which is not even as good. Here's the hint, uh the manual answered this question. So let me go ahead and fix this. So GCC not dash L math, dash L M, okay that's pretty good. Let me rerun the program A dot out and now I have the answer. So we'll see another trick today about how you can round without even knowing about this round function. But the exercise here is that if you think that there might be a function, a utility function of sorts, well check the man page for the name you might think it has and more than that, especially if you've not gone ahead and gotten any of the recommended books, which really aren't necessary you can go to the resources page of the course website under C. By far one of the best references here is this thing, C reference. We took this from cppreference.com, C plus plus reference, ripped out all the C plus plus stuff and left just the C stuff and you no what, I want some math functions. Alright standard C math, okay interesting. It looks like C gives me all of these things, most of which I don't need. Oh there's a pal function. You might find that useful at some point but not necessarily required anytime soon. But I want it, interesting that round is not documented here. Let's see display all entries. Okay well we won't waste time on this but somewhere it is actually embedded, for some reason not here. Damn, that's an interesting omission. So for every other function except round, turn to that documentation, which I promise you is outstanding. But it actually it is a good way of learning some new tricks right. We can only cover so much in lectures and even in sections. And frankly you'd get bored quickly if we spent an hour saying, "Here are the fifteen functions provided by the math library and here is fifteen examples of each." And that kind of stuff you can just kind of flip through when you care or when you need to. And again that's all about how one bootstraps him or herself to learning a bit more about a given language. So, let's go ahead and learn a bit more. So, we started last time with a bug. Let's start this time with another but of sorts related to this very simple idea of swapping two variables. Out of context, really not that sexy to say I want to take this variable and this variable and move it's value into this and this value into this, but it's a relatively simple exercise that triggers some problems. So in buggy three dot C, which is in your print out from Monday or if you weren't here there are extra printouts probably still outside I decided this week today to take off the training wheels so to speak so even though I've been very good in putting comments as you should in problem sets in the printout of this code, I wrote a little script that rips out all of the comments from the code displayed on the screen, only because I realized that if I continue asking questions like what does this block of code do? And the answer is they are expressed in that comment, really not all that stimulating. So realize you have answers in your handouts if you need to glance or reference later, but for the sake of engaging trying to focus up here when interesting topics come up. So here is a function, it's called main, that's my default function. This is kind of interesting. There's something interesting and new going on up here but more on that in a moment. So what does main do? Main declares two variables X and Y, gives 1 the value of 1 and 1 the value of 2. This program is going to printfF in each in value, not very interesting and then it's going to say swapping dot dot dot. And then it does what? Well in English what is this line of code doing? Like how would you express now that you're getting a little more comfortable with programming and see, what is that line doing in English. Okay so I'm calling a function and the function is called swap. Presumably it's meant to swap X and Y because if you kind of think ahead where this program is probably going, I'm hopefully -- I'm trying to demonstrate that X and Y are 1 and 2 but then I call swap and now they are 2 and 1. Okay so let's see if that is in fact the case. Let me go ahead and this is buggy 3. So make buggy 3 enter, and now notice incidentally one of the upsides of using make even at this point instead of running GCC manually, which is also instructive, realize that all the stuff it spits out automatically has among other things linker flags like this. So we sort of aggressively provide you with flags like dash L M just because we figure if you're running make you don't want to have to think about details like that but realize if you've been using make some of the magic has been happening because of our automation of that here. So now I have a program called buggy 3. It's in my current directory. I'm going to start getting pedantic with dot slash to say this directory, a program called buggy 3 enter apparently it doesn't work. It's broken. It's buggy. So why is that? So let's take a quick look. I'm going to -- this code looks pretty good. It's hard to find but maybe you have found it. But it's hard to find any fault logically with the code in main. So mainly presumably in it's this swap function. Maybe it just doesn't do anything. So let's look. So if I scroll down, okay alright somewhat of a new approach alright. But hereto, realize even though I'm calling some of these barriers A, B and temp, which would seem to violate this principle of good style, well realize there are some context like iterating in a look or just calling the variable I, so simple. It's very reasonable. Calling a number a counter N, very reasonable. Calling a three-line -- four line functions variables A and B because that's really all they have -- the function doesn't have to do all that much. Realize sometime that it's completely legit to use very simply named variables. So in this case how do I swap A and B? Well if I've got A here and B here, I can't just move -- copy A to B. Because what happens if I just do B equals A semicolon. I lose B. I'm kind of doing too much at once. So what would you do in reality? Well you can't just move this here and then that here because of that problem so let me just move B into a temporary variable, a little place holder. Then I can clobber his value -- change his value by doing A against B and then finally I can restore B by using per this last line here that tenth variable. So there's a trade-off here, subtle though it is, interesting over time but notice that I'm using 32 extra bits to implement this particular function. I'm taking A and B, I'm swapping them but to make that happen I actually need in this implementation a bit more memory, but not such a big deal. But apparently it's still wrong. So why can you find logical fault with this. Or even if you're maybe among those more comfortable, you can express what the problem is. Why is swap not apparently swapping? Yeah. >> [Inaudible background question] >> So I'm not returning anything. So that's an interesting point. So swap is declared as having a return value of void, so that's interesting because it's certainly not printing anything and the last time we saw a function that didn't print anything, it really didn't do anything useful. It didn't have any side effects. So that could be the explanation here. So it's not returning anything. Certainly up here notice I'm not even assigning a variable. The return variable of swap because it's return variable -- it's return value is nothing. It's void. So we could fix this that way somehow. But what else might the problem be? Yeah. >> [Inaudible background response] >> Okay so that's an interesting gotcha too. I seem to be talking about X and Y up at the top here in main, but then all of a sudden I start talking about A and B, so clearly X and Y aren't getting swapped because I'm only swapping A and B. So there's a couple of interesting take-aways here. So that's true in this case and it's not fundamentally the explanation, but it's definitely related. So in this case, yes I have two variables in this context of main called X and Y. I go ahead and pass them in as what we'll start calling consistently arguments. So arguments are inputs to functions, otherwise known as parameters, slight difference in terminology depending on the context but for the most part they're synonyms. So a function can take arguments or inputs and that obviously influences behavior. Think back a week, printfF takes an argument. It takes a string and maybe multiple arguments separated by commas, the variables that then get inserted into that string. So we've seen this before, so inputs to functions are called arguments or parameters. Well it turns out the way these work is as follows. If I have a variable X here and variable Y here notice that in the function that I'm calling I need to give those inputs names. Now I could coincidently name them X and Y but that's not strictly the case right. Consider after all that you guys have no idea what the person who wrote printf called those variables. You've been passing in quote-unquotes and then a string inside of it and maybe comma X comma Y comma Z but hopefully that programmer who wrote that function twenty plus years ago doesn't have to know or care what your variables are called. He or she can use his or her own variable names. So that's in fact the case here. It is completely my prerogative to call these things A and B, Fu and bar, anything I want, because what happens you call a function in pass and inputs usually, a copy is made of the inputs. So yes I have 32 bits up here called X and 32 bits up here called Y. They're storing a value, 1 and 2. What happens when I call swap is that a copy of X and a copy of Y are passed in. And now in this scope so to speak, in this context we now have copies of X and Y. They're called A and B. There a different 32 bits for A, a different 32 bits for Y. Are these four lines swapping do you think logically, A and B? Like is the code at least correct? So yes right. There's no logical fault with doing this. I have a temporary variable. I keep A around. I clobber A with B's value. Then I update B's value with A's former value, which I tucked away and tapped so logically if you think this through and even kind of play around with a simulation on a piece of paper. That's correct. But at this point in the story the very last line of this program, what is A's value? So what is A's value where the arrow is there. So 2 and what is B's value, 1. But what are X and Y's value? They're still the opposite. They're still the original values because again these are copies. So the key take away here is that when you actually call a function you get a copy of the variables that are being passed in. Now we'll see in time that there's a solution to this. The fundamental problem here are that functions like swap have their own scope, their own context, their own dedicated memory. So yes you can pass inputs to a function like swap. And yes that function can manipulate those numbers, do some math on them, even print out things, all side effects but it does not have the capability to change the original variables values, at least not yet. So we can see this in one other context here. So let's take a look at this little snippet. So here's a function called increment as the name implies. It's purpose in life is just to implement a value called X. Well they claim that this identical in spirit to this same problem. Let me go ahead and open buggy 4 dot C. Scroll down. Notice that I'm even claiming a simpler program here. X gets 1 quote-unquote. X is now 1 presumably incrementing dot dot dot. I call increment and now I claim it's incremented and then okay X is now 2 hopefully. So let's do this. Make buggy 4 enter. Increment that's interesting. Error oh okay that was the bug. Not an error. That's intentional. So notice what happened. I'm going to do it more simply with GCC so GCC of buggy 4 dot C. In function increments error X is undeclared. But wait a minute, I'm pretty sure I had int X so what does this mean? If you haven't realized it already if you get errors from GCC they're cryptic a bit but they also have some juicy information; the name of the file that's got the problem colon, the line number that GCC at least thinks the problem is on or began on and then hopefully an instructive error message as in this case. And realize too especially if you're first experience in the science center or on your laptop with CS50 Pset is to get not three lines of errors but like this many lines of errors. Realize that early on a stupid or simple little problem just trigger a whole lot of confusion. So again if your first reaction to your problem set is, "Oh my God, I wrote ten lines of code and generated a hundred lines of errors" fix the top ones first because there's often a cascading effect. So don't pluck off the one you understand because it's in the middle. Start from the top down and you'll likely knock off multiple bugs at once. So let's look at line 40. So notice I'm using, well let me use nano here for a second, so buggy 4 dot C. Notice if I scroll down, notice that the line number is changing so I can see, "Ah hah" line forty of forty-two. So it's not a very long file, X plus plus. So hereto we see the fundamental problem of scope. Notice in the top of this program buggy 4 I declared X. It's X. That was good. And then I assigned it a value of 1. But now in increments, the increment is a function. Increments has its own scope, its own context, its own chunk of memory to play with and guess what, X was declared in someone else's scope, namely me. So you can't just start talking about X in the context of increment because who knows where increment is being stored in memory. Increment knows nothing about make other than what it's told and apparently I have told increment nothing because I didn't pass in any arguments. So this program fundamentally doesn't work because I'm trying to implement a variable that just doesn't exist in that scope. So what's a solution perhaps to this problem? How can I at least get this program to compile? What could I do? So I could declare X. So I could say something like, "Alright well the problem is that I didn't declare X." To declare a variable means to give it name and to give it a type. Well let's say this int X, alright does that fix it. >> [Group response] No. >> No obviously not. That does give me X but a problem in C in many languages is if you don't initialize a variable who knows what's inside of it right. People have been using this computer for you. You on your own computer have been checking email, sending -- checking websites. So a lot of your RAM is in use and who knows what 0's and 1's have littered your RAM at this point in the story. So when you just say int X, you're just telling GCC give me 32 bits of space. But if you don't tell GCC what to put there the compiler, the computer is pretty much going to hand you what is already there. Now that's a bit of a white lie because some operating systems do scrub the memory so if you would actually get back in some programs is all 0's and is better than just complete nonsense. But the rule of thumb for today and for a while realizes do not ever fail to initialize your variables. Do not assume that they will be 0 because weird bad things will happen. So this does work in terms of compilation. Let me go ahead and save this. Save-modify buffer, yes, enter. Let me go ahead and rerun GCC. That made GCC happy, but it didn't make the logic of my program happy because I'm incrementing -- now I'm A dot out. No I'm incrementing some other variable that yes its 32 bits but it's a different 32 bits. And again I haven't really solved the problem. So what then is another solution to this problem, like how could I go about fixing this problem in buggy 4 dot c correctly, quote-unquote? >> [Inaudible background discussion] >> Yeah so what if the problem -- so the short answer is what about global variable. No something we've really touched on yet, but it's a simple idea. If the fundamental problem is that X does not exist in the scope of increment. It only exists in the scope of main. Well is there some other context, some other scope that all functions can see. I feel like intuitively I could get away with some trick like this. You know what, let me say X gets one there, but you know what let me try declaring X outside of every function because if you think of it now as having -- being viewable by the entire file this kind of makes sense. Now X is in scope for everyone because it wasn't declared inside of any particular function. So let's see if this works. Let me save this. Let me run GCC on buggy 4 dot c. Okay compile, so that seems to have been progress. No let me go ahead and run A dot out. Viola, so that did in fact fix the problem. So yes global variables are a possible solution to this problem but now what we just handed you as a solution, we kind of need to take back. In general using global variables, bad. That's sort of the montra within programming because global variables very quickly become a mess. It becomes unclear when you start writing programs that are this long, but this long and spread across multiple files. It's not clear where they were defined. Realize that if things get more sophisticated we'll introduce better ways of solving this problem for scope. But in this context for such a simple problem of incrementing a counter, which frankly seems to have little real world value as of it, this is an adequate solution to this problem. So for now, the tool in ones tool kit you have this ability to use global variables but clearly per the previous examples do we have the ability to pass inputs and get outputs so in general you should take the latter approach. So I promised to explain what this is here. So this was buggy -- actually let's go back to buggy 4 since we're already on it. So this is buggy 4 and notice that it to at the very top of the page has this, which looks like a function but it's missing what, minimally? There's none of those curly braces. Every time we've declared a function so far we have open brace and then some code right. It's missing code. But there seems to be this coincident, a void increment open paren clothes paren semicolon. That looks awfully like this thing here except I got rid of the code. I got rid of the curly braces and I slapped on a semicolon and also got rid of the line break between void. Incidentally you'll see different conventions. This is a matter of style. A lot of books, a lot of people will write code like this on one line. Personally I actually tend to put the return type on one line and the name of the function on the other because with sophisticated editor, text editors, word processors you can actually search your code and say you know what, I know I want the function called increment but I want to find it when it's the left most character on the screen because then I can find where I implemented it, not where I called it. So there's little tricks like this you pick up over time. But it's just a matter of style. So why do I have this seemingly redundant mention of increments up here? Well my program is working, right. We've mixed it with the global barrier. Let me go ahead and delete this for now, the seemingly superfluous line. Let me go ahead and run GCC of buggy 4 dot C enter, huh? Let me redo that. You know maybe it's not my fault. Maybe the computer screwed up. Hmh, probably not the computer's fault, so I'm doing something wrong, what is it? Fortunately again GCC is being a little helpful but it looks like I made three mistakes, line 23, line 38, okay line 23 gain, so that's two mistakes. But what's the warning saying? Implicit declaration of function increment. So the short explanation of this is that C is kind of stupid. It's an old language, so it's a very powerful language but when efficiency was more important then user friendliness certain decisions were made. For instance the decision was made that you cannot call a function unless you've already declared it earlier in the file than your actual calling it. So what does that mean? It means if I want this line here to call the function called increment, well it had better have been defined somewhere previously in that actual file. Alright so there's clearly a fix for this. Let's see let me just go ahead and cut these lines using little text editor tricks that you can just copy, paste and nano in different ways or just retype. Let me just go ahead and paste it here. Alright so the problem is if the increment was defined, was implemented after main, well an easy fix is just define it before main. So let me go ahead and recompile. Let me go ahead and rerun GCC and that seems to have fixed it A dot out enter seems to have worked. So does this mean the simple solution is just always put your functions above main. So maybe but there's some push backs here. So one when you open the file the program ultimately runs main first. I as the reader prefer to see what the program does first. I don't want see increments. I don't want to see other random functions. I want to see the main function first. So just in terms of friendliness and readability it feels like a good practice to put main first. But then you clearly run into these problems. And if you really think this through you'll run into scenarios where one functions call another and then he might call that again. You run into a problem where this guy has to go here and this guy has to here, like you'll run into this endless loop where you're in this catch 22. Everyone can't go in front of everyone else. So there is a solution to this problem. Not only can you define a function, to define a function is the very precise terminology for implementing the function without actual code. You can also declare the function by simply stating at the very top of the file what the return type is, what the name of the function is, what its arguments if any are semicolon. So at the top of most any program you write that has multiple functions within you just have to get into the habit of declaring your functions at the top of the file right. It's kind of nuisance job. It does not have this downside. PHP does not have this downside. It's sort of an artifact of the fact that when this language was really first in use it took time for the compiler to read the whole file from top to bottom, left to right. So it's not going to waste cycles and waste human time by reading it once just to figure out what functions you wrote and then go back with that knowledge and start compiling. So it's that simple reason there. So it's minorly annoying these days but very simply solved. Well let's look at one last buggy example. So here we have a very similar variant. So what I initially tried to do, this program compiled and this program has a global variable. Look at the top of the file, int X. Here's my function declaration. Here's main. Here I initialize X to 1. What do I do down here? You see already why this program is not in fact going to increment and then print the value of 2. So I didn't declare it as an int in main but that's okay because is there an X in scope, at that point in the story where my pointer is. There is as I declared a global variable called X up here. So this variable is in scope everywhere which means it's certainly in scope here, which means at this point in the story I am successfully initializing X to 1. But notice what happens if I run this thing. So this is buggy 5 -- GCC of buggy 5 dot C. And we go ahead and run A dot outs here, A dot out. Apparently the code is broken, it didn't compile but the code is printing one both times, what is happening do you think given these concepts of today? Yeah. >> [Inaudible background discussion] >> Yes, I declared X twice. And because I declared X twice in a more recent context, one that's actually enclosed in these curly braces, this is the declaration of X in the bottom of my file is quote-unquote shadowing or shadowing the original declaration of X. So this is completely fine. You are welcome as a programmer to use the same variable name in multiple context but if you pick the same name, that's all in context, still in scope from elsewhere. You're going to shadow it and end up incrementing X, yes but what is the value of X at this line the file, 11. But it's this copy of X, 32 bits that was declared inside of increments, not the 32 bits that was declared at the very top of this file by way of a global variable. So again another subtlety but this is actually a good thing because it means that C is very -- it keeps things very tight. If you declare a variable in a function, that's the one that you actually have access to. But there's actually an interesting explanation for all of this. And this is just a teaser because we'll start to peel back these layers in future weeks as to what's really going on. But for today's purposes, long story short, your computer -- nice.fas.harbor.edu it has a bunch of ram, probably like a gig of ram to gigs, four gigs whatever it is these days, and if you think of your RAM, I mean physically they're these little silicone boards. They're these little chips so if you think of them literally as a rectangle and inside of that rectangle are a whole bunch of bytes, billions of bytes, you have gigabytes of RAM. Well, what happens when a program runs its main function first take some of the bytes from the very bottom of your bank of RAM, so visualized here. So main's parameters, any inputs to main that we'll start using today, end up at the bottom of your RAM. Again if you think of your RAM, you're memory as just some big rectangle, so when main is actually called main can have equal variables, variables like X. Variables like those we've seen in examples, those yet put next into your RAM. So, from the bottom on up meanwhile if main happens to call a function called Fu, well if Fu takes some arguments, if Fu takes some parameters like A and B those parameters are stored next in your computer's ram, so above conceptually main's memory. Meanwhile if FU itself has some local variables, TMP that 32 bit integer, those meanwhile get put next into your computer's memory. So the point of this story is that when we talk about scope or we talk about context, what we're really talking about are conceptually these different chunks of ram that are being allocated from your program's start to finish as it's actually running. Fu has it's own layer there, it's own frame as we'll start calling it. That's distinct from main. That means that main does not have access to Fu's chunk of memory because just look at it, it's in a different place in the computer's memory. And things called global memory are actually stored somewhere else altogether. This is a more complete picture of the story we're beginning to tell and will continue to tell over time. Our global variables are actually stored way at the top of your computer's memory along with what's called the text segment. So all those 0's and 1's that you see in C outputs, when you run a program they've got to be loaded into RAM off of your hard drive. They too end up at the top of the rectangle that is your chunk of memory. Any questions? Okay that was a lot. Let's take our five minute break a bit early today. [Sound effects] Alright so we are back. Let's solve this problem in one way to just to equip you for one possible approach. It was actually proposed already here in the crowd, was to use a return value. So again the problem was that we're running into problems of scope that somehow relates to memory management, which is a topic we'll revisit. Well one approach to this problem of scope would be yes, don't just have a local variable whose value gets incremented and then do nothing with the result. Return the result of your hard work, return the result of those mathematics. But for this to work in the context of incrementation we're going to have to make a change. If I want to increment X maybe I should actually provide X as an input to the function so that that function has access to it. And you know what don't just let that function increment X or A if that's what the name is that it wants to give it, go ahead and actually have that function turn the result of its mathematics. But then the burden is back on me, main to actually keep it around. So a relatively simple logical fix to that particular problem, but let's see what else, how else this can expressed. So this now is slightly more compelling right. We already have a way of incrementing values, something plus plus. So that's not that interesting but you already have been inclined some of you to turn to the math library for rounding, so there's certainly little bite-sized problems that would be really nice to factor out and put inside their own method -- and put inside their own function. Maybe another such example similar to round is cube function. If you want to take a number and raise it to the power of 3 you know yes you could X times X times X all over the place, but it feels a little cleaner, or should start to feel a little cleaner to actually outsource that to a dedicated function like a function called Q. Define it as taking one argument called X. The name I give this argument does not matter and because this is such a short function I'm really not going to give it an interesting name, it's really not justified, so return A times A times A. So it's a slightly more useful function here. It does in fact solve the problem because now at the top, I'll pass in X as an argument. It does the math and returns the result and then I keep X around as a return value therefrom. Alright so enough on scope for a moment; let's actually segway to a topic that ultimately will be related. Because it boils down to manipulation of memory, but suppose I want to do something like this. If I want to write a program called grades dot C and this thing has to somehow manipulate grades for a course. I'm going to do something like into main, into RXC, Charstar, argv and now if I want to right a program that manages all the grades I get in a semester. Well I could do something like this and for simplicity we'll say grades are numbered from 0 to 100. Alright, so my grade for course 1 is going to be an int, course 1. My grade for course 2 is going to be int. Int course 3, int course 4. Okay so now I need to put values in these so I'm writing a program so that I sort of geek in my dorm room can do things later like course 1 -- I can do something like this. Hello me, what did you get in course 1, question mark closed parentheses. And now I'm going to do something like course 1 gets, what would you propose? Yeah so gets int for instance from the CS50 library and immediately begs the question well how do I make that happen. Well I need standard IO for printf. I need the CS50 library for get int and then okay I got that one course, now let me do a copy paste. So I'm just going to past this three times. Incidentally these little keyboard tricks I'm doing, if you again go to the course website resources, there's little instruction sheets for nano for VIM and also Emax which is another one. So I know how to change things around. I'm just going to change this to a 4 a 3 okay, so this will work. Okay so this program works. So arguably it's pretty clean. It's pretty simple. It's hard to find a huge amount of fault with this, but I only take four courses this semester. Next semester I'm going to another four, and after that another four and another four, 32 or more maybe in the end. Okay I can get a little creative here, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 lines of code. Okay so I'm going to get 12 so I get the white space. Okay so here's fall. There's spring. Sophomore year, sophomore spring, junior fall, junior spring, senior fall, senior spring, good. Now my program's coming along. [Background sound effects] At this point this should be rubbing you the wrong way, just like some of your larger scratch strips, probably started to get out of hand after awhile, especially if you're copying or duplicating strips or nesting things a lot. So even if one has not taken a course in computer science, hopefully the act of programming is not as tedious or naive as just copying and pasting like I've been doing in Microsoft word for years. So there's clearly an opportunity for a construct here called a loop, right. A 4 loop, a Y loop but there's kind of a problem at least for those who don't have any programming background. Even if I have a loop, I kind of still need 32 of these things, right. So I need a lot of these and thus far we've not seen a way where you can create a new variable inside a loop but create a new copy of it. We've declared variable I inside of a loop, but we don't get a new copy of I for every iteration. Usually we're incrementing the same copy of I. So we need a solution to this problem. I need a way of representing 32 ins and I'd really like programming not to be as awful as having to define 32 separate integers and then me the human remember what the name of all of those things are called and in fact, there are. So one of the nice things about seeing in most languages is that they provide us with this thing called an array. And I use this language in week 0 when we talk about scratch, because scratch has things called lists, which is sort of the child friendly name that they gave to the notion of the list or array. These things are also called vectors in some context. Linked lists will be something related. They are all different in certain ways. So what we define today I actually distinct from scratch did and even what some other languages do. But this is a little excerpt from a really nice tutorial on line that we also link on the courses and resources page about what an array is. So we've talked about memory already today. So it turns out and let me try to make use of this for one second. If again your computer's RAM is just a big rectangle from byte 0 on up to byte like 4 billion, if you got 4 gigabytes of RAM. Well what I'd really like if this represents my RAM, if I want to have courses -- if I want to have 32 courses I feel like I want to say something like int courses but now I don't want to copy-paste that. I want to say give me not one int but 32 ints all together. Well the notation for this is to use square brackets, say the number of ints that you want, closed square bracket, semicolon. What that has done is to declare for me a variable called courses. That variable tough is an array, an array of what, an array of integers. Now an array is just a contiguous block of memory that's been divvied up into smaller pieces all of which structurally are the same. Put in real English an array is just 32 ints back to back to back in memory. What that means is if I declare a single int called X with code like that, that would carve out my computer's RAM, 32 bits and call it X. But if I instead do int courses 32, what I really get then is a whole bunch of int here, and this obviously now a picture we're drawing here so they won't fit all in a row necessarily. [Background sound effects] So if I just count out 32 of these things, this is all going to be part of courses so this whole chunk of memory will have the name courses. Now how do I access an individual course, well what I'm going to do is this. I'm going to go ahead and clean up the code I started writing a moment ago. So I'm going to delete all that junk. I'm going to get rid of this original approach and I'm going to say something like int courses 32, now I've got them. How do I know start plopping grades inside of each of these cells, each of these elements. Well course 1 is no more. Courses is a variable. How do you think I might get at the first element in an array. Yeah so 0. We always start counting from 0 so courses bracket 0 equals get int. And now down here this becomes courses bracket, oops, courses bracket 1 gets get ints. Let me do another copy-paste just for now. Courses brackets 2 gets get int and you now see where this can go. We already have the ability to implement loops in C. We have the ability to have counter-variables in C like I and J. So do you already see in your mind how we can kind of rip out almost all of this code and try getting rid of a hundred lines at once. In fact I don't really need any of these lines either. Now this is not yet a loop but couldn't I do something like 4 int, I gets 0, I is less than 32, I plus plus. Give me little curly braces here, what did you get in course 1? I'll fix that in a moment. Let me close my curly braces here. There's a couple of problems. What's one I can fix easily? Yeah so it's not courses brackets 0. Stop hard-coding that. Courses bracket I and then this too is a little weird. I can't hard-code this. Now obviously that's not the solution there to change the 1 to an I in that context, but what could I say, course percent D question mark close quote comma I. So again same building set and again already viola, you know a new idea. We just deployed this really quick. We said you can have multiple variables all of the same type but give them one name and refer to them numerically in this way. Now we have the capability of expressing what in the beginning was a very simple problem. I want to waive inputting all of my grades. Well now let's actually look at a polished version of this. Well in array 1 dot C I have this program here and it's a little more interesting because I didn't want to just input my data, I wanted to just compute my average, which is slightly more compelling. So let's actually see the result of this first. So GCC array 1 dot C. Uh huh, can fix that right -- dash L CS50 good. A dot out enter. What were your quiz scores? So I got lets say 100 on the first one, then I kind of screwed up. So you're average -- you'll remember that comment now if you're the student that gets a 50 on the quiz right. So alright, so 50 is good. So 75 is my average. So you could do this on a calculator but if you had 32 courses, you now it's kind of nice to let a computer do that. You don't want to have to do it all by hand necessarily. So how does this work? Well notice, I'm incrementing some variable, so we already have the building blocks in there. I'm doing some mathematics. It feels like I'm maybe rounding too to the nearest int. You would notice if we were just using casting from floats to ints in this course instead of actually mathematically rounding grades at terms end. So let me go back into this. This was array 1 dot C. Well let's see what I'm doing. Well new feature; it turns out what I started to do on the fly there a moment ago is kind of bad practice. I hard-coded the number 32 and not only once but twice, that tends to be bad practice. So that's what's known as a magic number, magic in the sense that where the heck did I define that value all over the place? So another feature of C, and it's a little dark, I apologize here on this screen is this ability to have another thing called the preprocessor directive. We've seen the sharp sign before. That thing sharp include is a preprocessor directed. There's another one that's useful. Sharp define allows you to define a constant. It's not a variable. It's just the symbolic representation of something, in this case a number. So that henceforth in my code I can use capital QUIZZES anywhere I want and it's going to refer back to that same value. Now just intuitively what's an advantage to having used a constant like this instead of typing in 32? Yeah. >> [Inaudible background discussion] >> Yeah, exactly. If I'm on -- if my class has more quizzes in the future and I need to store more grades I just change it one place, recompile and done. And in fact that's a bit of an annoying process. We'll also see ways when I run the program I could just tell my program how many quizzes we had that semester. We don't even have to hard-code it. Now the fact that I'm capitalizing it this is this matter of style, convention. Almost any time you have a constant value, you should capitalize it entirely so that it stands to you the reader and other readers, teaching fellows or other programmers that in fact, it is a constant value. So what's going on here? Well let's see I have a float called grades bracket quizzes. Alright so we've not quite seen this context yet in examples. It turns out if you want to have multiple variables all of the same type, you don't need to put them each on their own line. You can just bring them together with commas. So on that first line I'm declaring an array called grades, I have how many elements in it, how many floats, so two as per the constant called quizzes and then after that I have another float altogether, a different chunk of memory called sum. And I also apparently have the foresight to declare a variable called average and one called I. And I start to use those here. Alright print. What were your quiz scores? Alright for I is 0, I is less than quizzes, I is plus plus quiz number percent, alright this is easy. I know what this is and here's the line of code that we already did on the fly albeit with get int grade bracket I get flow. So realize 0 indexing is important. When the compiler gives you memory you get 0 1 2. If you start counting at 1 you get 1, 2, 3, 4, 5, 6, 7 that's bad. You wanted to end at 6 so to speak. So what do I next with this value? Alright so now I have some. How do you compute a student's average? Well you take all the grades, you sum them together and you divide them by the total number of quizzes right, old school stuff. So sum is initialized as 0. So I is 0 on up to quizzes to another 4 loop, so this is easy alright. I'm just adding to sum inside of this loop the ith value of grades, which is just 2, but again realize the dynamism of this program. Just by changing that constant I could do this for a whole semester for four years worth of college. So now here's an interesting trick and I'll offer this just as a little teaser for now. To compute a student's average is really the result of taking the sum, dividing by the number of quizzes but then there's this .5 trick. For those of you who want to think this through actually for problem set 1, this .5 trick, this is how you can implement the notion of mathematical rounding. And I'll leave that as a little thought exercise, but if you think through what might happen to your grades if you do and do not include this .5 and then proceed to cast to an int, casting has the effect of truncating everything after the decimal point. So there's actually a very clever magic that's induced by adding .5 before you throw that stuff away. So the person who wrote the math round function in the math library, odds are they did something very similar to this. Then finally what's the average, well I just print out the results. Well just to show that you don't need to show that little trick, array 2 that you have print outs of is the exact same thing but I decided to use the round function explicitly instead of rolling it myself. Okay so enough about math, because we've actually dwelled on this for some time. Let's actually start manipulating things that are more genuinely useful and those are strings right, because problem set 1 even though it's largely grounded in numbers and arithmetic, that's really just a design of necessity. It's actually kind of hard to do more sophisticated things when you've not even written one 4 loop or one Y loop in C. So it's meant as a stepping stone. Problem set 2 though is going to introduce you to another real-world domain of cryptography, the art of concealing information. Information is often expressed in English or some other textual language and so that makes the question, "How do I somehow manipulate actual characters, actual strings, actual paragraphs or entire letters, entire letters of text?" So here's a simple example that's going to get us there. I turns out that what we called last time a string, we already know that a string is synonymous with a slightly more confusing Charstar the asterisk so again we'll tease apart what that means but a string is a Charstar. For today's purposes what a string really is is an -- it's an array not a int but an array of Chars, an array of 8-bit characters. So that kind of makes sense right? An array of if a string is just a contiguous sequence of letters, you know f o o or h e l l o you know it kind of makes sense that you know what the perfect data structure for strings if we're not talking about ints anymore but are instead alphabetical letters why don't we call this something like the string S so then I can put the letter H there e-l-l-o and so forth. It feels like it makes perfect sense to actually store a string in an array because I actually get this built-in feature of storing things back to back to back and not all over the place in memory. So this program here is called string 1 dot C. Notice that I'm using a new library up here, string dot H for reasons we'll see in a moment. Now what am I doing, well I've removed the comments for today's training wheel removal purposes but this line of code there simply gets a string from the user, not a flow per se but a generic string and in fact its going to store it. Get string is going to allocate a bunch of RAM like this and whatever you type it's going to put the first letter here, the next letter there, the next letter there and so forth and then it's going to hand you back that entire chunk of memory. So I do need to do one sanity check and this too is a teaser of sorts today. It turns out that if the user is malicious or foolish or there's just some problem that you can't anticipate we need to sometimes have return values that are not legit values like the actual string, a return value that's not the actual return value number you were expecting but some kind of sentinel value. So a special value that you the programmer can check for and if you get back that sentinel value instead of a legit value you know something went wrong and error checking is one of the topics for Monday. So it turns out, and you would only know this from reading the documentation or being told it in class, get string maybe can return a special value called NULL in all capital letters. So we'll use this throughout the semester. So today we're just scratching the surface. So this is just a special value NULL that if you check for it, when you get it back it means that the user did something like never typed anything or just hit enter immediately or just tried to generally mess with you or did something you weren't expecting. So the very first thing I do in this program is I check. If S does not equal NULL that's a good thing, let's proceed to do something with it. I now have 4-loop. 4 I gets 0. I is less than, oh this is interesting. Take a guess what this briefly named functions does. >> [Inaudible background discussion] >> String lengths. Stir lengths, so this is common feature of C. So why say string length when you can say stirleng. Well how does that -- that's a function. It exists in the string library whose hetero file is called string dot H. Now even just a little tangent, how would you the human implement string length. Well, I'd probably start looking at my chunk of memory and just start counting how many legitimate values do I actually see. Now it turns out there's going to be a special value that will store at the end of a string. Backslash 0 is literally the value of [Sound effects] eight 0 bits in a row so it's a special value not quote-unquote 0 which is an ASCII character but rather a special sentinel value so stirleng as we will see eventually in more detail actually iterates over an array like that to get its length. So what does this do, well notice is a Char because I declared it up here. S is a string because I got here from the user and S bracket I gives me the ith character in the string and then plops it in the variable called C. So what's the end result, well let me go ahead and on GCC on string 1 dot C, so undefined reference again dot LCS dash 50 okay so A dot out enter okay it's not doing anything why? Right because I didn't say printf -- I really cut some corners here so hello there exclamation point enter. Okay so h e l l o comma space t h e r e exclamation point all in a separate line, why did that happen? Well this was string one dot C, that's precisely what should have happened because in this 4 loop I printed percent C which is the new format code for just a character backslash N and so I got everything on a separate line. So in fact had I done something maybe a little less weird and just complied this and rerun this, now I have a sentence here enter, now I get it back. Now grant it I forgot one new line altogether but all this program demonstrates is that a string that you can fetch from the user by way of get string hands you effectively a chunk of memory that you can iterate over with this bracket notation just like you could a whole bunch of grades from your course work. Well string 2 has a slight variant on this so in string 2 dot C I do something more intelligent which is good design so this speaks to this access of design. Notice this what have I done differently here if you can think back or on your printouts see the difference between that line and the previous version. [ Silence ] >> A little louder, anyone? >> [Inaudible background discussion] >> Yeah, so I have two initializations. So notice at the left I have I get 0 comma N get stirleng S. Why did I move or add this declaration of N and assign it the return value of stirleng in the initialization part of the loop instead of, I'll scroll back if you haven't the print out, instead of putting it right here in the condition which was really nice and clean and sensible. >> [Inaudible background discussion] >> Yeah, because this approach elegant though it is, it's nice and compact, right looks like a really good piece of code, but remember the condition is checked every iteration which means the code inside this condition is executed every iteration which means you're calling the function again and again and again for as many times as this thing iterates. No what does that mean? You're checking the length of this string by going 1,2, 3, 4, 5, return 5 again and again. 1, 2, 3, 4, 5 return 5. 1, 2, 3, I mean this should feel stupid because this changing length in any way will know. So they're to is an opportunity for optimization for a little bit more clever design and thus in string 2 do I actually call that function once? And I wanted to be a little elegant so I put it in the 4 loop. I could have just done this and just got stirleng of S here and I didn't need to use this common notation so again there's often multiple ways to implement the particular goal but realize that was a fundamental improvement because I'm not calling the function whose value is never going to change more times than is strictly necessary. So let's use this same feature to do something that's more useful. So it's a little weird looking code but it uses all the same building blocks that we been using for days. So this program is set up as follows: Get a string from the user that's old hat now. Now what? Iterate over the string from I up to the length, okay so we just did that. This code is the same. So the only new magic here are these four lines. Now what is the saying in English? If the ith character in S is greater than or equal to lower case A and the ith character in S is less than or equal to the value of the lower case Z, what do you think the next line of code is doing? It's just capitalizing it. Well mathematically and I won't dwell so much on the arithmetic here because it's the same stuff as a week ago but notice do you capitalize something, well let's just do the math quickly for one example. Little A is 97. Right I've promised this would be useful so little A is 97. Big A is 65 so not matter what I'm doing I'm going to be subtracting because I gotta take big numbers and make them smaller if I'm going to go to like 97 and above to 65 and above. So I have the value of S bracket I here then I do subtraction. Well what do I subtract? Well technically I just need to subtract 65 but if I put 65 in here, kind of a bad thing. It's a magic number like Y 65. Well why don't we just go ahead and do this. The difference that we want to subtract off is always going to be this, A minus A, little A minus big A. So let's just subtract things off a little more dynamically. And again the astute can say why are you computing A minus A again and again and again. It turns out compilers can be smart and if they realize you're doing some arithmetic that's never going to change, sometimes the compiler can optimize that for you, but for today we offer it just for clarity. So if we go ahead and compile this, capitalize dot C, damn again dash L dash CS50 but again these errors should no longer be intimidating. Let's go ahead and run A dot out and capitalize. Hello there exclamation point and there I preserved my space. It preserved my exclamation point so I actually did get this right. So let's lay the stage now for where we're going with this. Two quick comments- one by far if you're feeling like you're not among those with books in hand or you just like learning stuff on line, these are the two places to start because it covers the stuff we've been looking at. But let's now pull back a layer that I've been waving my hand at for a week. You have for any program you've been writing used int, main, and then int argC comma Charstar argv. Well Charstar is strength. So that's the synonym for now. So it appears that it may all of this time has been allowed to take in two inputs ints and also a string. Alright so what does that actually mean? Well it means that just like I can run GCC and then Fu dot C I can apparently pass input to -- you gotta say something sometimes. I can apparently pass to programs like GCC by just writing those arguments on the command line. So it's not quite an argument in the sense of a function but this is a very different context. This is my so-called blinking prompt. I can clearly -- been doing things like dash 0 Fu and then down here I've been saying things like dash L CS50 so there's many different labels the world has slapped on these kinds of words, switches, lags, command line, arguments. We'll typically call them command line arguments but you've used these before any time you've typed commands. Nano takes the command line argument. It gives the command line argument that nano is supposed to take, the name of the file. So we have this ability clearly in Linux, MAC OS and other context to. So how do we get at that information? Well in argv 1 see a very simple example. Notice here that in this function I first, in this main function I print a new line then I do this. For I is 0 on up to argC. So take a guess, what does argC maybe represent? Argument count, argC it's a convention. I could have called it X and Y but the world's kind of standardized on these two nicknames. ArgC I argument count. So if I want to iterate over all of the words that the user typed at the command prompt, I'm going to iterate from 0 up to argC. What is inside of argv? Argv apparently all the time has been an array because of the bracketed notation. What is inside that array are not just characters. It turns out that inside an array you also put other arrays. You can put strings themselves. So you're really taking this -- it's like a 2-dimensional array. So argv in this case is an array of not Chars but of Charstars aka strings. So what does that mean? Well let's compile this and try to infer what's going on. GCC argv 1 dot C okay good stuff happens. Okay so A dot out enter okay, not such good stuff. Alright so how about Fu bar bas. So apparently my program has the capacity to spit out anything I type. Let me just get a little familiar like A dot out Fu dot C. So let's just think of this as burning nano. So it looks like also inside of argv is not just the words after the program you ran but what else? The program itself which is useful, so in short argv all of the words the user has typed at the command prompt including the program or the program name itself from 0 on up. So all this program does notice is this. It iterates from 0 to argC okay pretty simple. It's just integer incrementation and then what am I printing well percent S is a new format code to here today so this means put a string here not a decimal, not a float put a string here. Give me the ith word inside of argv the ith argument, inside of argv. We can get more creative still if I open up argv 2 dot C this looks a little fancier and we won't dwell so much on the syntax because again we have seen things like this. Here's a 4 loop iterating over I. Here's another 4 loop iterating over J but notice what this program does if I just reveal the magic here. Argv 2 dot C so RA dot out, oh interesting. So I'm just getting a littler aesthetically interesting Fu bar bas. So here I'm iterating not only over each of the words the user typed but also over each of the characters within. So I hinted a moment ago and we'll see this in more detail over time but argv is just a 2-dimensional array. An array of strings but strings are arrays of Chars so that's an array of an array of Chars so how am I doing this? Well I iterate over the arguments from 0 to argC and then oh here's something familiar. Again I've been just taking babysteps over the code today. Here's J is 0, N is initialized to the string length of ith argument okay. Iterate from J to that length, oh this is interesting if argv is in fact a 2-dimensional array, an array of strings aka an array -- an array of Chars it turns out you can put brackets back to back if you know it's this sort of 2-dimensional array. So argv bracket I right here, this gives me the ith word. What does argv bracket I bracket J give me, the J character in the ith word. So it's actually fairly straightforward. Again some new syntax but some fairly basic building blocks. So here's the canonical list for now of functions you can use that will be used not so much for problem set 1. For the most part you've had already the basic building blocks for problem set 1 as of last weekend and this Monday. But for now before we start looking at the code here's a quick reminder of what functions are in CS50's library. The last one of which is this latest one get string returns a string. But remember a string can be manipulated with this bracket notation as we've been doing. Now for the astute 2 at the top I disclaim memory leaks. So CS50's library is buggy. It intentionally -- we allow ourselves to indulge in what's called the memory leak whereby we are actually allocating a whole bunch of RAM for you and we never ask you to give it back. So realize that we'll have a lot of interesting opportunity to discuss that but where are we going with this and why introduce this at all? Well clearly we got to arrays today and that's kind of a juicy new feature but we can do this in a more interesting context such as cryptography. So we introduced Monday with Ralphie. We had that expression be sure to drink your Ovaltine, which I is repeated here using ROT 13, rotate 13, just rotate all the letters 13 places and that's the nonsense you get out but it was a specific instance of something we called a Caesar cipher, a cipher being an algorithm or program that scrambles information. So this is very similar in spirit to some very real world things. This is the German enigma machine. You can read up on this on Wikipedia. It's covered in many movies and books certain over the years. We've seen real-world incarnations of cryptography. This is essentially a really fancy typewriter with really special really secret gears and levers that when you type out a message what gets spit out is something that looks more in spirit like this. But the Germans were smarter than just rotating all the letters in the German alphabet by 13 places. That's why the Americans and allies were so intent on stealing boxes like this so that they could figure out what those messages were. But what we'll look at this coming week is this notion of cryptography and this sort of a fancy depiction that I'll just wave my hand at just so we can look at this guy here, Caesar supposedly. Naive though this algorithm may seem all these years later, use simple cryptography to send messages to and from his generals in the field. And they did so by way of writing them down on a piece of paper and then rotating all of the letters as the story goes by some number of places, so that A became D and B became E and so forth so he and his generals had a secret that they whispered together before they went off out to battle and such and he said 13 or something like that. Right now it's a fairly simple cipher and even I have sort of trouble imaging that there weren't still even back then before computers, really smart people who maybe by trial and error might have figured out how these messages were encrypted. But for us it offers a really interesting opportunity, because just as I've written -- just as this figure presents these letters from left to right in a grid, it suggests that just by using a little bit of arithmetic can we rotate letters. An in the event that we go too far off, if we try adding 13 to the letter Z we don't want to fall off into no-man's land. We want to wrap around back to the letter A and what simple building block have we seen whereby we can wrap around. >> [Inaudible background discussion] >> Yeah so the modulo operator. So that's where we're going. Now all this time throughout today's lecture has Homer Simpson been busy at work with his little internet company. I thought we would conclude with this 20 second clip of how his internet business turned out. >> Oh they have the internet on computers now. >> Bill Gates is here. >> Bill Gates the millionaire computer nerd Bill Gates? Oh my God. Oh my God. Get on a site Marge. I don't want this to look like a 2-bit operation. [Sound effects] >> Mr. Simpson. >> You don't look rich. >> Don't let the haircut fool you. I'm exceedingly wealthy. >> Make small chat Marge. >> Your internet ad was brought to my attention but I can't figure out what if anything Compu Global Hypermagenet does. So rather than risk competing with you, I've decided simply to buy you out. >> I put my heart and soul into this business and now it's finally paying off. We're rich. We're richer than astronauts. >> Homer be quiet. You'll cramp the deal. >> I reluctantly accept your proposal. >> Well everyone always does. >> Buy him out boys. [Sound effects] >> Hey what the hell's going on? >> Well I could get rich by writing a lot of checks. [Laughter] >> Have a good weekend we'll see you Monday. ==== Transcribed by Automatic Sync Technologies ====