In this video, we'll learn about what functions are in c++.
When we develop c++ programs, we typically use the predefined
functions and classes in the c++ standard libraries.
These are functions and classes that have already been written
for us and tested, and they're available for us to use.
We've already seen how useful the standard vector and
standard string classes can be.
C++ has many other libraries that we can use in the same way.
Depending on our application, we may also use third-party
functions in libraries.
These may be open source commercial or other types of libraries that
have been developed by other programmers and are available
to use in our applications.
So if we want to develop games in c++, we'd very likely use
third-party libraries or frameworks such as Coco's, 2DX, Unreal,
Spring, Cryengine or others.
Why would we use third-party libraries?
Well, that's pretty easy.
Because these libraries take a tremendous amount
of effort to develop.
And chances are high that the functionality you need
has already been implemented and tested and ready to use.
So why reinvent the wheel?
Well using existing functions and classes from
existing libraries is great.
But even then, you still need to write your own c++ functions and
classes that are specific to the problem you're trying to solve.
We'll talk about classes and object-oriented programming soon.
In this section, we'll focus on functions.
Functions allow us to modularize our program.
This is a big deal since we can divide our program into logical
self-contained units of code that we can reuse whenever we need to.
Let's see a simple example.
On the left hand side of the screen, you can see a program
written in the way we've been writing them up to this point.
Lots of statements one after the other.
Some of these statements might be if statements, some
might be looping statements.
But you can see that this program has three logical sections: one for input,
one for processing and one for output.
But everything's in the main function.
This is okay for relatively small programs like the ones we've written.
But as programs get larger and more complex, this breaks down quickly and
the code becomes difficult to manage.
Also, we tend to copy and paste code a lot since we may
need the same functionality in different places in the program.
There's a field in computer science called software engineering.
Software engineering is all about designing your solutions and writing
your code in a way that can be easily understood, debugged and extended.
One of the fundamental principles in software engineering is abstraction.
Abstraction is exactly what functions help us achieve.
Let's look at the example on the right side of the screen.
In this case, we've replaced ten statements with three.
These three statements are function calls.
Now when we look at our main function, we see less detail, more abstraction.
We can now see read input, process input and provide output.
So we've modularized our program.
We know that we still have to execute all the code we had before.
But we've removed it from main and replaced it with a call
to functions in each case.
Let's see what these functions look like.
On the left side of the screen, we see the same main function
with the three function calls.
And on the right side of the screen, we see the implemented
functions: read input, process input and provide output.
Notice that each of these functions executes the same
statements that we were executing previously in the main function.
This makes our code more modular, more readable, more maintainable,
easier to debug and easier to reuse.
Let's see how this can help us develop programs.
A common analogy that's used when learning about functions
is the boss/worker analogy.
Let's assume you're the boss, and you need to get a task done.
This task involves several subtasks, and your job is not to perform
the individual subtasks but to coordinate the execution of those
subtasks and report the synthesized results back to your own boss.
So you've hired three workers that have expertise
in each of those subtasks.
So you assign a subtask to each worker and provide each of them whatever
information they need to perform it.
Since each of the workers knows exactly what to do.
When they complete their subtask, they report their results back to you.
This may simply be a comment that says I'm done or could be a complex report
that they created and provide to you.
Now that all subtasks are completed, you look at the
individual results, synthesize the report and give it to your boss.
Sounds like an easy job being a boss, right.
Actually, no.
The boss needs to know what worker to assign the specific subtask
to, the order to do them in, the information to provide to each
of them, so they can do their job.
And the boss needs to know what he or she is getting back in order
to synthesize it and report back.
This is a great analogy to using functions.
If you need to call functions, you write your code to the
function specification,
you need to understand what the function does.
You need to understand what information the function needs.
You need to understand what the function returns to you.
You need to understand any errors that the function may produce and why.
You need to understand any performance constraints and so on.
What you don't need to worry about is how the function works
internally unless of course you're the programmer coding the function.
This is super important to understand.
When we use string, vectors, math functions, complex
image processing libraries.
Collision, detection and games, we don't need to know
how those algorithms work.
This concept is called information hiding.
And we'll revisit this again when we talk about object-oriented classes.
Let's see an example of this.
C++ has many libraries.
One library is a mathematics library.
In order to use this library, we must include cmath.
The cmath library has many mathematical functions,
including trig, exponential logarithmic power, rounding and
many more kinds of functions.
These functions are global functions, which means they're
available to the entire program.
We call these functions by using their name, followed
by a series of arguments.
In the output statement on this slide, we're calling square root
and we're passing in 400.0 to it.
The square root function will calculate the square root of 400 and
return the result which is printed.
In the last example, we're calling the power, power function,
which expects two arguments.
In this case we're calculating 2.0 raised to the 3.0 power.
Notice that to use these functions, all we need to know is what they
do, their name, what they expect from us and what they return to us.
How the square root or the power is being calculated isn't something
I need to know to use them.
That's classic abstraction.
There are many built-in functions and classes in c++.
However, we'll need to learn to design and write our own.
In this section, we'll learn to write our own functions.
Here's a preview of a very simple function so you
can see where we're going.
Don't worry about the syntax I'll cover all that later.
In this case, I have a function called add numbers.
And it expects two integers named a and b.
The body of the function simply returns a plus b.
So we take the sum of a plus b and return the result to the caller.
Notice the int to the left of the function name. That tells
you what the function returns.
In this case, an integer.
Pretty easy, right?
Now every time we need to add two integers, we can call add numbers
and supply the two arguments that the function expects.
Then I can do whatever i want with the result I get back.
In this case, I'm displaying it.
I know what you're probably thinking.
Why in the world would I write a function that adds two numbers when
I can just use the plus operator.
Well, normally you wouldn't.
But suppose we had a requirement that if any of those numbers is
negative, then we must return 0.
Let's see how we can modify this function.
So this is what the function might look like if we had to return
0 if either a or b is negative.
It would probably be a good idea to give this function a better name.
But hopefully, this preview example gives you a good high level view
of a simple user defined function.
Let's head over to the IDE and use some of the functions
in the c++ standard library.
Before we learn to write and define our own functions, it's important
to understand to use functions that are already defined for us.
I've opened up a browser, and I've gone to cppreference.com.
I'm going to show you three pages within this website, and I'll provide
urls and the resources for the course.
Here, I'm going to the c++ standard library header files.
Here are all the standard header files in c++.
And you can see, there's a whole bunch of them.
This would become your next learning experience in c++.
Once you understand the basics of the programming language, once you
understand object orientation within c++, then it's a matter of learning
what's out there and available to you.
There's a lot of stuff out there, and there's a lot to learn.
But don't worry you won't learn it all at once, you'll learn it
little by little as you use c++.
What I want to do here is I want to talk about a couple of libraries,
and we'll run a couple of example programs using those libraries.
We'll use some of the functions in those libraries.
The first library we'll use is the math library.
And I've got a pane open right here to the cmath standard library header.
Now we're going to use some of the functions in here, you can
see that they're all defined.
And if you need information about any of them, you can just click on
here, and you can learn about them.
We're going to use the square root, the cube root and the power function.
They're just like what you would think, right.
You pass in a number, you get the square root.
You pass in a number, you get the cube root.
And in this case, I pass in two numbers to the power function, and it
will raise the base to some exponent.
And here's a whole bunch of information about those functions.
Okay, we're also going to do sin and cosin and a couple of other
interesting and very useful functions, the ceiling, the floor and round.
The ceiling of a floating point number is the next integer.
So if my number is 12.4, the ceiling would be 13.
The floor is the other way around.
So if I have 12.4, then the 4 will be 12.
And rounding works just like you would expect, 12.5 rounds up
to 13, 12.4 rounds down to 12.
So that's what we'll do.
And then in the next little program we'll write, we'll
come to the c standard library.
And I'll open up that website for you as well.
This is c standard lib.
That's the name of the library header.
That's what you need to include.
And there's a couple of functions in here that we'll use.
And I'll scroll down just a little bit there right here, it's rand and srand.
Rand generates a random number, a pseudo-random number.
And I'll explain what that means in a little bit.
And srand seeds in the random number generator.
So what we'll do is, we'll use this function, rand, to generate
the num -- let's say we're rolling a 6-sided dice, and we can
get something between 1 and 6.
We could really make that between anything and anything, and
I'll show you how to do that.
And then we'll see that random number generator so that the patterns of
numbers we get will differ every time.
So I'm going to head over to the IDE now, and we'll start
with the math functions.
Okay, so I'm back in the IDE.
And I'm in the section 11 workspace in the math project.
And here we're just doing some real simple math examples to show
you how to use these functions.
First of all, we're including cmath that's required.
Otherwise, you're going to get a lot of compiler errors because
the compiler won't know about square root, it won't know
about sign or anything else.
In this little example, I'm declaring a double called num, and I'm asking
the user to enter that number.
Once the user enters the number, I'm simply calling the square root
function that will return the square root of the number, and we'll display
it right in line the cube root, the sin, the cosin, the ceiling, the
floor, and we'll round that number.
Then after that, I'll ask the user for another number, which
I've defined called power.
In this case, we'll raise that number that they typed into this power.
So if they typed in 2.5, we'll raise it to whatever power they wanted to.
And again here what we're doing is we're calling the power function
right here, and we're passing in the number and the power to raise it to.
Pretty simple.
You can see from this code, I don't know how square root works or cube
root works or sin or cosin or power.
I don't know how this stuff is implemented behind the scenes.
That's the whole point.
I don't care, I don't need to know.
And this is where abstraction really shines because we're
just trying to solve a problem.
And I know I need to raise something to a power.
Well, I know I need a sin or cosin.
I can simply look up the library, understand how that function is
being called, understand what that function returns and then
just use it and use the result.
So let's run this program, and let's say the number we enter is 125.6.
And I'll press enter.
So the square root of 125.6 is 11.2071.
The cube root we expect to be right around 5, right.
Because 5 times 5 is 25 times 5 is 125 so that gives us a -- it's not a
formal test case, but it's a pretty informal test case that makes us
feel good that our code is working.
Here's the sin of the number, the cosin of the number, now
the ceiling of 125.6 is the next integer up which is 126.
The floor would be the integer down, which is 125.
And in this case, we round 125.6 up to 126.
So let's enter a power.
Let's raise this to the 4.2 power.
There you go. That's a pretty big number.
So 125.6 raised to the 4.2 power is 6.54269 times 10 to the 8th.
There you go.
We've used the math functions without knowing anything
about how they're implemented.
That's a real, real powerful place to be.
Let me go back to the IDE now, and we'll create some random numbers.
Okay, so I'm back in the IDE, and I'm still in the section 11 workspace.
This time I'm in the random project.
Now in order to use random numbers, I'm using the rand function.
Now the rand function has been used a long time in c++ and in c as well.
But there's a better way to create random numbers if you're really
doing statistical processing and that's the random header file.
I'm not going to cover that.
I'm just going to use rand since that's what we're learning
about calling functions.
But if you really need very precise distributions, consider
using the random header file.
Okay, so in this case, we're including the c standard library
that gives us the rand function.
And we're also including the c time library.
I'll talk about that in a minute.
In order to use random numbers, we really need to seed a
random number generator.
Now what's a random number generator?
A random number generator is just a generator that creates random numbers.
Computers are real bad with random numbers.
We have what are called pseudorandom numbers.
What that means is that the numbers themselves are random but the sequence
that they're generated in is not.
So in order to create more real random numbers, we want to seed that random
number generator with a different value each time that way it creates
different sequences of values.
So we'll do that in a second.
I'll do it without seeding and with seeding so you can see the difference.
But let's talk about what's going on here.
I need a random number generated, right.
So I'm going to create a variable called random number
and I'm initializing it to 0.
And then what I want to do is, I just want to loop and
create 10 random numbers.
And that's what my count variable is.
I can make that as whatever I like.
But in this case, it's a 10.
And then in this case, I'm assuming we're rolling a die.
So I want to return a random number between 1 and 6 inclusive.
So 1 2 3 4 5 or 6.
This could be 1 to 10. This could be 1 and 2
if you're flipping a coin.
This could be anything you like, whatever range you like.
This is how you would create that range.
And I'm just going to create min and max to be 1 and 6.
You can modify those to whatever you like to create
whatever range you need.
Okay, now the rand.
If you look at the rand function in the documentation, it
says that it returns a random number between 0 and rand max.
I have no idea what rand max is on my system.
It'll probably be different on your system.
But it's guaranteed to be at least 32767.
So I'll run it here, and we'll see what we get.
Now this function right here is the one that's seeding
the random number generator.
Remember, we want to seed this random number generator
with a different number every time that we run this program.
So what better way to seed it than with the system time.
And that's what's going on right here.
I'm seeding the random number generator to -- I'm calling
the time function and passing in a null pointer which is 0.
This line of code right here you can see an example of that in the
docs that I showed you earlier, it shows you exactly how to seed
the random number generator.
So now we've seeded the random number generator.
And what we want to do is we want to generate 10 random numbers.
So I'm going to start from I equals 1, while I is less than or equal to count.
So I'm going from 1 to 10 by 1, there's my increment.
And then each iteration of the loop, I'm going to call rand.
Rand returns a number between 0 and 32767 or higher in this case.
I have no idea what rand max is on my system.
We'll see in a minute.
I need to really scale that number down.
Because I only want numbers between 1 and 6.
So if I take rand and I take the modulus of it, based on max,
right, so take rand divide it by 6 and whatever the remainder is,
I've scaled that number down now.
So in this case, if I divide a number by 6, the remainder's either
going to be 0 1 2 3 4 or 5, right.
Those are the only options I have.
But since I want to go 1 to 6, I just add min into it, and it's as simple
as that, so that's going to give me a number 1 through 6 inclusive.
And I'm going to output it.
So let's run this program and see how it runs here.
I'll build and run.
And rand max on my system is 32767.
So now we know what it is.
And here you can see that I'm generating 10 random
numbers 1 through 6.
So I'm getting two 2s, a 5, a 3, a 1, a 2 and so forth.
If I run this, remember the, the first sequence there is 2 2 5.
So let's run this again and now I've got 4 6 3 as the first three numbers.
And I'll run this again.
And now I've got 2 2 1 and so forth.
Now if we did not see that random number generator, let me
comment that line out right here.
If I don't see that and run it again, you can see 66556.
Okay, let me run it again, 66556.
So we see the numbers are random but the sequence
that we're getting is not.
We're always going to get the same sequence of numbers.
Now that could be useful sometimes if you're trying to repeat
experiments and so forth, but usually you don't want that.
And that's why we see the random number generator here.
So there you go.
You see a couple of examples of using some built-in functions we use the
math library and we're using the random number generation library,
and we're using the c standard library to generate random numbers.
None of this do we really care about how the random number
generator works unless that's what really interests you and you can
dig into the libraries and see exactly what algorithms they use.
But if I need to create random numbers, this is how i do it.
Really easy.