LongCut logo

CS50x 2026 - Lecture 1 - C

By CS50

Summary

Topics Covered

  • The Compiler: Translating Human Code to Machine Language
  • Input Validation: Preventing Invalid Values with Error Checking
  • Variable Declaration vs. Reuse in C

Full Transcript

All right, this is CS 50, and this is week one, our second week together, and you'll recall that last week, week zero, we focused on scratch ultimately this graphical programming language by which you can drag and drop puzzle pieces that interlock together only if it makes logical sense to do so.

And many of you had actually probably played with that in like middle school or even prior at some point, but for our purposes, the goals of Scratch were to give us sort of a mental model for some fundamental constructs that we're going to see again and again today in C in a few weeks in Python.

and even thereafter, and those include things like functions and return variables and arguments and variables and loops and conditionals and more.

And so even if today feels like a bit of a fire hose such as that pictured here, appreciate that a lot of today's ideas are exactly the same as last week's ideas.

It's just that the syntax is going to change.

It's going to look a little different.

It's going to look a little scarier.

It's going to be harder to sort of memorize except with practice will come that muscle memory, but the ideas ultimately are going to be the same.

And indeed this is, if unfamiliar, MIT down the road has a tradition of hacks whereby students once a year do something fairly crazy and at this point they happen to connect an actual working uh drinking fountain to an actual fire hydrant, and the sign there, very pixelated, says Getting an education from MIT is like trying to drink from a fire hose.

And that's indeed how computer science, how programming, how CS 50 will sometimes feel, but realize that what's going to be ultimately most important is not where you.

Uh, feel you are day after day, but where 3 months from now you feel that you are relative to last week alone, so-called week zero.

So let's look back at what week zero looked like.

It looked a little something like this the simplest of programs by which we get get that cat to say Hello world.

Today that same code is going to start to look a little like this, which was a glimpse we gave you last week.

But this time I've deliberately color coded it to try to send the message that we're in scratch.

We had this yellowish puzzle piece that sort of kicked things off.

That didn't really do anything itself, but it got the program started, whereas the real work was done in purple here.

Same is going to be true today, whereby I'm going to wave my hands for a little bit of time at this yellowish code on the screen, but what's really going to have the most effect is this same purple line here and the white text within.

And we'll break down what all of these lines mean over the next couple of weeks, but sometimes we'll wave our hand at details if we feel it's a little unnecessary at this point in the story.

And in fact, let me get rid of the color coding for now and we'll see that this is the kind.

Of code in a language called C we're going to start playing with and using today and for the next several weeks.

And indeed it's representative of what we're going to generally call source code.

So source code is what programmers write.

It's what you write.

It's what you wrote, albeit by dragging and dropping puzzle pieces.

This week onward you're going to start using your keyboard all the more and you're going to write source code.

So this is code that we humans can understand with some training and with some practice, but of course per last week what language do computers ultimately understand?

Only so binary zeros and ones and so you and I, yes, can write code starting today in a form that looks a little something like this, which admittedly might look a little arcane and cryptic, but it's certainly better than a whole bunch of zeros and ones.

But we're going to write in source code, but the machines that we write code for ultimately only understand these here zeros and ones, which may very well say hello world, but we're going to call this moving forward machine code.

So machine code is what the the.

understand only the zeros and ones.

Source code is what you and I understand and actually write, so it stands to reason that we're going to have to somehow translate one to the other from source code to machine code.

And I alluded to this ever so briefly last week, but we're going to use the same mental model whereby the source code we write might be the input to some problem.

The output we want therefrom is going to be the machine code.

So what we're going to equip you with today inside of this proverbial black.

Box is a special piece of software that takes source code as input, produces machine code as output, and that type of program is called a compiler, and there's bunches of different compilers in the world.

We're going to have you use one of the most popular ones, but it's simply a piece of software that someone else wrote that converts one language to another.

Source code, for instance, in a language called C to machine code, the zeros and ones that our Macs PCs, phones, and other devices actually understand.

So where are we going to do this and how are we going to do this?

So I promised last week that we'd introduce you to this year tool, which I used briefly at the very start of class to whip up that chatbot.

We're going to use it though not for Python this week, but indeed for a different language C.

And indeed this tool, Visual Studio Code or VS code for short, is super popular in industry.

This is what real programmers, so to speak, are using all of the time nowadays.

There's absolutely alternatives.

If some of you have programmed before, you might have used or experienced different tools, but this is a very.

Common tool that you'll see even after CS 50, and in fact it's something that ultimately you can install for free on your own Macs and PCs so that by the end of the course you're completely independent of CS 50 and any CS50 related tools, but what we have done for the very start of the class is essentially provided you with a cloud-based version of this tool.

So all you need is a web browser on any Mac or PC or the like, so that everything's pre-installed for you, pre-configured for you, and you don't have to deal with the stupid technical.

Support headaches at the start of the term because it should just work.

But by the end of the term, once you're a little more comfortable with technology and with code in particular, you can absolutely offboard yourself from this tool, install it, download it on your own Mac and PC, and have pretty much the exact same environment completely under your control.

So starting today, you're going to see an interface that looks quite like this quite often, and we use this same interface last week ever so briefly.

Moving forward, here's where we're going to write code at top right is where one or more codes.

Tabs are going to appear similar to any tabbed environment that you might use.

Here, for instance, is just a screenshot of the first file we'll create today called hello.c.

The reason it's called hello.c is because it's in a language called C, as we soon shall see, no pun intended.

Meanwhile, the code here happens to be color coded, not quite in the same way as you saw before, because I manually made it look more like scratch blocks.

But among the features that VS code and other programming environments provide.

Something called syntax highlighting whereby you don't worry about or even think about these colors, but as you write out code in a recognized language, tools like VS code will just color code different parts of your code for you just to make different features jump out, and we'll see what those features are over the course of today.

But you'll also spend a good amount of time, as I briefly did last week, down here in the bottom right of your screen, the so-called terminal window, which is going to be where you run commands for compiling code and write.

In code.

And in fact, as we'll see today, you're going to start using your mouse and clicking a little bit less.

You're going to start using your keyboard and typing a bit more.

And ultimately, even though if that first that might feel like a step backwards to sort of not use something that's so user friendly, the reality is most every programmer tends to find themselves ultimately much more productive, much more powerful, using the keyboard more often, more quickly than, say, a traditional mouse or trackpad would allow.

Meanwhile, we'll see some somewhat familiar features.

Here at left like this is where you'll see the files and folders that we will create over time.

At far left here is going to be an activity bar, which is essentially a modern form of a menu via which you can open and close things and access other features.

For my purposes, I'll generally hide this part here.

I'll generally hide this part here so that when we're together we're focusing almost entirely on code and commands, but I'm just typing some quick keyboard shortcuts to simplify my own user interface in that way.

So with all that said, just some terminology.

So this The whole collective environment that I'm describing here is generally what's known as a graphical user interface.

Why?

Well, it's an interface for users that's graphical in nature with icons and buttons and the like.

Shorthand notation for this is GUIY GUI for short.

But within this graphical user interface, as promised, is going to be that terminal window at bottom right where I promised we would be typing most of our commands.

And just to give you a bit more jargon in computing, that's generally known as a command line interface, or CLI.

For short, whereby you're typing commands into that interface instead, and the world of computing software is essentially divided into GUIs and CLIs and sometimes a piece of software might have one of each as well.

But without further ado, why don't we go ahead and focus entirely first on this here program, which I dare say is the simplest program you can write in a language like C and see how we can actually compile and run it together.

So I'm going to go over to VS code here.

I've hidden my File Explorer with all the icons and I've hidden my activity bar so that only do I have room for tabs of code and the command prompt at the bottom.

I'm calling this a command prompt because it's at this dollar sign where I'm going to run some of my commands, and it's a dollar signed by convention.

It has nothing to do with currency.

It's just a computing convention.

Some systems will use a carrot symbol.

Some systems will use a greater than symbol rather, or something else, but it just means type your commands here.

The first such.

And I'm going to type is this code hello.c with a single space in between.

code hello.c with a single space in between.

I've not used any spaces in the name of the file.

I've not capitalized any aspect of the file just because this is convention, unlike your Mac or PC, where you might be in the habit of naming files with spaces and capitalization.

Generally you'll make your life simpler by just using lowercase and no spaces at all.

As soon as I hit enter, what you'll see is that a brand new tab appears called hello.c with a cursor blinking on online.

I and this is essentially VS code waiting for me now to type the first line of my code.

Notice though that the command is complete thereby whereby I have another cursor here which I'd give if I click in the terminal window and give foreground to it, my cursor might blink there instead.

That just means I can type another command when I am ready.

So let's go ahead and whip up this code, and I've done this many times, so I can type it fairly quickly, but in this tab I'm going to do include standardio.h,

so to speak, in main void.

Then inside of so-called curly braces indenting therein by 4 spaces, I'm going to say print F quote unquote hello world backslash and close semicolon, and voila, I've written my first program in C.

In a class like this, no need to write down each and every line of code that I write.

In fact, on the course's website will be copies of everything that we've done as well as excerpts therefrom in the course's notes, but you're welcome but not expected to follow along in real time with what I am typing here.

So that's it.

Like I've written my very first program and see if I had done this on an actual Mac or PC without a command line interface, I might have a new icon on my desktop, so to speak, called Hello, and ideally I could double click on that or tap on it and run the program, but because I'm in this specific programming environment that has a mix of a GUI and a CLI.

I actually need to click down in my terminal window, and I need to now compile this program first because at this point in time it exists only as source code.

So to do this, I'm going to compile my code by very aptly saying make space hello, and I'm pronouncing the space, but literally I hit the space bar.

Make space hello, is it sort of implies some.

will make a program called hello.

Notice I have not said hello.c again because the compiler, let's call it Make for now, even though that's a bit of a white lie, is going to infer that if I want to make a program called hello, it's going to automatically look for a file called hello.c in this case, so a bit of magic.

Enter.

And remarkably, any time you don't see any output at a command like this, that's probably a good thing.

Generally speaking, when you see output when compiling your code, you have done something wrong or in this case I might have done something wrong, but no output is good because what I can now do, and this is a bit cryptic, I can run this program not by double clicking or tapping anywhere, but by doing slash hello with no spaces.

And this is a bit weird, but what the slash means is that after having just made a program called hello, that program's going to end up in my current folder.

It's somewhere in the cloud, yes, more on that in a bit, but the program called hello is just somewhere in my current folder.

When I say slash, that's like saying go into the current folder and run the program therein called hello specifically.

Now, as I often do, I'll cross my fingers, hope that I didn't mess this up in any way, and I should see in a second.

Hello world indeed printed onto the screen.

And so just to recap those in commands, one, I ran code hello.c,

which is a VS code specific thing.

Code short for VS code, just creates a new file called hello.c and then I'm on my way with my own keyboard.

Make hello compiles that source code into machine.

Code thereby creating a new file called hello and to run that program hello, I type this strange command.

hello.

But this is a paradigm no matter what you call your programs, we're going to see again and again and again.

So even if you've not done something quite like this, it will very quickly get familiar.

Yes, questions.

How, when you say make hello, how like, how does, how do you, how does the computer know like what part of the code to what part of the code is ascribed to hello?

Good question.

When I say make hello, how does the computer know what part of the code is ascribed to this program, hello?

It literally is going to take the entire contents of hello.c and turn them somehow into a program.

of hello.c and turn them somehow into a program.

And does it have to be like hello?

Does it have to be named hello?

No, I could have called it goodbye or anything more myfirstprogram doc, anything at all, so long as I change these words here accordingly.

But it has to be like it needs to be like from the same thing like it.

Yes.

Exactly.

If you change the name there, you need to change your commands accordingly.

Other questions on these here, steps.

No.

All right, so let's tease apart what it is we just did and like why this code works in the way that it does.

Well, to recap, in Scratch, we had a program like this.

When the green flag was clicked, we wanted to say hello world onto the screen.

The code that corresponds to that is roughly here and indeed notice that the yellowish or orangeish code lines up with the when green flag clicked, the purple code here lines up with the same block, and the white code inside of here roughly corresponds to what was in the white oval that we kept using again and again last week.

So let's do more of a one.

One correspondence and these slides are deliberately designed to give you again that sort of mental model of taking same ideas from last week and just changing the syntax this week onwards.

So when we have a function like this thing here, and recall that a function is just an action or verb, it sort of accomplishes a small piece of work in code in C specifically, you're going to type, of course not a purple puzzle piece, but you're going to say the word print while more technically print F, where the F as we'll soon see, means format the printed.

Output because this is more powerful than just printing some raw text alone, then you can have parentheses open and closed left and right and notice that it's no accident that MIT MIT chose an oval for their input to functions because it roughly looks like the start of a parenthesis and parenthesis on left and right.

Meanwhile, what goes inside of the parentheses in the corresponding C code, well, at the end of the day, minimally hello, comma world because that's literally what we want to print to the screen.

But in C, unlike in Scratch.

A bit of overhead, a bit of additional syntax that you just got to deal with to make clear to the computer what you want to print.

In particular, you're going to have to surround everything you want to print with double quotes to make clear that hello is not some special function or variable or something else.

It's Hello world is the English phrase that you want to print.

So double quote here, double quote there means He's the beginning and the end of what I want to print.

You're also curiously going to put a backslash n.

In most cases, at the end of the word or words you want to print, we'll take that away in a moment and see what it does and then lastly and perhaps most annoyingly in programming circles, you have to finish your thought with a semicolon, much like in English you would finish most sentences with a period instead.

And the thing the thing about programming is with C in particular, if you mess up almost any of these details I just rattled off, something's going to go wrong.

And so you're in good company.

The very first program you try to write or try to compile, odds are it might not work correctly because you'll develop over time the muscle memory for spotting all of these seemingly minor and actually minor details but that do matter to the computer.

All right, so if you're familiar, of course, with the notation in like mathematics of functions like a function in code, it's really the same idea as a function in math whereby the function F takes some input, for instance X, and generally produces some output.

So if you're coming more from that background, realize that what we're really doing here is roughly the same.

But in code, recall that we can have different types of output.

So if this is our grand mental model and say we've got a function.

As inside of this black box that takes arguments, that is to say is it's inputs, it can sometimes have side effects and recall that side effects are often visual things that happen as a result.

They just play on the screen, maybe it comes out of the speaker.

It's some thing generally ephemeral that just happens, but it's.

Not necessarily useful in the same way as another type of function that we'll return to in just a bit, but last week recall that we got the cat with the speech bubble to manifest on the screen and say hello world in that speech bubble when the input was hello world and the corresponding function was instead say.

So let's see if we can't now tease apart what the code we wrote is actually doing for us bit by bit.

So let me go back to VS code here and let me propose to break this in a little way.

Let me delete the backslash N, if only because at first glance, who knows or cares what that's doing.

Let's just get rid of it if we don't understand it.

I could now go back down to my terminal window and I could do hello enter again, but there's seemingly no change.

Which is good, doesn't seem like I broke it, but I've kind of misled you here why?

Why did nothing seem to change?

I didn't recompile it, so recall that the compiler converts source code to machine code, but I already did that a couple of minutes ago.

If I've changed the source code, it stands to reason that I need to recompile the code to actually see the effects of that.

So let me do that again.

Make hello E.

Nothing seems to have gone wrong, but let me now do hello Enter.

And it's subtle now and in fact let me go ahead and zoom in, it's really just an aesthetic bug insofar as functionally the program is still technically printing Hello world, but what's seemingly wrong or put another way, what did the backslash and apparently do?

Yeah.

Yeah, so it's somehow giving me a new line, and that's essentially what the backslash N denotes is give me a new line there.

And why was I doing that?

Well, really just for the aesthetics.

Like if this dollar sign represents my prompt where I type commands, if anything, it just looks kind of stupid that I finished a program over here and then the prompt is on the same line.

It just looks wrong even though you could sort of argue that was my intent, even though in this case it wasn't.

So what would the alternative be?

Well, what you're seeing here is what's actually generally known as an escape sequence which.

are sort of special sequences of symbols like backslash and N in this case that do a little something unusual.

And here's just a non-exhaustive list of some you'll encounter in the real world and including in CS 50 backslash N moves you to a new line.

Backslash R is a so-called carriage return if you've ever seen or used an old school typewriter, this refers to the process of bringing the typing head back to the left end, so it sort of moves the cursor horizontally as opposed to vertically.

This one's interesting.

backslash double quote.

Why does there exist this pattern?

Backslash double quote, yeah.

Exactly.

So recall that phrase we tried to type, uh, print out like hello, comma world.

If for some reason you don't want to say hello world, but you wanted to say some or like sort of snarkily like hello world or something like that, well, you can't put a quote, a quote, a quote at a quote and expect the computer to know which quote corresponds to what.

It's just arguably ambiguous.

So if inside of double quotes you actually want to print actual double quotes.

This is an escape sequence that tells the computer this is not some quote delineating where my thought begins and ends.

This is literally a double quote and we'll see other situations in which a single quote or apostrophe is the same.

We'll see crazy situations in which you want to print a backslash, but backslash already has some special meaning, so there's solutions to all of these problems. But let's not get too far into the weeds here.

But let me go back to the code and propose what the alternative.

Otherwise might have been.

If I didn't know about backslashn, my instinct to move the cursor to the next line might have been literally to just like hit enter or do something like this, like move the double quote, move the parenthesis, move the semicolon onto the next line.

But this should start to rub you the wrong way.

And indeed this violates a principle of most programming languages and that most programming languages are line based.

You sort of start and finish your thought.

Ideally on the same line, and this runs afoul of that.

And 2, even if you're seeing code for the first time, assume that this just looks stupid as well to sort of move part of your thought to the next line.

It just looks a little sloppy and it is.

So C and many other languages, Python among them, solve this by giving you these so-called escape sequences.

So if you want a new line there, you do backslash N and you will get your new line there.

Now that's a bit of an Overstatement what I said in that sometimes lines of code will be so long that they do wrap onto multiple lines, but generally that's a convention that we're going to try to avoid.

All right, what else could go wrong?

Well, let's do this.

Let me go ahead and clear my terminal window, which I can do by hitting control L, or I can literally type clear and I'm going to frequently do this just to keep the screen clear, even though it has no functional impact.

It's just an aesthetic.

Let me do something else.

suppose I forgot to finish my thought and I omitted the semicolon, but otherwise the code is perfect.

Let me do make hello now.

Enter.

Now we're going to see some output that's a little more arcane.

Let me go ahead and scroll back up here to make clear that what's just happened is Iran make hello, but I didn't get back to another prompt.

I don't see immediately a dollar sign because there's an error message here that is almost as long as the code I tried to write.

Not to worry.

Let's see.

Here is the name of the file in which the problem exists, stands to reason that it's in hello.c.

Here is the line number in which the problem seems to exist, line 5, and that's helpful because it lines up with this.

And then if you're you care to.

This is the 29th character.

So if I count from left to right around 29, something is wrong, something is missing.

So it's a pretty decent error message.

In fact, it even says expected semicolon after expression.

There's a little green carrot symbol pointing me at the mistake.

So this is again this is another value of the compiler.

Not only does it know how to convert source code to machine code, it's also pretty good at finding mistakes in your code and trying to draw your attention to them.

So how do I fix this?

Well, assuming you've understood the error message at this.

Point.

Well, you just go back in, add the semicolon, let me go back down to my terminal window.

I'm gonna clear it just to clean up the mess.

Let me rerun make hello, and now we are back in business and indeed if I do slash hello, I've got hello world back on the screen.

Well, let's make one other mistake.

Suppose that I forgot, as you sometimes will, to include this line at the top, which will make more sense next week.

But for now, let's just omit it and dive right into the code.

You would think this is enough, just printing out Hello world.

Well, here, let me go back down to my terminal window.

Let me do make hello again now, and I'm going to get a whole different error message instead.

So now the problem is still with hello.c.

that makes sense.

Line 3, OK, so somewhere in there print F is suddenly the problem even though the semicolon is back and the backslash N is back.

So let's keep reading error call to undeclared library function print F with type.

And and then this is a whole mouthful.

So here is an example of an error message that unless you're sort of conditioned to know what this means and you've seen it before, it's quite more cryptic and unclear like what the solution to the problem is, especially when the rest of your code is truly correct.

I've just forgotten something stupid, but how can I sort of think about this problem?

Well, it turns out.

That another feature of C is that it comes with a bunch of header files, a bunch of files whose names don't end in doc but end in H, and these so-called header files, which end inh contain code that other people wrote that you can use in your own programs. So for instance, in this particular case, a header file is giving us access to what's more generally.

In computing called a library, a library is code someone else wrote that you can use, and I actually used the library last week when I did that import line and mentioned OpenAI, the company, I was actually using a library from that company that I automatically downloaded and installed into my programming environment in advance of class because I don't know how to implement a chatbot without standing on their shoulders and

using a lot of the code they themselves wrote.

Same idea here, even though printF is a feature of C, if you want to use it, you have to include that library by telling your program to include the header file.

That defines that function and you only know this by being taught it or looking it up in a book or a reference, but in this case I wanted to use a header file called Stanio.h STDio.h.

It is not studio.h.

This is a very common bug online if you find yourself typing studio.

Hypo, it's standardio.h and in that file then is defined the printer function.

it's standardio.h and in that file then is defined the printer function.

So if I go back to my code here, the solution to this problem truly is to just undo the deletion I made a moment ago because what line one is now doing for me is it's telling the compiler, oh by the way, I didn't write all of the code that I'm about to use.

Please include the definition of printF from this other file called standardio.h.

And again, you'd only know this by looking it up in a reference, attending a lecture or something like that.

It's not obvious otherwise, but these are the kinds of things you very quickly look up.

So where do you look them up?

Well, it turns out the ecosystem of C.

Has hundreds of books you can buy or download.

Many, many, many websites among them is one of CS 50's own.

And in fact the conventional way to look stuff up for the programming language called C is to look at the official manual pages or man pages for sure, for the C language.

Unfortunately, many of them were written decades ago when they were certainly written by fairly advanced programmers and not for a broad audience.

And so what we have done is imported all of that freely available documentation.

Uh, hosted it at our own URL here, manual.cs50.O,

manual.cs50.O,

and we've essentially simplified it for those less comfortable, those of you who might be less familiar with, less comfortable with technology, and really for most people who aren't used to reading manual pages, it's just useful to have it written in teaching assistant-like language instead.

So for For instance, if you go to a URL like this, you'll see CS 50's documentation for this official library Standardio.h that comes with C itself.

library Standardio.h that comes with C itself.

If you get a URL like this, you can look up the documentation for printF itself specifically.

So for instance, let me go ahead and just give you a teaser for this.

If I were to do the same.

On my own computer, I might see the CS 50 manual pages here and you'll see header file by header file a bunch of frequently used functions in CS 50.

We've also filtered the list down from a massive list to a much shorter list so that you can sort of see what's most likely useful to you.

If you go to a specific page like Standardio.H,

you'll see for instance here just over a half dozen functions that we won't touch on today beyond print def, but that we'll see in the class over time that does useful stuff for.

For instance print prints to the screen and we'll see other functions for opening files, closing files, and the like because all of that's related to standard IO input and output.

If I go to a specific man page for this header file, you'll see the standard formatting for these pages.

So here's the name of the function printF, and it prints to the screen.

You'll see a synopsis, and this indeed indicates we're in less comfortable mode.

If you want to see the original, more arcane documentation, just uncheck that.

And you'll see the original official documentation, but you'll see a mention of like what header file this function is defined in so that you know what file to use in your own code.

You'll see a so-called prototype, which is just the first line of code from that function.

More on that in just a little bit.

You'll see an English description.

You'll see example code.

Long story short, this is the authoritative answer.

And even though you have access in this class, to the virtual rubber duck at CS50.AI and other forms of it that you'll soon see.

You should also have the tendency and the instinct moving forward to check the official documentation, and all of today's AIs are trained on things like the official documentation.

So that's the source material that any of these AI, the ducks the duck among them are actually relying on.

But what we're also going to see is that besides these official functions, there's some that CS 50 itself has invented.

We use these really as training wheels for just the first few weeks of the course, and then we take these training wheels off, but the reality is in a language like C, certain stuff is just really hard or annoying to do.

Certainly if you're learning how to program for the very first time, or at least you are new to C, we'll eventually show you how to do it that way.

But even if you just want to get input from the user like a string of text or a number of some.

It's generally not that easy to do and see, at least in these early days.

So for instance, at this URL here you can see documentation for CS 50's own library and CS 50's own header file CS50.H,

and you'll see such functions in the documentation as these get string, get in, get char, and a bunch of others as well, and we'll touch on those this week, but it will ultimately be a way of just getting useful work done quickly by standing on our shoulders and actually.

Uh, using functions we wrote to then solve problems of interest to you.

So let's focus, for instance, on one of these first.

Get string.

A string in programming speak means text, zero or more characters of text like H E L L O W O R L D.

That is a string of text in computer speak and it's obviously not a number like 50, it's actual text that you would type on the keyboard.

We'll see then what other things we want to get, but with this.

this function, we can start to replicate another program that we implemented pretty quickly last week in Scratch.

So recall that in Scratch this one was a little more interactive.

I used another blue puzzle piece ask to actually get input from the user and recall that unlike the printF function today and the same block last week, this time we still have the same input output model, but if we pass an arguments to a function that we're about to see.

You can get back not just a side effect sometimes but a return value like a useful reusable value like the person's name, as we'll soon see.

All right, so let's actually do this.

If in scratch the equivalent was asking the user what's your name, asking them that, and then waiting for an answer that we can store in a variable, let me propose that in C side by side it's going to look a little something like this.

Instead, at left we have the scratch block, the ask function.

Here is the argument there too, and then it and wait just means it's going to wait till the user finishes typing.

If I want to translate this to see now today moving forward, well, it looks a little something like this.

The closest analog in C, thanks to CS 50's library is going to be a function called get string.

So there's no C function called.

Ask and we deliberately named this function get string just to make super clear what it is you are getting a string of text in this case, and we've got the parentheses ready to go indicative of this white oval for user input.

If I want to prompt the user with that same phrase, what's your name?

Well, I can just put it inside of those parentheses.

But what next do I need to add around my user input?

Yeah, I need the quotation marks just to make clear that these aren't special individual words.

This is a whole phrase that I want to be displayed to the user, so I'm going to indeed put double quotes around everything, and this is just an aesthetic.

I don't in this case want to bother moving the cursor to the next line.

Like I want the user to see the question and I want the cursor to just stay there blinking, waiting for their prompt, but I don't want the cursor to be right next to the question mark.

So I'm deliberately just leaving a single white space there just to kind of scooch it over a bit so it looks a little prettier, at least to my eye.

Now we're not done yet.

Because we need to do something with this value.

The get string function, as we'll soon see, is going to prompt the user for me to type something in like my name, but where do I want to put that?

Well, MIT has the answer put in a variable called answer, and you can't rename that in scratch.

It's just defined as answer.

But in C, what I'm going to need to do is something like this.

If you want to keep return values around from a function, you literally use an equal sign.

And then to the left of it you put the name of the variable into which you want to put that return value.

So in mathematics we would use X, Y, and Z as our variables.

Again in code, as in scratch, you can name your variables anything you want.

By convention they should usually be lowercase.

They should not have spaces therein, similar to file names, but this is a pretty good analog now of what's going on collectively.

Here, but C is a little more precise.

You can't just give the variable a name.

You need to tell C or really the compiler, what type of value you want to put in this variable.

So if it's a string of text, you put string.

If it's a number, you're going to put something else.

But for now it's a string per the function's name it's going to give me a string.

Now we're so close to finishing this comparison.

There's one detail missing.

What's still missing from the code here?

Yeah, yeah, so we have to finish the thought lastly with a semicolon.

So if you're getting the sort of the point already, like this is one of the reasons why we start with scratch, you sort of you get the intuition pretty quickly and even though nothing on the right hand side is particularly hard, there's just all these stupid little details that you have to ingrain in yourself over time.

In this case, for C, but for many programming languages we're going to see the similar paradigm.

But among the goals of the course too are to show you how ultimately languages have been evolving.

And so one of the things we'll see in Python in a few weeks' time that some of this syntax actually goes away because over time humans.

Gotten annoyed at older languages like this.

Like why the heck do I have to keep putting a semicolon when it's clear that I'm at the end of the line?

So we'll see among languages like Python we can get rid of some of these same features.

But for now it's just a matter of remembering what goes where.

All right, so let's go ahead now.

And take that same idea of converting Scratch to see and actually do something with this code.

Let me go back to VS code here.

I'm going to keep my file name the same, but what you'll see on CS50's website is that we'll add version numbers to each of the examples that I'm typing out so you can actually see the progression of these programs, even though we're not changing the name.

And what I'm going to go ahead and do here, for instance, in hello.c this time.

in hello.c this time.

Is the following.

I'm going to go ahead and first get rid of the single Hello world.

I'm going to go up here and include this time CS 50.

H, so not one but two header files, and then inside of my curly braces inside the so-called main function, as we'll soon call it, I'm going to go ahead and do this exactly the same line of code as on the screen before.

I'm going to get a string.

Prompting the user for what's your name?

question mark space close semicolon, and as an aside, this will will soon see print on the screen.

What's your name?

So that implies that the get string function is actually using printF itself to print out that message.

I do not need to use printF to display that message on the screen because I read the documentation for CS 50's get string function and I just know that it is using printF for me to achieve that particular goal.

Now let me do something intuitive but not quite correct.

If I want to print out that answer so that the expression is going to be not hello world but hello David or hello Kelly, let me go ahead and say hello answer backslash and to move the cursor down as before, semicolon.

So this is not quite right, and even if you've never programmed before, you can perhaps see where this is erroneously going.

Let me remake the program because I've changed the source code and I need new machine code.

Nothing seems to be wrong aesthetic logic rather syntactically, but if I do now hello and hit enter, you'll see I'm being prompt.

What's your name?

So I'm going to go ahead and type in David and then hit enter.

But when I do, If you know where this is going, what am I going to see instead?

Hello answer and the computer's just doing literally what I told it to do.

I said, quote unquote, print out hello answer, but obviously that's not the goal that I have in mind.

So how do I actually work around that?

Well, what I really need to do is achieve the equivalent of this thing here, which we did by stacking blocks in scratch or nesting them, if you will, one inside of the other.

So I want to join the expression hello, comma space and that answer, and it turns out in C you can't do it quite like this.

Like there isn't an analog of the.

function at least that we'll see today.

So we have to do this a little bit differently.

We can do it though by maybe telling the computer, well go ahead and print out hello com space and then maybe we can give it like a placeholder to plug in the name once we know the name because when I'm writing my code I have no idea who's going to play this game, me or Kelly or someone else.

So what if we use special syntax to indicate where I want the person's name actually to go?

Let me propose that we now do this.

Instead of printing out hello hello answer, quote unquote, let's go ahead and start printing out something, and I got my parentheses ready to go and I did my semicolon in advance this time.

I want to somehow now say hello comma placeholder, and you would only know this by someone having told you or a reference online percent S is the placeholder for a string that you don't know when you're writing the code, but when someone else is running the code, it will be filled in.

And substituted for their input.

So hello cents is the closest we can get to this.

I still need those some other syntax.

I still, I do need those quotes on the left and the right just to be aesthetically pleasing.

I'm going to put a backslash N there at the end to move the cursor, but now I've left room in my parenthesis for one more thing, and you could perhaps guess where I'm going with this again, even if you've never programmed before, this is telling print F print out H E L L O comma space something.

What should I probably pass in to these parentheses as a second input so that PRF knows what that something is.

Yeah.

The variable name, so the variable in which I have the user's name, and indeed the convention is to put a comma after the quotes and then the name of the variable that has the value you want to be substituted for that placeholder.

Now notice there's a collision of syntax and grammar here.

The comma inside of the quotes is just an English thing.

Hello.

so and so.

The comma outside of the quotes is meaningful to see because it delineates which is the first input or argument to left and which now is the second, and we haven't seen this before in C up until now we've only been passing one input, but you can pass in 2 or 3 or 4.

Completely depends on what the function is designed to expect.

So let me put this all together now.

Let me go back to VS code.

Previously we were literally printing out answer, but I can change answer to percent S.

I can move my cursor outside of those quotes, comma answer, because that's the name I gave to that variable.

I can go back down to my terminal window and clear it just to reduce clutter.

Let me do make hello one more time.

Seems to work.

hello, E DAVID, and now hello David is printed.

OK, questions on any and all of that.

Mhm.

Good question.

Where is it pulling these header files from?

So what you are seeing here is a graphical user interface that's somewhere hosted in the cloud at cs50.dev, the URL I mentioned last week, and we're going to tease this apart in just a moment.

That software is running on a computer and that computer's got a hard drive.

or solid state drive like folders of storage, those files CS50.

H and Standard IO.h and many more are pre-installed on the server to which I have connected, and they're stored in a standard place so that the compiler in particular knows where to look for them.

And those are all things we did in advance for you, yeah.

and not create a new like a new line.

Why does the backslash N not create a new line?

So it is backslash N is essentially being printed here, which has the effect of pushing the dollar sign to the next line, otherwise the dollar sign would stay on that second to last line.

Other questions?

Good, uh, why is there no backslash N over here?

Good question.

My choice as the programmer.

I just wanted to see the sentence.

What's your name?

question mark and I wanted the user me to type my name immediately after it like this, but I didn't have to do it that way.

I just wanted to show you the difference.

Got you.

And then also like just generally when we're like doing like the what actually always write the like first four lines.

Should you always write the 1st 4?

Oh, these?

Yes, for today, trust me, do this, do this, do this, do this, and next week we'll understand even more what those lines do.

However, slight caveat only use CS 50.H if you're using one of our functions.

Clearly you don't need CS 50.H if you're just printing something out as in the first example.

Other questions?

dividing the first input and the second input.

I understand that the second input is what I typed as the user, but the first input does not really feel like input for me because that's the question that you ask.

Can you like.

Correct.

So to summarize the question on the right here, this input is effectively provided by the user.

This first input though is provided by me.

That's the way it is.

So these are both inputs because they're being provided as inputs to the function.

The origins of those inputs though are entirely up to what I'm trying to achieve.

The first one I know in advance, like I'm the programmer, I know I wanted to say hello someone.

The second input I don't know in advance, so I'm using a place I'm using a variable to store the value that I'm going to get when the get string function is used later on, but they're both inputs even though they're used in different ways.

Good question.

Any others?

Yeah, OK, so if we now have that done, well, let's just take a step back into the first question that was just asked about where are these files.

Let's take a look back at actually what it is we're actually using here.

So it turns out, even though most of you are using Mac OS or Windows, there's other operating systems out there in the world.

Phones have iOS, iPads have iPad OS, Android devices have Android.

Which is its own operating system.

The operating systems in the world are the pieces of software that really just do the most fundamental operations on a device like booting it up, shutting it down, sending something to a printer, displaying something on the screen, managing windows and icons and all of that sort of commodity stuff that is used by other people's software as well.

A very popular operating system in the programming world and in the world of servers in the cloud and on the internet at.

It's called Linux, and it's a descendant of something called Unix, which has been around for quite some time, and it's what many programmers, most programmers use depending on their environments insofar as Linux is very highly performance, like you can support thousands of millions of users on servers running an operating system like this.

It tends not to, but it can have a graphical user interface, which just means it can operate more quickly because it does.

Need all of these graphics that are really just for humans' benefits, not necessarily for web browsers and other devices, and Linux, insofar as it's usually used or often used as a command line interface, comes with a whole bunch of commands that you'll start to use and see over time.

Now I've used a bunch of commands already.

I've used code, which is a VS code thing.

I have used Make, which is for today's purposes our compiler, but that's a little white lie that we'll distill next week.

And then I've used hello, which is a command I essentially invented as soon as I created a program called Hello.

But there's a bunch of other ones as well.

For instance, if I want to list the files in my current folder, I can type LS and hit enter for short.

If I want to create a new folder, otherwise known as a directory, I can use MKDIR to make a directory.

If I want to remove a directory, I can use RM.

Director.

If I want to remove a file, I can use RM.

If I want to rename a file, I can use MV for move.

If I want to copy a file, CP, if I want to change directories, change into a folder, I can use CD.

Now these two just take a little bit of time and practice to memorize them, and they're all very terse insofar as the whole point of a command line interface is to let people navigate things quickly.

So for instance, even though this will be a bit of a whirlwind, let me go back into VS code and let me propose that we play around with just a few of these commands so that you've seen me doing it, but generally speaking in CS 50's problem sets, we will tell you step by step what commands to type so that you can achieve the same results and then later

in the term we'll stop bothering reminding you pedantically how to do this and that because it should come more naturally eventually.

But for instance, let me go ahead and do this.

Let me go ahead.

And reopen my file explorer at left.

Yours will look a little different.

You'll have a different number as your unique ID, but generally you'll see whatever files and or folders you've created already.

The first thing I created today was called hello.c.

and then by using Make, I created a second file I claimed called hello.

So the reasonhello works is because there is in fact a program called hello.

In my current folder, ergot that was created when I compiled my source code into machine code.

Now suppose for the sake of discussion that this is going to get messy quickly because the more programs we create in class and for problem sets, you're just going to have a hot mess of files inside of this one main folder.

Well, let's create subfolders like you might be inclined to do on your Mac or PC or Google Drive or whatnot.

What we can do.

This in a bunch of ways.

I could right click or control click on my File Explorer and I'll see a somewhat familiar contextual menu and I can literally choose new folder or I can rename things or I can move things around by dragging and dropping them.

But for today, let's focus more on the CLI, the command line interface, and again commands like this.

So let me go back into VS code.

And let me propose that we do a few things just because as a tour.

First, let me delete the machine code.

I'm done with this example.

I don't really want to keep these bits around unnecessarily.

I'm going to delete hello, not hello.c,

not hello.c, but hello, the compiled program.

When I type that, I'll be cautioned, remove the regular file, whatever that means, called hello.

Here I'm being prompted for a yes no response.

Y suffices.

So I'm going to hit Y enter and watch what happens at top left as soon as I use my terminal window and this command.

To remove that file, it disappears.

I could have right clicked on it or control clicked on it, but this command line interface achieves the same thing.

Now suppose that for problem set one and future problem sets, I want to keep like every program I write in its own folder just to keep myself organized, especially as the term progresses.

Well, let me create a new folder called hello itself.

So I don't want to create a program called hello.

I want to create a folder called hello.

One way I can do this per this here cheat sheet is to make a directory, which just means folder.

So MK DIR, hello enter and you'll see a top left.

Now I indeed have a folder and it even has an obvious folder icon next to it.

Now I could cut some corners.

I could click and drag on hello.c and just drop it into hello, but again, let's stick with the command line interface.

Let me go ahead now and move MV for short.

Hello.c into hello.

So this is the first command where I'm passing in not one word after the command like code hello.c or make hello.

Now I'm typing two words after the command because the way the move command is designed is to expect the origin as the first word and the destination as the second, so to speak, whereby if I want to rename hello.

sorry, if I want to move hello.c into the hello folder.

I should type like this.

Now you can, just so you know, include a trailing slash, a forward slash at the end of the destination just to make clear that you want to put this into a folder and not just rename Hello.c to hello, but because the hello folder already exists, Linux knows what it's doing and it's just going to assume that when you do that, watch what happens at the top left.

Hello.c seems to have disappeared, but if I click this little triangle, ah, there it is, it's now inside of that folder.

But now I've created.

Kind of a predict for myself.

Let me clear my terminal window and now let me type LS.

And when I type LS for list, you'll see only a folder called hello, and it's color coded just to call it out to your eyes and there's a trailing slash just to make obvious that it's a folder that's all done automatically for you by Linux, the operating system.

But wait a minute, where did my hello program go?

Like where is hello.c?

Well, it's in that folder, so I need to change into that folder or directory.

And here per the cheat sheet we have CD for.

directory so I can do CD space hello, with or without the slash and hit enter, and now you'll see this, and it's admittedly a little cryptic, but my prompt has now changed to still be a dollar sign, but before it is just a constant reminder of where what folder I am in.

We adopted this as a convention.

Many systems do the same thing, though the formatting might be a little different.

This is just to help you remember where the heck you are without having to type some other command to ask the operating system what folder you are in.

So now that I'm here, if I type LS and hit enter, what should I see?

Just hello.c because that's the only thing in that their folder.

So now let's do maybe one other thing.

Let's do make hello inside of this folder.

That is OK and notice at top left what just happened.

Now I've got both files back.

All right, suppose I want to get rid of one well I can do RM hello again.

I can type Y for yes to confirm the deletion, and now I'm back to where I just was.

Now suppose I want to do yet other things, suppose that I'm not really proud of this version of hello.c.

Let me keep it, but.

Rename it.

Well, I can say how about MV hello.c to old.c.

I just want to rename the file so MV can be used not only to physically move a file from one place to another.

If you use it on two file names, it will just rename the file for you.

So there's no rename command that you need to use instead.

Uh, but you know what, nope, I regret that this program was fine.

Let's name it back.

So let's move old.c back to hello.c and watch it top left.

It just renames the file again.

Um, let me go ahead and make a backup though.

So let me copy with CP, hello.c into a file called like backup.c just in case I screw this up.

hello.c into a file called like backup.c just in case I screw this up.

I want to have a spare around.

Now you see at the top left, I've got both files.

If I now type out less, you'll see both files.

So what's happening in the GUI is the exact same thing is happening in the CLI, but you know what, this was just for demonstration's sake.

I don't need any of this, so let me remove the backup, say yes for why.

Let me go ahead and move hello.c out of this folder, which I could just kind of drag and drop it, but how do I move hello.c

hello.c to the parent folder, so to speak?

I want to move it out of this folder.

Well, you would only know this by having been told.

is special notation that means the so-called parent folder.

So go back up in the hierarchy.

And now if it's not obvious, a single dot, which we have seen before, means this folder, two dots means one step up.

There's no triple dots or quadruple dots.

You have to use different syntax, but more on that another time.

So watch what happens when I do move hello.c up into the parent directory.

Notice at top left that the indentation changed because it's no longer inside of that same folder and heck, now I'm going to go ahead and do this.

I could go back to my main folder by doing CD.

to back out of this folder, but when in doubt or if you ever get yourself into a confusing mess, just type CD enter alone and you'll be magically whisked away to your default folder, a home directory, so to speak, even though that too is a bit of a white lie, so that will lead you.

Always where you're starting when logging in to CS50.dev AKA VS code, and now I can see the folder which happens to be empty, and the file.

So let me go and do one last command or hello to really undo all of the work such that we're now back to where the story began.

But the point here is just to demonstrate that with these basic fundamental commands you can do everything that you've taken for granted on Macs and PCs for years with a mouse instead.

Questions.

On any of these here Linux commands, yeah.

Really good question.

If you have 5 different files in a folder, how can you choose which one to open?

Well, you can certainly do code, space, and the name of the file you want to open, or we're going to see other tricks like you can use an asterisk or a star for a so-called wildcard and say open everything in this folder, and you can even use more precise patterns than that.

So over time, once we have more files at my disposal, I'll be able to do tricks like that as well too.

Yeah.

Yeah Uh-huh.

So when you like delete the file, uh what was that?

Hello How did Sure, so one of the things I did in my VS code a moment ago was once I was inside of the Hello folder into which I had put hello.c just for the sake of discussion,

put hello.c just for the sake of discussion, I then recompiled it by running Make hello, and this example is a little confusing, deliberately insofar as I've got a file called hello.c

inside of a folder called hello, but because I compiled Hello.C,

I then created a program called Helloo as well.

But that program he was inside of.

folder called hello, which is only to say that you can totally do this.

You can't have a file in a folder in the same place name the same thing because they would collide.

Like you can't do that on a Mac or a PC as well.

You have to have unique names, but you can certainly put something inside of another folder without collision.

Good question.

All right, so let's introduce a few more building blocks and a few more things we can do.

So besides these Linux commands, which we'll now start taking for granted, we have a bunch of other features of programming languages that we saw in Scratch.

Let's now translate them to C.

So conditionals were sort of the proverbial fork in the road, enabling you to do this or this or some other thing based on the answer to a question, a so-called boolean expression.

Here, for instance, in Scratch is how we might express if a variable X is less than a variable y.

We'll go ahead and say x is less than y and out of context, I didn't include it in the slide, presumably we've created X and Y and somehow given them values, whatever they are, but this is just now the conditional part of the program.

In C, the way you would do the same thing is you would say if and then a space, then parentheses, which have nothing to do with functions.

If is not a function, it is a feature of C that implements conditionals just like this orange block is a feature of scratch.

Inside of the parentheses you put your same Boolean expression.

So here too out of context, if up here I have defined variables X and Y, well I can certainly use them in this conditional and I can use this less than operator just like in math class to ask this question.

And the answer, even though it's a less than sign, is indeed if you think about it going to be true or false, yes or no, it's a boolean expression.

It either is less than or it is not.

All right, inside of the curly braces which are necessary here, I'm just going to literally put.

Old friend print F, and there's nothing interesting here except the new phrase X is less than y with the backslash N, the semicolon, and the parentheses.

This though is deliberate, just like in Scratch.

The say is sort of indented and sort of hugged by the if orange puzzle piece.

Similarly, do these curly braces, are they meant to sort of imply the same?

It's sort of embracing these lines of code.

As an aside, in C, they're not always necessary.

If you have a single line of code, you can technically omit.

However, what you'll see in C as well as in CS 150 in particular, we will generally preach a certain style like any company in the real world would do so that programmers who are collaborating on code all write code that looks the same so that it doesn't devolve into a mess because everyone has their own convention.

So this is a convention to which you should indeed adhere and then I've indented 4 spaces to make clear logically that this line of code only executes if the answer to this question.

Is true or yes.

Meanwhile, in scratch, if we had an if E condition, so a two-way fork in the road, if X is less than Y, say so el say x is not less than Y.

How can I do that in C?

Well, if X less than Y, something else, something else.

And what are the uh what goes in between those curly braces?

Well, just two different print Fs.

X is less than Y or X is not less than Y.

The only new thing here is we've added Ls and another pair of curly.

Races just like we've got sort of two orange shapes hugging those two purple puzzle pieces there.

All right, how about something a little more involved and this looks like it's escalating quickly, but it's just because the scratch puzzle pieces are so big.

If X is less than Y, then say X is less than Y.

else if X is greater than Y, then say X is greater than Y.

else if X equals Y, then say X is equal to y.

How can we do this in C?

Almost the same idea.

If X less than Y, if X greater than Y, L X equals equals Y.

Well, before we reveal what's in the curly braces, this is not a typo.

Why have I presumably done this even if you've never used C before?

Yeah.

sit Exactly, the single equal sign, which we've used already when storing a value from get string into a variable like answer is technically the assignment operator.

So humans decades ago decided that when faced with a situation where they wanted to copy from the right to the left a return value into a variable, it made sort of visual sense to use an equal sign because you want those two things ultimately to be equal even though you kind of read the code from right to left.

In that case, I can only imagine at some point the same people were in the room and they were coming up with the syntax for conditionals and like, oh shoot, we've already used equals for assignment.

What do we now use for equality and the solution in C as well as in many other languages is literally this they use 2.

So this is the equality operator, whereas a single one is the assignment operator, and it's just because.

Now Scratch is designed for kids, no sense of confus.

using little kids with equal equal signs, so scratch uses a single equal sign, whereas C and most languages use double equal signs, so a minor divergence there.

What goes in the curly braces, nothing all that interesting, just a bunch more print Fs.

But here's an opportunity to distinguish not only the equivalence of this scratch code with C code, but a missed design opportunity that we sort of tripped over, if briefly last week.

This is arguably not well designed, even though it is correct.

Why, yeah.

Yeah, we don't need to ask this third boolean expression.

Is X equal equal toy, so to speak?

Well, logically, if we're using sort of normal person numbers, it's either less than or greater than or by default equal to.

So you're just wasting the computer's time and in turn the user's time by asking this third question.

So slightly better here would be get Of the ELTS if just have a default case, an ETS block, so to speak, that looks like this.

If it stands to reason that there's only 3 possibilities, you only really need to interrogate 2 of them out of the 3.

So a minor optimization, but you can imagine doing that again and again and again in your code.

You don't want to be wasting the computer or the user's time if you can improve things like that.

All right, so now that we have these equivalences between scratch code and C code for these conditionals, well, what other things can we throw into the mix?

Well, C has a whole bunch of operators, and just so that you've seen a list in one place, you've got not only assignments and less than and greater than in equality, but a few others here as well.

Now, even though in like Microsoft Word and Google Docs you can kind of do a greater than or.

to sign one over the other or less than or equal to in C, in most languages, you actually just hit the keyboard twice.

You do the less than and an equal sign, or you do a greater than and the equal sign, and that's how you achieve the notion of greater than or equal to or less than or equal to this one we've seen.

Anyone want to guess what exclamation point equals means, otherwise pronounced bang equals?

Yeah.

Not equal.

So generally in programming you'll see an exclamation point implying the negation of something else, the opposite.

So you don't want it to be equal to, you want it to be not equal to.

Now you might think, shouldn't it be not equal equal?

Yes, but they're trying to save keystrokes.

So this is the negation of that, even though it doesn't quite look like it should be, just 2 characters instead of 3.

Um, and there's many other operators that won't encounter in the wild over time.

Um, but there's also worth noting in C, more than just strings, like strings we call were strings of text, and there's other types of Uh, data that you might get from a user or store we've seen string, but we'll actually see a whole bunch of others.

So in C we're going to see boos themselves of a variable that can be true or false, and that's it.

So very much interrelated with Boolean expressions.

A variable itself can be true or false.

We're going to see chars or characters, so not strings of text like multiple letters and words and the like, but just individual characters.

See, unlike some languages.

Does distinguish between single characters and multiple characters.

Double, or rather let's jump to float.

A float is otherwise known as a floating point value, which is just a number that has a decimal point in it, a real number if you will, but a float generally uses nowadays 32 bits total to represent those numbers.

The catch with that is that how many total values can you represent with 32 bits roughly per last week.

It's one of the few numbers I propose you remember it's like roughly 4 billion, but how many real numbers are there in the world according to math class?

An infinite number.

So we seem to have a mismatch between what we can represent in code and how many actual numbers there are in the world.

OK, so not to worry, if you need more precision, like more significant digits, well, you can upgrade your variables, so to speak, from a float to a double, which uses 64 bits, which is way more precise, twice as many bits, but it doesn't fundamentally solve the problem because really it's still finite and not infinite, and we'll end today with a look at what the real world implications of that are.

But besides floating point values, there's just simple integers 012, and the negatives thereof, but those conventionally used 32 bits, which means the highest a computer can count using an in would be 4 billion.

But if you want to do negative numbers, it's going to be roughly 2 billion, so you can go all the way to negative 2 billion.

So that's not that large nowadays.

Along uses 64 bits, which is a much bigger range of values, but there too still finite, and there's a bunch of.

Others as well.

So these are just the types of data that we can store and manipulate in our programs, but a couple of those now, do a couple of those, one in particular specifically come from CS50.H. So

among the things you get by including CS50.

H in your code is access to not only get string, but these other functions as well.

And we'll start to use these in a little bit whereby you can get integers or chars.

Doubles or floats.

We don't have a get bol because it's not really useful to just get a true or false value typically, but we could have invented it.

We just chose not to.

But we'll frequently use these here functions that you can access by using that there header file.

But where are we going to put these values and how are we going to display them?

Well, turns out there's more than just percent S.

So percents was a placeholder for a string, but if you want to print out something like a char.

Single character you're actually going to use percent C.

If you want to print out a floating point value, you're going to use percent F, an integer percent I, and a long integer that is a long, you're going to use LI instead.

So in short, there are solutions to all of these problems. These are not intellectually interesting details, but they are useful, practical things to eventually absorb over time.

So let's go ahead and do.

Let's do just a few more examples together in a little bit we'll adjourn for a short break during which snacks will be served every week out in the transit.

But before we get to that, let's focus on these here variables.

So in Scratch we had the ability to store a bunch of values in variables that we could create ourselves by creating new puzzle pieces.

In C you can essentially achieve the same.

So for instance, suppose that in Scratch we wanted to keep track of someone's score.

Using a counter, well, we might create a variable called counter and set it initially to 0 and then eventually add 1 to it, add 2 to it, and so forth as they drop trash into the trash can for instance.

Well, in C you're going to do something almost the same.

You can choose the name of your variable just like I did previously with answers.

You can assign it a value like 0 initially, but per earlier, what more am I probably going to have to do in C on the right hand side here?

Yeah.

I got to give it a type and a counter insofar as it's numeric is not going to be a string of text, and I don't think I need to worry about decimal points if I'm just counting the equivalent on my fingers.

So int will suffice and in is the go to number and at least if 2 billion plus values is more than enough for your case, which this is going to be still one minor thing missing.

Yeah.

The semicolon to finish the thought.

So that on the right is the equivalent to doing this here on the left.

Suppose that in scratch you wanted to increment the counter and add 1 to the score, add 2 to the score, and so forth.

It might look like this.

Change counter by 1, implicitly going up unless you did negative, which would go down.

In C you can do this actually in a few ways, and this looks a bit wrong at the moment.

How can counter possibly equal counter plus 1?

This does not mean equality per se.

The single equal sign recalls.

Assignment and it means take the value on the right and copy it to the value on the left or to the variable in this case on the left.

So this takes whatever the current value of counter is 0, adds 1 to it, and then stores that 1 in the counter variable.

So now the value is 1, and if you do it again, it goes to 2, it goes to 3, goes to 4, and so forth.

But honestly, this incrementation technique is so common that there's more shorthand notation for it.

You can also just do this.

Looks a little weird at first glance, but counter plus equals one semicolon does the exact same thing.

You can just type fewer keystrokes, and honestly, doing this is so down common in C that you can even do this.

Counter plus plus does the exact same thing by adding one to the variable.

There's no plus plus plus or plus plus plus or more pluses.

It's only for incrementing individual values by one.

So arguably this version and this version, albeit more verbose, are a little more.

A tile because then you can add 2 or 3 or more at a time.

And there are equivalents for you doing decrementation and doing minus or the minus symbol more generally in there.

All right, so let's actually use this technique in some code.

Let me go back into VS code here.

Let me close my file explorer and let's go ahead and create maybe this time like a little calculator of sorts.

Let me propose that we implement a very baby calculator, or rather, not even a.

Calculator, yeah, let's just compare some few values.

So let me do this code of compare.c to create a brand new program called Compare.

And then in here I'm going to do a bit of boilerplates.

I'm going to go ahead and include CS 50.

H.

I'm going to go ahead and include standard.io.H,

and I'm going to go ahead and do in Main void, more on that next week.

And then inside the curly braces, let's use these these new techniques.

Let's give myself a variable called X and set it equal to.

The return value of get in, that other function I promised exists, and let's prompt the user for a value for X with a sentence like What's X question mark, and then a space just to nudge the cursor over.

Let's get another variable Y.

Set it equal to get into again and ask the user this time what's Y, essentially using the same function twice but to get two different values.

Now.

Let's go ahead and do something pretty mindless.

If X is less than Y, go ahead and print out with print FX is less than Y backslashn to move the cursor close semicolon.

So it's not that interesting of a program, but it's at least dynamic in that now I'm prompting the user for two numbers.

So let's do this Make compare enter seems to have worked, and in fact I can check that it worked by typing what command to list the files in my directory.

LS for short.

And now you'll see I've got hello.C,

but no hello because I deleted that with RM a few minutes ago.

I've got Compare.c which I just created, and then I've also got a program called Compare and the asterisk there is just a visual indicator that this is executable.

It's a program you can run.

It's not just a simple old file, even though I didn't type.

As previously with hello, it would have similarly had an asterisk next to it in this context, but you don't see that in the File Explorer.

If I now do compare, well, let's do something silly like 1 for X, 2 for Y.

OK, X is less than Y.

Let's do it again.

compare, 2 for x, 1 for Y.

OK and I see nothing.

Well, why am I seeing nothing?

Well, logically, I didn't have a condition for checking for greater than, let alone equal to.

So let's enhance this a little bit.

Let me go ahead and minimally say, right, else if x is not less than Y, let's go ahead and print out X is not less than Y backslash and close semicolon.

So I'm at least handling that situation too.

Let me clear my terminal window, do make compare again, compare 1 and 2 works exactly the same.

Now let me go ahead and do 2 and 1.

There we have better output.

Of course it's not really complete yet because if I do slash compare again and do 1 and 1, it'd be nice to be a little more specific than X is not less than Y.

It's not wrong, but it's not very precise.

So I can add in to the mix what we did earlier and I can say, OK, well, else if X is greater than Y.

Say X is greater than Y else if X equals equals y, go ahead and print out X is equal toys.

But here too someone observed that this is sort of stupidly inefficient.

What line of code should I actually improve here?

To tighten this up, yeah.

if you could Yeah, so line 17, I think I can just get rid of that unnecessary question because logically that's going to be the case at this point and now I can go ahead and recompile this with make compare compare again enter 1 and 1, and now we're back in business, catching all three of those situations, uh, those scenarios there.

Questions on any of these things here.

Why have I deliberately not done this?

Let me rewind just a moment and let me hide my terminal window just to keep the emphasis on the code here.

Why not do this and keep my code arguably simpler?

Like, why not just ask three questions Step 9, step 13, and step 17 here?

Yeah, what don't you like?

Because then it would check each and every condition, um, even though for example the first one might be fulfilled, it would check the 2nd and 3rd to that way.

Exactly, it's another example of bad design because now no matter what you were asking three questions on lines 9, 13, and 17.

Even if X ends up being less than Y from the get-go, you're still wasting everyone's time by saying, well, well, is X greater than Y?

You already might know that it's not.

Is X equal to Y?

You already might know that it's not.

And so these three conditionals at the moment are mutually exclusive, whereby you're checking all three of them no matter what, even though logically that should.

Be necessary.

So our first approach was actually quite better.

And in fact just to show you the density difference here, let me go back to this very first version here whereby I was only checking that one condition is X less than y.

Well, if you're more of a visual learner, you can actually draw out what code looks like in flow chart form.

So here is a drawing of a program that starts here and ideally stops down here, and each of these figures in the middle sort of represent logical components of the code.

Uh, here in the in the diamond here is my boolean expression, which represents the start of the conditional.

So if X is less than Y, I have a decision to make.

Yes or no, true or false.

Well, if it is less than Y, true, well, let's go ahead and print out quote unquote X is less than Y and then stop.

However, the first version of that program recall just said nothing if it were not the case that X were less than Y.

That's because false just led to the stop of the program.

There's no keyword stop.

There's just.

No no code to handle that situation, but the second version of the code, when I actually added in ES looked fundamentally a little different.

So now 2nd version of that code asked is X less than Y and if true, behavior is exactly the same.

But if it weren't true, it were instead false, that's when I got the message X is not less than Y.

But in the third version of the code where I added the if else if L if, then the picture gets a little more complicated and let me zoom in top to bottom.

Here we have.

Longer flow chart, but the questions are really the same.

When I start this program, I ask, is is X less than Y?

If so, I print out X is less than Y.

However, in that, in that last version of the program, I was still foolishly asking the same question.

Well, wait a minute, is X greater than Y?

Wait a minute, is X equal toy?

And that's the version in which again I had all of that unnecessary code which I just undeleted here asking three questions at a time.

Ideally, Don't want to make that mistake by doing it again and again and again.

So if I instead revert that code to ETS if and Es if, then my flow chart looks a little bit different because notice the sort of shortcuts now.

If X is less than Y, woo, true, we do this and we're done super quick.

If x is not less than Y, fine, we do ask one more question.

X is greater than Y.

Well, if so, boom, we make our way to the end of the program by just printing that only if it's the.

Reverse case where x equals equals y.

Do we check this condition?

No.

This condition, no.

This condition and then OK, now we can print out X is equal toy because it must be logically.

Of course it's been observed multiple times.

This is a waste of everyone's time, so we can prune this chart more and just have one question, two questions, and that alone tightens up the program.

So again, if you're more of a visual learner, most any block of code you can translate to this sort of pictorial form, but it really just captures the same.

Logical flow that the indentation and the syntax in the code itself is meant to imply.

All right, how about a final exercise with one other type here?

Recall that this is our available types to us.

Actually two final examples here before we have a bit of a break.

Here we have a list of types that we can use, and here we have a list of functions that we can use.

Let's go ahead and make a program that's representative of something we do quite often nowadays, but using a different type.

So let me go back into VS code.

Let me close compare.c.

Let me reopen my terminal window and clear it just so we have a new prompt.

And let's go ahead and create a program.

Called agree.c.

It's all too often nowadays that we have to like agree to terms and conditions.

To be fair, it's usually in the form of like a pop up and a button that we click, but we can do this in code at the command line as well.

Let me go ahead and include to start CS 50.H and include to start standardio.h.

Let me again for today's purposes do in Main void, but we'll reveal next week what we why we keep doing that.

And now for a yes no answer, it suffices just to ask for a single char or character, not a whole string.

So let's do this char.

C equals get char and let's ask the user, quote unquote, do you agree question mark for instance.

And now I can actually compare that value for quality with some known answers.

For instance, I could say if C equals equalsy, then go ahead and print out, for instance, agreed period backslash semicolon, else if C equals equals n.

In quotes, let's go ahead and print out, for instance, not agreed backslash and semicolon.

Now there's still room for improvement here, but notice we're just now using the same building blocks and C um in different ways to solve different problems. But notice on lines 8 and 12 I've used single quotes, which I alluded to earlier.

Why is that the case?

Why single in this case here?

Yeah, it's a single character and this is just the way you do it in C.

When you want to compare a single character, you use chars and you use single quotes.

When you want to use strings of text like multiple characters, multiple words, multiple sentences or paragraphs, you use strings.

So this would seem to work, but are.

I could be a little more efficient if the user doesn't type Y.

I mean, frankly, I could just chop off this L if and make it an E and just assume if you don't give me ay answer, then at least I'm going to assume the worst and you don't agree.

But even here, the program's not all that great.

Let me go ahead and do make agree.

And then do slash agree, and do I agree?

Sure, I'm gonna go ahead and type Y.

Meanwhile, if I type anything else like N or uh even emphatically no, that would seem to, whoops, why did that not work?

Yeah.

Exactly.

So among the features of CS 50's functions like Getchar is that it will enforce what type of data you're getting.

So even though I, because I use Getchar, if the user doesn't cooperate and types in multiple characters, GetAR, like some of our other functions, is just designed to prompt them again.

Again and again until they cooperate, that's useful so that you don't have to deal with that kind of error checking.

But here I could type N in uppercase, and that seems to now work but that only works because of the Ls.

Let me go ahead and do this, which is very reasonable.

I'm going to go ahead and type Y Y, which you would hope works.

That feels like a bug at this point.

Like it's fine if we don't want to support yes and no.

We just want to support Y and N, but it's kind of obnoxious not to support the upper case version thereof.

So how can we fix this?

Well, let me hide my terminal window and I could go in and fix this as follows.

I can say, well, else if C equals equals quote unquote.

Capital Y in single quotes and then I can do print out agreed period backslash and semicolon, and then I can do that that would work that would work there, but what rubs you the wrong way perhaps about this solution, even if you've never programmed before.

Just applying some of the lessons from last week, yeah.

It's redundant.

I mean, I didn't technically copy and paste, but like line 14 is identical to the line 10, so I might as well have copied and paste, and that's generally bad practice.

Why?

Well, if I want to change the English language to say something else in that case, now I have to change it twice and it's just I'm repeating myself, which is just bad design.

So there are ways to address this through other types of operators that we haven't yet seen.

If I want to ask two questions at once, that's fine.

I can do something like this.

Well, if C equals equals Y or C equals equals Y, I can tighten things up using so-called logical operators whereby I am now taking a boolean expression and composing it from two smaller boolean expressions, and I care about the answer to one of those questions being true.

So whether it's lowercase y or uppercasey, this code now will work and if it's anything else, we're going to default to not agreed.

So the two vertical bars, which is probably not a character you type that often, and it varies where it is on your keyboard depending whether it's American English or something else, just means logical or.

This is not relevant here, but you could also in some contexts use two ampersands to connote and, but this does not make sense why.

Why is it clearly not correct to say and in between these two clauses, yeah.

Exactly, the variable can't both be lower case and uppercase.

That just makes no sense.

So this would be a bug, but using a vertical two vertical bars here is in fact correct.

All right, well, let's do one final flourish here besides conditionals.

We had these now loops.

We call that a loop is just something that does something again and again and again.

Here, for instance, to scratch how we might meow 3 times.

In C there's going to be a few different ways to do this.

Here is one.

You can in C.

Declare a variable like I for integer or whatever you want to call it and set it equal to 3, the number you care about.

You can then use a loop, and the closest to the repeat block is arguably a y loop.

There is no repeat keyword in C, so we can't translate this verbatim, but we could say while I is greater than 0.

Why?

Because that's sort of logically what I want to do.

If I start counting at 3, maybe I can just sort of decrement one at a time and get down to 0, at which point I can stop doing this thing.

So I'm going to initialize a variable to I, a variable I to 3, and then I'm going to say while I is greater than 0, go ahead and do the following.

And at the end of that loop before whipping around again, I'm going to use this line of code, which we haven't seen, but you can infer I minus minus just means subtract 1 from I.

So this is going to have the effect of starting at 3, going to 2, going to 1, going to 0, and as soon as it goes to 0, this boolean expression will no longer be true.

And so the loop will just implicitly stop because that's it.

So what are we going to put inside of the curly braces besides this decrementation?

Well, I think I can get away with just saying meow, and that will now print 123 times.

And yet that's interesting.

I sort of counted instinctively 123, even though I'm proposing that we count 321.

So can we implement the logic in the other direction whereby we count up from 0 instead of down from 3?

Well, sure, we just have to.

A few changes.

We can set i equal to 0 initially.

We can change our boolean expression to check that I is less than 3 again, again and again.

And on each iteration of this loop, let's just keep incrementing I with I plus plus.

And at this point it will have the effect of doing +1233 is not less than 3, so I won't put any more fingers up.

I will meow in total 3 total times.

And again, if you're a visual person, here's how we might start counting at 0.

Initially, check that i is less than 3, which it is initially, and if so, we print out meow.

Then we increment I and we get whisked around again to the Boolean expression because that's how while loops work.

You constantly have the condition being checked again and again.

That's just how C works.

As soon as I've incremented I from 0 to 1 to 2 to 33 will eventually not equal, not be less than 3, so the answer will be false, so the loop will just.

So that has the effect of achieving the same, but it turns out that looping some amount of times is so darn common that you don't strictly have to use a Y loop.

A 4 loop, so to speak, is another alternative there too, whereby the syntax is a little weird, it's a little harder to memorize, but it allows you to write slightly less code because you write more code on a single line.

So the way you read a for loop is exactly the same in spirit.

You initialize the variable, everything to the left of this first semicolon.

You then check the condition and the computer does all this for you.

If I less than 3, if so, you execute what's inside of the curly braces, and then automatically the thing to the right of the second semicolon happens, so I gets incremented from 0 to 1 in this case.

The condition is checked is 1 less than 3.

It is, so we print meow again.

And C increments 1 to 2.

Is 2 less than 3?

Yes.

So we now again I gets incremented to 3.

Is 3 less than 3?

No, so the 4 loops stops.

So it's exactly the same, but just more magic is happening in this first line of code here more than you yourselves have to actually write, and it's just arguably more common convention, but both of them.

Are perfectly correct if you'd like to do that yourself.

So let's go ahead and actually implement now this this beginning of a CAT in VS code.

Let me go back to VS code and close agree.c.

Let me reopen my terminal window and create an actual cat in cat.C.

And let's go ahead and do this initially the wrong way, include standardio.

H in main void, and then inside of Main, let's go ahead and print out quote unquote meow backslash N semicolon.

And then heck, let me just copy paste.

So this is obviously the wrong way, the bad way to do this because I'm literally copying and pasting, but it is correct if I want the cat to meow 3 times, I can make this cat.

I can do cat, and I get my meow, meow, meow.

But let's now actually use some of those new building blocks whereby we converted scratch to.

See and let me go back into this code and I'll do the while loop first.

So I could instead have done in i equals 3 if we count down initially while I is greater than 0, then go ahead and print out quote unquote meow backslash N and then do I + plus or I minus.

I minus minus because we're starting at 3.

Now let me go back to my terminal window and clear it.

Do makecagalaca and we get 3 meows and this is now arguably better implemented.

What if I want to flip things around?

Well, I could now change, uh, maybe do it the normal person way.

I could start counting at 0, and I can do this so long as I is less than 3, and I can do this so long as I increment I on each iteration.

Now I can do makecagaincat enter, and that too works.

But there's another way I could do this if I want to count like a normal person, like start counting from 1 and count up 2 and through 3.

I could do this, but this is arguably this is correct.

It would iterate 3 times, but it's a little confusing because now I have to think about what it means to be less than 4.

OK, that means equal to 3.

I could be a little more explicit and say, we'll do this while I is less than or equal to 3 using yet another one of those operators.

So I can make a cat yet again, and that too would work.

Now which of these is correct or best?

The convention truthfully is in general in code to start counting from zero, start counting up to but not through the value.

You that you want so at least you see the starting point and the ending point on the screen if you will at the same time.

But of course I can condense all of this a bit more and turn this whole thing into a 4 loop and I instead could do 4 in I equals 0, I less than 3, I + plus, and then down here I could do print out quote unquote meow and if only because I typed fewer keystrokes that time, like this feels a little nicer, it's a little tighter

and more efficient to create even though the effect is the same.

Indeed, when I make this cat.

And do a final time this year to gives me the three meows.

So what could go wrong?

Well, sometimes you might be inclined to do something forever, and we might have done that in scratch, and indeed we did when we had some things bouncing back and forth off of walls and so forth.

You can achieve the same thing in code.

In fact, in C we could use a while loop, but there is no forever block, so while suffices.

But recall that the while loop expects a boolean expression, and if I want to do something.

Forever I essentially need an expression here that's always true.

So I could do something stupid and arbitrary like while 2 is greater than 3 or while 1 is less than 2.

I mean, make a statement of fact that never changes ergo it's just going to run forever.

But if the whole goal here is to do something forever and to get this boolean expression to be true, the convention in programming is just to literally say while true, and that implies.

And functionally means that you will do this thing forever unless you somehow prematurely break out of those curly braces.

More on that before long.

So if I want to meow forever, I could now just do this, and this would be an infinite deliberate loop, but unlike a game where you might want it to keep going and going and going for some time, I'm not sure this is going to be the best thing for us.

Let's go ahead and try this.

So let me go ahead here and Include for good measure uh CS 50's library if only because um it too is giving us features like uh bulls.

Uh, here I'm gonna go ahead and say while true, and then inside of my curly braces I'm just gonna print out meow.

Let's go ahead backslash N semicolon.

Let's go ahead here and make cat one final time.

Let me go ahead here and do cat and.

This is like the annoying cat game just like meowing meowing meowing endlessly.

Like I've now kind of lost control over my terminal window and mark my words, at some point you might do this too, but let's go ahead and take a juicy 10 minute break here.

Uh, we have some delicious blueberry muffins out in the transep.

Come back in 10, and we'll figure out how to stop this here, cat.

Alright, so it's been about 10 minutes and like VS code is freaking out with high code space CPU utilization detected.

Consider stopping some processes for the best experience.

So this is what happens when you have intentionally or otherwise an infinite loop insofar as I've been printing out meow endlessly, and I was warned by my colleague that I probably shouldn't let this run too.

Long because we might lose control over the environment altogether, but the answer to how to solve this is going to be control C.

So there's a few cryptic keystrokes that you can use to generally interrupt things as in this way.

And in fact, if I go back and you'll see, you know, I kind of lost control over my code space here, I'm going to go ahead and try to reload the window altogether, but had I hit control C in time, let's hope this doesn't now go off the rails.

Control C would have been our friend.

There we go, and we're back.

OK, so now that we've got control over our so-called code space again, how can we go about making our meowing program a little more dynamic in so far as let's like start asking the user how many times they want the cat to meow, certainly rather than do it an infinite number of times and even rather than do it 3 times alone.

I think we have all.

These building blocks thus far.

So let me go ahead and stay in cat.c here and go ahead and delete the body of the contents of my main function.

And let's go ahead and do this.

Let's give myself an in and I'll go ahead and call it N for number, though I could be more verbose than that if I wanted.

I'm going to set it equal to the so-called return value of get in, which we call is going to get an integer from the user and quote unquote, let's ask the user what's and just.

Like I asked earlier, what's X and what's Y, where N is the number of times I want the cat to meow.

Now how can I use this variable?

Well, we have that building block too.

I could use a Y loop or a 4 loop, and if I use a 4 loop, I could do this.

I could initialize a variable I for integer, set it equal to 0 initially.

I could then do I less than not 3 this time, but N, so I can use that.

Variable is a placeholder inside of the loop to indicate that I want to do this n times instead of 3, and on each iteration through this loop I can do I + plus.

Of course I could be counting down if I prefer by using decrementation, but logically I would say this is canonical.

Start at 0 and go up 2, but not through the value that you actually care about.

And I'll go ahead now and print out quote unquote meow with a backslash N semicolon.

Back down to my terminal, make this catgaca enter.

I'm prompted this time for N.

I can still give it 3, and I'm going to get 3 meows this time.

However, if I run it again with cat and a different input like 4, of course I'm going to get 4 meows instead.

Now what is get in doing for me?

Well, it does a few things similar to get char doing a few things for me.

For instance, suppose that instead of answering this question correctly with a number.

and I say something random like dog that is not an integer and so the get in function is designed to reject the user's input implicitly and just reprompt again, again and again.

I can try bird and it's going to do this again.

So somewhere in the implementation of get in there's a loop that we wrote that does this kind of error checking for you, but it doesn't do everything because an integer is a fairly broad category of numbers.

It's like negative infinity.

Through positive infinity and that's a lot of possibilities, but suppose I don't want some of those possibilities.

Suppose that it makes no sense to ask the cat to meow like -1 time, and yet the program accepts that.

It doesn't do anything or anything wrong, but I feel like a better designed program would say no, no, no, like -1 makes no sense.

Let's meow 0 or 1 or 2 or more times instead.

So how can I begin to add some of my own error checking and coerce the user.

To give me the type of input I want.

Well, let me clear my terminal window and go back up into my code, and why don't I do something like this?

After getting N, let's just check if N is less than 0, because if so, I want to prompt the user again, and I can prompt the user again by doing N equals get in quote unquote what's N question mark semicolon.

Now what's going on here?

Well, on line 6 I'm doing two things.

I'm getting an integer from the user and I'm not only storing it in the variable N, I'm also technically creating the variable N.

So I didn't call this out earlier, but on line 6 when you specify the type of a variable and the name of the variable, you are creating the variable somewhere in the computer's memory, and that's necessary in C to specify the type.

If the variable already exists though, and you just want to reuse it and change it later on, it suffices as in line.

9 just to reference it by name.

It would be sort of stupid to specify the type again because C already knows what type it is because you told C what it is on line 6.

So that's why line 6 and 9 are a little bit different.

So let's see how this now works.

Let me go back to my terminal window and remake this cat.

Let me doca again.

Let me not cooperate and type in like -1 again and notice I am reprompted this time.

Fine, fine, fine.

Let's type in 3.

And now it works, but you can perhaps logically see where this is going.

Let me go ahead and run this againca, type in -1, type in -1, and huh, it didn't prompt me again, but that's consistent with the code.

If I hide my terminal window here, you'll notice that I've got 1, maybe 2 tries to get this question right, and after that there's no more prompting of me.

Now you can kind of imagine that this is probably not the best way to do this.

If I were to go inside of line 9 and then move the cursor down and say, OK, well if N still doesn't it still is less than 0, well, let's just do get into again and ask what's N question mark and heck, OK, if it's still less than 0, well, let's just keep asking the same, right?

Why is this bad?

I'm repeating myself.

I'm essentially copying and pasting even though I'm retyping.

I mean this just never ends, right?

Like how many chances are you going to give the user?

In spirit you'd hope that they don't not cooperate this many times, but really to do this the right way we should probably prompt them potentially as many times as it takes to get the correct input.

So this is not the right path for us to be going down.

But of course we have already now this notion of like a loop whereby we could just do this in a loop.

Ask the question once and maybe just repeat the question again, again, but the same question.

So how might I do this?

Well, let me go ahead and delete all of this and let me just try to spell this out logically.

So I want to get a variable N from the user and let's go ahead as follows.

While true, I know how to do infinite loops now, and even though that created a problem for me with the cat, I bet we can sort of terminate the loop prematurely.

I proposed earlier as follows.

I could do this in N equals get in and ask the user again what's N question mark.

And then I could do something like this.

If N is less than 0, well then, you know what, go ahead and just continue on with the same loop.

Else if it is not the case that N is less than 0, what do I want to do?

I want to break out of this loop.

So this is new syntax.

This is something you can do and see whereby if N is.

Less than 0, fine.in means go back to the start of the loop and do the same exact thing again.

fine.in means go back to the start of the loop and do the same exact thing again.

Otherwise if you instead say break, it means break out of the loop and go to below whatever curly brace is associated with that loop.

So continue essentially brings you to the top, brake brings you to the bottom if you will.

So logically I think this is right, but this code curiously isn't quite going to work and get me a value for N.

Let me go ahead and open my terminal window again.

Let's make this cat and huh cat.c line 1925 is an error use of undeclared identifier N.

cat.c line 1925 is an error use of undeclared identifier N.

Well, what does that mean again cat.C line 19.

Let me hide my terminal window highlight line 19 N is being used in line 19, but I created it in line 8 and so what's the problem?

Why is it?

Not declared seemingly, yeah.

Like and Yeah, this is a subtlety, but I'm using.

I'm creating N inside of this loop.

I mean literally between the curly braces on line 7 and 17.

The implication of which because of how C works is that that variable only exists inside of that 4 loop.

This is a problem of what's known as scope, the.

and only exists inside of the scope of the while loop in which it was declared.

So how do I actually fix this?

Well, I need to logically somehow declare that variable and outside of the loop so that it exists later on in the program as well.

And there's a few different ways I can fix this, but the best.

The way is probably to move the declaration of N, so to speak, the creation of N outside of the curly braces, and maybe kind of squeeze it in here below line 5, so still inside of Main, whatever that is, more on that next week, but in the same curly braces as everything else.

So I can in fact do this, and this is where the syntax gets a little bit different.

I can solve this quite simply as follows.

I can go down to a new line 6 and just say in and semicolon, and that's it.

This declares a variable called N.

It creates a variable called in and initially it doesn't give it any value, so who knows what's in there.

More on that another time.

But now on line 9, I don't need to recreate it.

I just need to assign it a value.

And because now N has been declared on line 6 and between the curly braces on line 5 and all the way down on 24, now N is in scope, so to speak, for the entirety of this code that I've written.

So let me reopen my terminal window and clear that old error.

Let me do make cat again.

Now the error messages is gone.

Let me go ahead and do slashca.

What's in.

Now I'm back in business and I can do 3 for meow meow meow.

But better yet, because I'm inside of a loop now, watch that I can do -1, -1, 1123, 50.

Finally I can cooperate with something like 3, and because I'm in a loop that by design may very well go infinitely many times until the user actually cooperates and lets me break out of.

That exact loop.

Now I strictly speaking, don't need both continue and break.

I wanted to demonstrate that both exist, but this is like twice as much code than I actually need.

If logically I just want to break out of this loop if and only if n is greater than or equal to 0, because I'm sort of comfortable with the idea of zero mouses, but negative makes no sense, well I can just flip the logic.

I can say if N is greater than or equal to 0, then go ahead and break and I've tightened up.

The code further.

I could technically do something else.

I could say something like if N is less than 0, but wait a minute, I want to negate that.

You can start to do tricks like this an exclamation point with some additional parentheses so you can invert the logic.

It's arguably a little hard to read even though that would be logically correct.

So I'm just going to say more explicitly as before, if N is greater than or equal to 0, break out of this here loop.

All right, so this is one way to use an infinite loop, but it turns out there's another construct that you can do altogether that is in a feature of C.

Instead of using a while loop and forcing it to be infinite by using while true and then eventually manually breaking out of it, there exists another type of loop altogether, and that's called a do while loop, and you can literally say the word do, which means do the following, then you can do.

Exactly what we did before N equals get in quote unquote what's end question mark, so exactly like before, but then after those curly braces you use a while keyword, so at the end of the loop instead of the beginning, and that's where you put your boolean expression.

I want to do all of that while N is less than 0, so you can kind of invert the logic.

And now kind of tighten things up further by just telling the computer do the following.

What's the following?

Everything in between those curly braces while N is less than 0, and this implicitly handles all of the continuation and all of the breaking by just doing what you've said do this while this is true, but the difference between this do while loop and a normal while loop is literally that the condition is checked at the bottom.

Instead of the top, so when you say while parentheses something, that question is asked first and then you proceed maybe this condition is only asked at the very end and why is this useful?

Well, oftentimes when writing programs where you want to do something at least once, like you obviously want to ask the user this question at least once, there's no point in asking a question.

And like while true or while anything else you should just do it and then you should do it again if the expression evaluates the true and tells you to do something.

Now you haven't played with these loops yet most likely unless you have programmed before.

Uh there's a fun sort of meme that's apropos of this moment, so let's see if this maybe causes a few chuckles if you remember Looney Tunes here.

It's funny for people in the know.

There we go, thank you.

OK, this doesn't make sense.

It eventually will, and it still might not be funny, but it will at least make sense, and it illustrates the difference between do while loop, like the roadrunner, is stopping because he's checking the condition while not on edge, he'll run, but if he is on the edge, he's not going to proceed further.

But of course the coyote here, he's going to do running no matter what and then only too late does he check.

Ha ha, he's still on the edge.

All right, so, ah, thank you.

All right, now you're cool.

All right, so many more memes will now make sense as a result, but let's go ahead and revisit this code and maybe do something a little bit different here whereby we no longer want to just futz around with some of these, uh, conditionals and these loops.

Let's actually make the software a little better designed.

And to do this, we'll revisit an idea that we touched on last week and he had to do with problems. 0, which was like create your own function like C does not come with everything you might want.

CS 50 library is not going to come with everything you might want.

And at the end of the day, a lot of programming is about abstracting away your ideas, so you solve a problem once and then reuse it, reuse it, reuse it.

And heck, you can package it up in a so-called library like we have and let other people use it as well.

So here for instance in Scratch is how we could have implemented the notion of meowing as by getting The cat to play the sound meow until done.

We abstracted it away and then we had a magical new puzzle piece called meow.

In C, this is going to be a little weird today, but next week these details will start to make more sense.

You would instead do the following literally type void, the name of the function you want to create, and then void again in parentheses.

For now, know that this is the return value of the function.

So void means it returns nothing.

This is the input to or the arguments to the function, void means it takes no inputs, and that makes sense because literally meow doesn't return anything, it doesn't take anything, it just meows.

It has a so-called side effect audibly last week.

So this means, hey, see, invent a function called meow that takes no input, produces no output, but does have a side effect of printing meow on the screen.

Meanwhile, if I wanted to do something like this in code last week where I meowed 3 times, well, that's fine.

We have the building blocks for this, and here's where inventing your own functions starts to get more compelling.

I can abstract away the notion of meow.

Now this doesn't come with C, it doesn't come with the CS 50 library.

I just created in the previous code this meow function so I can encode with a 4 loop and that new function meow 3 times.

But I can abstract this away further.

Recall that the refinement and scratch last time was this.

I could edit the new function and I can say it actually does take an input, otherwise known as an argument, called N.

And I clarified that this means to me meow some number of times and then inside of those scratch blocks I repeated N times the meowing act.

Well, in C I can achieve the exact same thing even though it's going to look a little more cryptic, but meow still returns nothing.

It has an audible or visual side effect, but it doesn't return a value.

But this version does take an input, and this might look a little weird, but just like before, when you create a variable in C, you specify the type and the name.

When you invent your own function in C and it takes one or more inputs, AKA arguments, you specify the type and the name of those as well.

No semicolons up there, just inside of the parentheses, and you'll get used to with practice this convention, but the rest of this code is exactly the same except instead of 3.

I'm now using N.

So again, I'm just composing the exact same ideas as last week, even though it looks way more cryptic this week, but it will come more and more familiar with more and more practice.

So how can I go about implementing this myself?

Well, let me propose that.

We do something like this.

Let me go back to VS code here and let me go ahead and let's really delete most of the code that I've written inside of Maine and let me just suppose for the moment that meowing exists, and I'm going to go ahead and say for the first version for into I equals.

less than 3, so we're not going to take input yet.

I plus plus, and then I'm going to go ahead here and say meow is what I want this function to do.

Now if I scroll back up, you'll see there's no definition of meow yet, so I'm going to invent that too.

I'm going to go up here and say void, meow, void, and again this first version means no input, no output, just a side effect, and that side effect super simply is going to be to say just quote unquote meow with the backslash n.

And now if I go and open my terminal window, clear it from before, do make cat so far so good, scat, we're back in business, but I've abstracted the function away.

Now much like last week where I sort of dramatically dragged the meow definition way down to the bottom of the screen just to make the point that you don't need to see it anymore, out of sight, out of mind, let me sort of try to do the same here.

Let me highlight and delete that.

And like go way, way, way down arbitrarily just to be dramatic and paste it near like the 100th line of code and scroll back up.

Now out of sight, out of mind.

I've already implemented the idea of meowing.

We don't need to see or talk about it again.

But there is a caveat in C.

When I now clear my terminal and make this cat, now I've introduced a problem, and there's like more problems it seems than code.

Let me scroll back up to the first such error and you'll see this on line 9 of cat.

9, there's an error.

Call to undeclared function meow and then something fairly arcane.

But that means that meow is no longer recognized as an actual function.

I know that it doesn't come from CSST.H,

and I know it doesn't come from standard IO.H. It's just down there.

But why is the compiler being kind of dumb here?

Uh, yeah.

defined the Yeah, because insofar as the first version worked, like logically it would seem that putting it at the bottom was just a bad idea because C compilers are fairly simplistic.

Like they won't proactively do you the favor of like checking all the way down to the bottom of the file.

They're going to take you literally.

So if meow doesn't exist as of line 9, that's on you.

Like that is an error.

So I could fix this by just undoing what I did.

Move it way back up to the top, but let me argue that in general when writing C programs, the main function which I keep using and we'll talk more about next week is literally meant to be the main part of your code.

And so it kind of stands to reason that it should be at the top because when you open the file, it'd be nice to see the main program that you care about, the main function.

So there's an argument to be made that it's a little annoying to have to put my functions all at the top, which is just going to push main further and further down.

So there is a solution, and this is dare say the only time copying and pasting is appropriate.

Let me delete most of these blank lines, which is unnecessarily dramatic, and just move it below main as over here.

The way I can uh the solution here though is to do this to copy the first line of the main function.

It's so called signature and then just put that one line and only that one line with a semicolon above main and this is what's known as a prototype.

So a prototype is just a bit of a hint to the compiler, a promise if you will, that hey, compiler, there will exist a function called meow.

It takes no input and it returns no output semicolon, and it's on the honor system that it will eventually exist later in the file.

We'll talk more about this next week, why that works, but this is sort of a promise to the compiler that it will eventually be defined.

Now what I've done here on line 4 as an aside is what's generally known as a comment.

I just wanted to put on the screen exactly what I was verbalizing.

Anything in C that starts with slash slash is a note to self, like a sticky note in scratch, which is just for the human, not for the computer, and it's a way of reminding yourself or someone else what's going on on that line or those lines of code.

But I'll go ahead and delete it for now is unnecessary because now if I go back into my terminal and clear those errors, make this cat again now.

It does work because the the meow function has been defined exactly where it should be, and now I can make the new version of this cat even better.

I could change the function meow to take a variable n as input for the number of times, and then in here I could do something like my 4 loop 4 into i equals 01 less than Ni plus plus, and then in this.

For loop, I can print out quote unquote meow, and then I'm gonna have to change this too because I have to copy and repaste it if you will, or just manually fix that.

But now I can get rid of all of this and do meow 3, for instance, and this now will be the second version of the scratch code if you will, makeA still gonna work exactly the same meow meow meow, but now I've implemented my own function that does take input even though it doesn't happen to return any outputs.

All right, questions.

On any of these examples just yet.

Confusion All right, let me add one other feature to this to demonstrate that we can take not only input but actually produce output if we want.

If I go back into this code here, let me propose that it's a little silly to be hard coding that is fixating 3.

It'd be nice to get input from the user, so I could do this.

I could use in N equals get in and say something like.

Like what's question mark and then I could pass N in if only to demonstrate a couple of things.

So one, now the program's dynamic, I'm going to ask the user how many times to meow and I'm going to pass in that value n.

Now this deliberately is confusing at the moment because wait a minute, I got N defined here, used here, but then redefined here and then reused here.

So it turns out that even if you create n up here and use the name N, no other functions can see it for that same issue of scope.

So for instance, suppose I didn't quite remember this, and I sort of naively just said void, meow doesn't need to take any inputs because heck, N is already defined in Maine.

Let me go ahead and open my terminal and clear it, make CA and see what error comes out here.

Well, error oh sorry.

I made two mistakes here.

Let me, I also have to change the prototype up here to say void, which means again meow takes no inputs.

Let me go ahead now and rerun make CAT, and there we have an undeclared identifier again N.

So in cat.

C line 14, which is here, it doesn't like that I'm using N.

But wait a minute, I created N here, but for the same logic as earlier, that's fine.

You create an N on line A, but where does N exist?

In what scope?

Yeah, only between the curly braces, which is lines 7 and 10.

So by the time you get down to 14, it's out of scope, so to speak, so it just doesn't work.

So the solution is exactly what I did the first time.

I can pass it into meow as input, and I have to tell C to expect that input, and I can use the same name, but arguably that's going to get confusing sometimes.

But let me do this.

Let me go back into my code.

Let me undo this change such that now meow does take an input, but instead of just calling it N and using N everywhere for number, this is crazy, let's just call this like times.

So meow takes some number of times and then it uses that value, and now I'm passing in on line 9 N, but in the context of the meow function on lines 12 onward, that same variable n.

Is now referred to as times because you're passing it in as input and giving it its own name and that's totally your prerogative.

It's just a matter of scope.

I mean I could have called it M or some other letter of the alphabet, but times is even more clear because that's the number of times I want the cat to meow.

But again, the whole point here is just this matter of scope.

All right, so let's take a higher level look now at some of the things we've been thinking about, and then we'll do a final deep diver too on some of the corner some of the problems that we can solve with all of these building blocks and some of the problems that we're sort of ignoring for now.

So when it comes to writing good code, CS 50 and really the world in general tends to focus on these kinds of axes correctness, design, and style.

What does this mean?

Correctness just means does the code work the way it's supposed to in the context of a class, it should do exactly what the homework assignment, AKA problem set, tells you.

To do in the real world, it should do exactly what someone decided the software should do the product manager, the CEO, or the like.

Correctness just means it behaves as it should.

That's different though from how well designed the code might be, and we've seen that a few times.

I've had some simplistic examples in Scratch and C that were 100% correct, like it did the right thing logically, but I was wasting the computer's time.

I was wasting the human's time by asking more boolean expressions than I needed to and so forth.

So design is more about like in the in the world.

English like not only saying things that are correct but doing it well, like and making a good cogent argument, not just one that happens to be correct.

Style meanwhile is the third axis on which we might evaluate the quality of someone's code, and that's more of the aesthetics like is everything pretty printed, that is nicely indented, are variables well named and not just called X Y Z arbitrarily or something like that.

So style matters really to other humans, not to the computer, but to other humans.

And to illustrate these.

And you'll see that in problem set one onward you'll be given a number of tools that you can use.

So one of those tools is called Check 50, and in each problem set, problem in C and Python and other languages, you'll be showed how you can test your own code and you can literally run a command that CS50 created called Check 50.

You'll then specify what's called a slug, which just means a unique identifier for that homework problem, and you'll get quick feedback on whether or not your code is correct.

It doesn't mean it's well implemented or well designed or.

that is well stylized, but at least that's the first gauntlet in getting good code submitted.

Design though is much more subjective.

Design is something you get feedback on from a human, for instance, in section or a teaching assistant or in software.

You can actually see at top VS code there's a couple of buttons that I haven't yet used but could.

Design 50 is built on top of the CS50 duck, whereby if you have a program open in a tab, you click Design 50, you will get chat GPT like advice on how you can.

Prove not the correctness of that code, but the design of that code, the quality thereof, which is a bit more subjective and modeled after what a good teaching assistant might say.

Style 50 meanwhile is a third tool that will provide you with feedback on the style of your code.

It will show you on the left what your code looks like and on the right what your code really should look like insofar as it should be consistent with what we've taught in class and consistent with CS 50's so-called style guide.

And those of you who have some prior programming experience undoubtedly won't.

Like some of CS 50's stylistic choices, and that's going to be the case in the real world too, but as I alluded to earlier, in typical companies you would have an official style guide or tool to which everyone adheres so that everyone's code actually looks the same as everyone else's, even though people have contributed different solutions to problems. So correctness, design, style is not only how we,

but really the world writ large tends to evaluate the quality of code, and we do it by way of the CS 50 specific tools here.

All right, how about one final flourish then to this here program back in VS code, I've got a correct solution right now.

Um, it's well styled.

I'll stipulate even though it could stand to have some more comments.

So for instance, I could do something like this, like meow uh some number of times, a comment to myself or up here I could say something like, uh, get.

A number from user just to remind myself and my TA or my colleague what it is this code is doing, but what more could I do in the way of design?

Well, this function here get in will indeed get me an integer, but not just positive or zero, but negative, and I could go in and add a bunch of code like before, like I could actually do instead of this line, I could do something like in and.

Semicolon do the following N equals get in and then I can say what's N question mark and then after that I can do something like while N is less than 0, keep doing that so I can have a pretty verbose implementation of getting user input or I can implement another function of my own that only gets a positive integer or non-negative integer from the user.

For instance, I might do something like this.

Uh, I could, uh, declare at the, uh, maybe below my main function a function like this, uh, in, uh, how about get N and then inside of this I might say void because I'm not going to pass in any input.

Then inside of this function is where I'm going to do into and do Y.

N equals get quote unquote what's n question mark and then down here I'm going to do while N is less than 0, but rather than do something immediately with N because I'm no longer inside of my so-called main function, what I'm going to do, which is new, is return this value n.

And notice that this notion of returning a value, which is the first time I've done this explicitly, is consistent with this little hint here on my 19, which implies that this get end function which I'm inventing is going to return, not void, which means nothing but an integer, and that's the whole purpose of this function in life now.

If I scroll back down here, I can get rid of this whole block of code.

And just say get in from the user and then I can immediately call meow with that value.

I need to do one other thing.

I need to highlight this line of code here, and I'm going to go ahead and add another prototype up top, which is the only time again for now that copy paste is encouraged and best to do.

So I've invented my own function, get in, the whole point being now I have this sort of abstraction here of a function whose whole sole purpose in life is to get me not just an integer, but one that is zero or positive and not negative.

If I open my terminal window, clear the mess from before, make this catca what's N3, I'm now back in business, and again we've essentially translated from scratch last time into C this time.

Exactly how we might modularize now the code, abstract away these lower level details, and ultimately create my own function that as before takes not only arguments but in this case has not only side effects, it doesn't have side effects but rather a return value this time.

All right, so as you walked in, we had a little walkthrough of Super Mario Brothers playing from yesteryear, which was a side scrolling game in which Mario would jump down and go up, down, left, right and try to collect coins and make it to the end of the level.

There's a lot of obstacles throughout this kind of game whereby the world might look a little something like this, like there's a pit that Mario's got to jump over, and then there's these coins hidden typically behind these question marks that he can jump up and hit his head with and actually accrue points.

Now we're not going to do anything graphical just yet.

We're leaving.

Graphics behind for now in the form of scratch, but with C we can implement some of these ideas.

For instance, if I were to write code to generate just this row of 4 question marks, I dare say there's a bunch of ways we can do this.

In other words, let's see if we can't use all of today's building blocks to start implementing our own tiny version of Super Mario Brothers in a file, say, called Mario.c.

called Mario.c.

So let me open and clear my terminal window.

Let me run codemario.c.

And let's just try to do something super simple like print 4 question marks in a row.

Well, to do this, I need printF, so I'm going to include standard IO.H. I'm then going to do in Main void.

More on that next time.

And inside of Main, my default function that just automatically as before gets called for me, I'm going to print out the simplest possible implementation, just print out for.

Or question marks like that.

So no need per se for a loop just yet, but I think we can go down that rabbit hole too.

Let me go down into my terminal window, make this version of Mario Mario enter, and voila.

We have a very black and white version, textual version of 4 question marks in the sky.

Now I'm kind of cheating.

Here by just hard coding 4 question marks, what if I wanted not 4 but 3 or 5 or some other number?

Well, we could do that with a loop too.

So let me change this code here and do something like this 4 I equals say 0 I less than say 4 for now, I plus plus.

Then inside of this loop I can print out one question mark at a time, semicolon.

Now let me go back to the bottom, make this version of Mario Mario enter and hmm.

It's not actually correct this time.

So why am I getting a column instead of a row with this here change?

Yeah.

Yeah, so I've got, I foolishly included the backslash N after each question mark.

OK, so that seems like an easy fix.

Let me get rid of that.

Let me now recompile Mario, rerun Mario, and now so close.

Now I've just done something stupid.

All right, I need the backslash N, so I think I do want this here, or What do you propose instead?

Yeah, I should really put the backslash in outside of the loop so once I'm done printing all of the question marks, then I get the backslash in and that's fine, even though we haven't seen this before.

Backslash N is an escape sequence that you can certainly print by itself, so I do quote unquote backslash N outside of the loop below those curly braces.

Now if I do make Mario Mario, now I get the 4 question marks in a row.

As well as the new line at the very end.

So again, kind of a little baby exercise, but demonstrative of how you can just take a few different techniques, a few different building blocks we've used to compose a correct solution to what a moment ago was a brand new problem.

Well, let's try another.

So later on in Super Mario Brothers, when you go into sort of the underground world, you see, or rather it's still above ground, you see a column of bricks.

Like this that he has to jump over.

So those here, how might we make a column?

Well, we kind of had that solution already.

And in fact, if I go back to VS code here and just change this version of Mario, I think we can design this thing to be pretty simply the same.

I is less than 3 though, and I do want to put the backslash N at the end there, make Mario Mario and albeit textual.

I've got my column.

Of 3, of let's see, I don't want question marks.

Let's make this a little better.

Maybe we'll use the hash symbol because that kind of sort of looks like a square.

So make Mario Mario.

OK, now we're back in business.

But let's make it more interesting by going into Mario's underground now and here's the third and final Mario problem whereby we want to implement like this 3 by 3 grid of bricks circled here.

So this one's interesting because we've never done something in two dimensions.

I did horizontal, I did vertical, but we haven't really composed those ideas into the same.

So let me now think a little harder this time about how I can print out row, row, row, and this is where if you have in your mind's eye any familiarity with.

Old school typewriters, it's kind of the same idea where you want to print a row of bricks, then go back to the beginning, a row of bricks, then go back to the beginning and a row of bricks, and that's kind of what printF has always been doing for us.

It's printing line by line by line of text.

It's not jumping around, so we can leverage that perhaps as follows.

Let me go into my main function here.

And if I want to print out something 2 dimensional, let me kind of think about it as rows and columns.

So maybe I could do this for in I equals 01 less than 3, I + plus.

Why?

Well, I want to do something 3 times, even if I have no idea where I'm going with this solution.

I at least want to do something 3 times like 3 rows of text.

But how about this on each row, what do I want to do?

I want to print out 3 things.

So I could steal this idea like I equals 01 less than 3, I plus plus, and then inside of this loop, let me just print out one brick at a time, no new lines yet, one brick at a time, but there is a bit of a problem here.

This is correct to nest loops in this way.

Totally fine to have an outer loop, totally fine to have an inner loop, but I probably don't want the inner loops variable competing with the outer loops variable by giving them the same name.

And that's fine.

It is pretty conventional in code when you want another integer, and it's not I because you've used it already, fine.

You can use J.

So using I and J and K is generally fine.

If you're using L, M, and O, like at that point you're probably doing something wrong.

There's no hard line, but at some point it gets ridiculous and you should be coming up with better variable names.

But I and J, maybe K is fine.

So now what's really happening?

Let me propose that this is my Uh, for each row, this is my for each column.

I want to print one brick.

Now this isn't quite correct, but let me go ahead and make this version of Mario Mario, and now there's what, 123, there's 9 bricks there.

So I'm close, right?

It's supposed to be 3 by 39 total.

What do I want to do though to get this just right?

Yeah, up on the left Yeah, what, on what line number would you or after, uh, where would I put the new line?

Cause I think I don't wanna put it here because I'm gonna get myself into trouble as before, how about in back?

After the what?

After 13, yeah, so after I finished printing each brick in the column from left to right, I'm gonna go ahead and print out, I think, a single new line here, nothing else, and now if I open my terminal, run Mike Mario again.lamario,

now we've got it, and it's not a perfect square because like this.

One is because like the hashtags are kind of more vertical than they are horizontal, but it's pretty darn close.

The the takeaway here being you can certainly nest these kinds of ideas and compose them, and honestly I and J is maybe making this more confusing than necessary.

I could just give these better names like row row.

Row and then maybe call for column or column I can spell it out if that's clear column column just to make clearer to myself to my TA, to my colleagues what exactly these variables represent and indeed like an old school typewriter, the outer loop is.

Handling row by row by row, but each time you're on a row you first want to do column, column, column, column, column, column, and that's what logically the nesting is achieving.

And again, if I do make Mario Mario, all I've done is change variable names, it has no functional effect beyond that.

Now this is a little more subtle, but there is a bit of duplication in this program.

There's a bit of magic, and this is subtle, but does anyone want to conjecture what still could be improved here?

What is maybe rubbing you the wrong way?

Yeah, I've hard coded the 3 here and here.

It's not a big deal.

It's like an in-class exercise.

Like who really cares if I'm just manually typing 3?

But if I want to make this square bigger and bigger and bigger over time, I'm going to have to change it in two different places and I've conjectured last time and today eventually that's going to come back and bite you.

You're going to do something stupid or a colleague isn't going to realize you hard coded 3 in multiple places, like just bad design.

So how could we fix this?

Well, we could just.

Declare a variable like n, set it equal to 3, and then use n in both places, and that's pretty darn good.

That's better because now we are reusing the value, but we can do 1 better than this.

It turns out in C and in many languages too, there's the notion of a constant whereby if you want to store something in a variable but you want to signal to the compiler that this value should never change and better still, you want to prevent yourself, a human, or Not to mention a colleague from accidentally changing this value, you can declare it to be constant or constant for sure.

So if I go back into VS code on line 5 now and say constant, that means that N is an integer that has a constant value.

So if I do something stupid later in my code and I try to set N equal to something else, the compiler won't let me do that.

It will protect me from myself, so it's just a slightly better design as well.

All right, questions on any of these here, Mario.

Examples the first of our sort of real world problems, albeit simplified textually.

All right, let's focus lastly on things we can't really do well with computers, uh, namely some of the limitations thereof.

So here is a cheat sheet of some of the operators we've seen thus far.

We played with these with comparison and, uh, doing some, uh, addition or the like, but here we have addition, subtraction multiplication, division, and the modulo operator which is essentially the remain.

operator, which you can do with a single command with a single operator like this.

Let's use some of these to make our own calculator and see what this calculator can and can't do for us.

So back here in VS code, let me open my terminal.

Let's go ahead and create a program called Calculator.c.

And in this program, let's do something super simple initially that just like adds two numbers together.

So let's include first.

Uh, CS 50.h so we can use our get functions.

CS 50.h so we can use our get functions.

Then let's go ahead and include standard IO.h so we can use print F.

Let's just copy paste our usual in main void, and inside of Main, let's do this declare a variable X, set it equal to get in, and let's ask the user what's X question mark.

Then let's declare another variable Y, set it equal to get in and ask the user what's Y question mark.

Let's do something super simple like give me a third variable, heck, we'll call it Z, set it equal to x + y, and then lastly, let's just print out the sum of X + Y.

So this is a super simple calculator for addition of two numbers.

Print F quote unquote.

What's the answer going to be?

Well, it's not pers.

This was quick earlier.

What's the placeholder to use for an integer?

Percent I backslash N and what do I want to substitute for that placeholder?

Just Z in this case we haven't quite done this before, but again it's just the composition of some of our earlier ideas.

I can go ahead and make this calculator enter calculator enter what's X is 1, what's Y is 2, and indeed I get 3.

So not a bad calculator.

It seems to be working correctly, but it's maybe not the best design.

Like it's generally frowned upon to create a variable like Z if you're only going to use it.

A moment later in one place, like why are you wasting my time creating a variable just to use it once and only once?

Sometimes it's fine if it makes your code more readable or clearer, and in fact it might if I called it sum.

Like that's arguably a net positive because I'm making clear to the reader that it's the sum of two variables.

But even then I'm quibbling, I could just get rid of that third variable altogether and heck, I could just do X + Y right here.

That's totally fine and reasonable, especially since it's still a pretty short line of code.

It's not.

Hard for anyone to read feels like a reasonable call, but this hints at again my comment on design being subjective.

There's no steadfast rules here.

Some of the TAs might disagree with me, but like, ah, this feels fine.

It's readable, which is probably the most important thing ultimately.

Let's make this calculator calculator.

E 12, and we still get 3.

So the code now is still working.

As an aside, if you're starting to wonder how I type so fast, sometimes I'm kind of cheating.

With autocomplete.

So if I know I want to create a program called Calculator, and Calculator.c exists,

and Calculator.c exists, I can start typing CAL tab and you can hit tab to sort of autocomplete the rest of the file name if it happens to exist there.

Better still, if I want to go back to previous commands I've typed, I can actually use my up and down errors to go through my history.

So if I go up, up, up, you'll see all of the recent commands I typed, and that saves me time.

2 so just little keyboard shortcuts that speed things along.

All right, well, let's do something like this, not just addition.

Why don't we use some multiplication?

So how about we prompt the user, not for two numbers, but how about just 1 initially X, and let's go ahead and multiply X by 2, and I would do X, asterisk 2, which is the multiplication operator in C.

Let's make this version of the calculator calculator, and now what's X?

Let's do 1.

So 1 times 2 is 2.

Let's do this again.

Let's type in 22 times 2 is 4.

Let's do this again 33 times 2 is 6, and so forth.

That's fine.

It seems to work, but maybe let's implement like a recent meme from the past year or two.

How about this?

Let's, uh, let's see if you recognize it as we go.

So I'm going to get rid of this code altogether and inside of my calculator I'm gonna do something like in dollars equals $1 by default.

Then I'm going to deliberately induce an infinite loop just for demonstration's sake.

Then I'm gonna do a character from the user and say something like this using get char, which gets a single character.

Uh, how about I'll tell the user, here's this many dollars percent I with the US dollar sign before it.

Double it and give to next person question mark if familiar with that one, and I'm going to prompt them for a yes no answer, but I'm going to plug in the current number of dollars so they know what they're wagering on.

Then below this I'm going to say if the character the human typed in equals equals Y for yes, then I'm gonna go ahead and do dollars times equals 2, which recall was our shorthand notation for doubling something.

Uh, in this case, I could more pedantically say equals dollars times 2, but again I can say some keystrokes and dollar equals 2 instead.

There's no plus plus.

There's no star star trick, asterisk trick, you have to do it in this way minimally.

However, if the user does not want to double it and give it to the next person, then let's do an L and just break out of this infinite loop altogether.

But notice what I've deliberately done in Getchar.

Similar to Print F, I have included a placeholder.

Why we implemented GetHA and get in and get string just like Print F and that you can pass in placeholders and plug in values.

Why?

Well, again, for the meme's sake, I want to be able to tell the user how much money I'm about to hand them when I ask them the question, Do you want to double it and give it to the next person?

I want to see the number and the dollar sign is just because we're talking about dollars.

The percent I is because we're talking about integers.

All right, if I didn't mess this up, let's make this version of a calculator or meme.

So far, so good.

calculator, enter.

Here's $1 which was the initial value of my dollars variable on line 6.

Double it and give it to the next person.

All right, why?

Here's $2.

Double it and give it to the next person.

OK.

OK.

OK.

OK.

OK.

I'm going to do it faster.

It's getting pretty good.

You can see the power of exponentiation.

It's getting pretty high.

Let's keep going.

Keep going, lot of dull, mm mm, too far.

That does not happen in the memes.

What happened here?

What's going on?

Yeah, what do you think?

Exactly good intuition because the computer only has a finite number of bits allocated to each integer.

I hypothesized earlier that it's usually 32 bits, maybe 64 bits, but it's finite, which means you can only count so high and it's roughly 4 billion or again an integer by default can be negative or positive.

So it's roughly 2 billion, and that's pretty close to what we were getting here.

In fact, we overflowed the integer in memory.

In fact, integer overflow is a term of art.

Whereby you can overflow an integer by trying to store too big of a value in it, and the reason for this is again to make this clear, this is a piece of memory inside of a laptop or a desktop or some other device, and in these little black chips is a whole bunch of bits or really bytes that can store information electronically, but they allocate those bits in units of 8, maybe 16, maybe 32, maybe 64,

but finitely many per value.

Whether we're using 32 or 64, you can only count so high if you have a finite number of bits, and we've seen this problem even on a small scale with our flat light bulbs last week.

If we have a 3 digit number as represented by like 3 physical light bulbs or 3 tiny transistors in the computer, I can count from 0 to 1 to 2 to 3 to 4 to 5 to 6 to 7.

If I want to count to 8 though, I need a 4th bit.

But as the red suggests, if you don't have a 4th bit, for all intents and purposes, that number is just 0.

Or as an aside, depending on how you're representing your numbers, sometimes a leading one indicates that the number itself is negative, which is why in VS code we actually saw both symptoms. First we went negative because we wrapped around logically, much like that 1 resulted in our getting back effectively to zero, and then we did.

Indeed end up on 0 ultimately.

So how can we chip away at this?

Well, a couple of solutions perhaps.

Let me close my terminal window here and instead of using an in, well, let's just kick the can down the road.

Let's use a long, which is 64 bits.

So at least we can give away even more money in this scenario.

I can't use percent I I need to use LI now for a long integer, but I think at this point, if I go back to VS Code's terminal window here, or when I quit that program by hitting control C quickly.

Uh, now I'm going to go ahead and do make calculator again calculator, and I'm just going to keep hitting Y.

But because I'm using a long in now and thus 64 bits, if I do this long enough, it's going to get crazy high and much, much higher than before, high enough that I'm not going to keep clicking Y enter because we're never going to hit the boundary, but eventually, especially if I did this in a loop automatically, it would certainly, 00.

OK, I guess exponentiation works fast.

OK, so it did work.

I didn't think I was going to hit it enough times, but the same problem happened again.

We overflowed this long integer, even using that many bits because I was talking so long I kept hitting Y enough times to overflow even that long integer.

So that too was a problem, and this happens truly in the real world.

So picture here is a Boeing 787 from a few years back, long before there were all the more recent problems with.

planes whereby after 248 days of continuous power, which is kind of a thing in the aviation industry like time is money, and generally they want the planes in the air as much as possible, which means they want them powered on as much as possible, which means they don't like turn them off at night.

They keep them going and flying.

After 248 days, the New York Times reported a few years back that a Model 787 airplane.

That has been powered continuously for 248 days can lose all alternating current electrical power due to the generator control unit simultaneously going into fail-safe mode.

This condition is caused by a software counter internal to the GCUs that will overflow after 248 days of continuous power.

Boeing is in the process at the time of developing a GCU software upgrade.

Will remedy the unsafe condition.

So literally what this means is that the power to these planes would just shut off if the planes were on for more than 248 days at a time, and this was a common thing for lanes to be maximal power.

Why was this actually happening or what was the solution?

Well, the short term fix, because it took a while for Boeing to fix this, was what?

What would you do if the symptom is that the plane shuts off midflight after 248 days, yeah.

Literally turn it off and back on again, much like you've probably been taught with your phones and computers and any other electronic devices that somehow freak out on occasion.

Reboot the plane.

Now why is that?

Well, any time you reboot a phone or a laptop or a plane, all of those variables get reset to their default values, which, if it's the first line of code, like in some of my examples, get set back to zero again.

For instance, the first line of code is executed from top to bottom.

So this effectively solved the.

Problem.

But when they finally rolled out a fix, then you didn't have to do that anymore.

But the source of the problem is essentially that they were probably using 32 bit integers, but also negative value, so they had 31 bits at their disposal to count to positive numbers, and 248 days is roughly how many tens of a second there are, which means once you count in tens of a second for 248 days you would overflow an integer and the power would shut off effectively because.

Something ended up going to zero, so there was a lot of sort of marketing speak or technical speak in that, but it boiled down to just a simple integer overflow.

There's a historical bug in Pac-Man if you've ever played this in any of its forms whereby you can play up to level 255, but because there was a missing if condition that checked what level you were on, you could accidentally garble the screen if you were amazing at Pac-Man because they too would overflow an integer and just random character.

would end up appearing on the screen, so it's sort of like a badge of honor to actually hit level 256 in this way because of this bug.

But there's yet other issues we can see here, and if you don't mind, we might go a couple minutes over, but let me just demonstrate what these examples can do for us here.

If I were to revamp my calculator here as follows by clearing my terminal window after hitting control C to kill that, let me go ahead and get rid of all of this meme code here, scrolling down to the inside of main.

And let's just do a couple of things like this in X equals quote unquote uh what's X question mark.

Then let's go ahead and do in Y equals get in quote unquote what'sy question mark.

Then let's go ahead and print out just X divided by Y.

So here's a percent I backslash N X divided by Y.

This would seem to be a calculator now for division, which I can make as before.

And actually, sorry, I don't want to do the missing terminating, oh, sorry, missing a double quote there was an unintended bug.

So, if I make this here calculator, do slash calculator, type in 1, type in 3.

I get 0, which is weird.

What if I do instead maybe 2 and 3?

It's 0 instead of 0.66.

What if I do 3 and 3?

Well, that curiously works, but if I do something like 4 and 3, which would be 1.33, that 2 doesn't seem to work.

So there's this other issue in computing when you have finite numbers of bits known as truncation whereby even when you're trying to do floating point math like with a decimal point, if you are using an integer, you're going to.

Throw away everything after the decimal point unless you're explicitly using the right data type, and we saw an allusion to this earlier.

If I actually go in now and change my values from integers to floats and change the percent I to a percent F and remake this calculator, now I can do 1 divided by 3 and I actually get back that their response.

But there's another issue latent here which happens to in the real world whereby I'm going to tweak this percent F to be a little arcane.

It turns out.

You can see how many digits you want to show how many significant digits you want, if you will, by just using a dot and then a number like 50 arbitrarily.

And contrary to what you might have learned in grade school, this calculator would seem to think that calculator 1 divided by 3 is not 0.33333333 infinitely many times.

There's all this random stuff happening at the end.

Long story short, this is because computers one only use finitely many bits even.

To represent floating point numbers and if there's an infinite number of those, you can't possibly represent every possible floating point value.

So we're essentially seeing an approximation of 1/3 precisely, but this too happens quite a bit in the wild.

There's really no solution to this other than by throwing more bits at the problem using a double instead of a flow, or at least somehow trying to detect this and catch this.

That then is what we'd call floating point imprecision.

But to tie this together and sort of induce a bit of fear and for the coming years.

These things happen all of the time.

Back when I was finishing school, there was the so-called Y2K problem or year 2000 problem whereby for decades computers had been using not 4 digits to represent years but just two because it was convenient, it was more efficient because you use half as much memory to represent maybe the year 1999 just using two digits instead of 4.

Of course when the year rolled around from 1999 to 2000, if you didn't have these numbers even in memory, you might confuse.

2000 with 1900, which was the presumption if you're only storing two digits.

So we screwed that up and thankfully the world scrambled, and if you read up on Wikipedia and news articles from the time everyone thought the world might very well end, but it didn't, so you'd think we'd learned our lesson.

Unfortunately, another such problem is coming up in the year 2038, whereby historically since the 70s and prior, computers have generally used 32 bit integers to keep track of time, the date and the time.

By means of counting how many seconds have passed since January 1st, 1970, and all of the math is just relative to that date because that's when computers were really starting to come onto the scene, if you will.

Unfortunately, there's only 4 billion values you can count to or 2 billion if you're doing negatives from January 1st, 1970.

And so, um, on the date January 19th, 2038, we will overflow a 32 bit counter and suddenly if this problem is not.

Fixed by you or other people before the year 2038, our computers and phones and other devices may very well think it's December 13, 1901.

So there are solutions to these problems. CS 50 is all about empowering you with solutions to these problems, but if you'd like to scan this here code, um, this will add that date to your Google calendar or your Outlook calendar.

Keep an eye on it.

That though is week one for CS 50.

Problem set one will be in your hands soon.

We'll see you next time.

Loading...

Loading video analysis...