Hello, and welcome back.
In this lecture, I want to go through a solution demonstration
of our previous challenge which was to create some functions,
mainly the GCD function and a couple function, absolute value
function and a square root function.
I'm going to create a project, and I'm just probably going to name
the project functions, I'm going to close my existing project here.
Going to be another console application.
We haven't really gotten into libraries or any kind
of graphical programming.
This is going to be how about just some functions.
Usually, you want to have a good name there, but this is
just for learning purposes.
So we're kind of just providing generic functions.
If it was a GCD program, I'd write greatest common divisor.
But first thing we're going to do is we're going to implement our
greatest common divisor program.
This is going to be a function that finds the greatest common divisor
between two non-negative integer values and then returns the results.
We should be providing function prototypes as well so that we
can call them and we can place them anywhere in the function.
So let's do that.
For the first function, this is a function declaration.
Why do we make a function declaration, so that we can
invoke it anywhere in the program.
We don't have to actually implement this function above the
main function when we call it.
And it's just good practice, it's very easy to in clear to see what's
going on in the program with all the function declarations at the top.
This is going to return an int.
So remember, function header the first thing you do is you specify the type
of data that's going to be returned.
GCD is going to return an int.
It's going to then name the function which is GCD.
And then inside the parentheses are data that's being passed to the GCD.
And this is going to be also being int.
We're going to pass two items of data.
So we separate those by commas.
We specify the data type for each one and the variable name.
I'm just going to say into u and v.
And then I have the semicolon to end the definition of the function.
Now I can define my function below the main and I can still invoke it
and not get to have any problems.
So now when you want to actually define the function implement
it, you do the same function header int return value GCD.
It has to match up with the declaration in terms of types.
You could name it something else like int x for the names, but
we're going to be consistent.
We're just going to say int v.
We know it's the function definition because there's
brackets that define the body.
This is the implementation code.
The actual algorithm for the GCD is quite simple.
All you have to do is write a loop and go through the loop and look
at temp values based on remainders.
So I'm going to create a local variable inside my GCD function.
How do we know it's local because it's inside the brackets for 12 to 14.
This variable is not accessible inside the main function.
It's only local to this block.
Here I'm just going to call temp since it's local.
I'm also going to now create my loop.
I'm going to use a while loop.
And my while loop is just going to go until v, which would be
our greatest common divisor.
Remember, the greatest common divisor takes two parameters.
It would take a parameter.
And based on both those parameters, it has an algorithm to create to
find the greatest common divisor.
So if we're trying to find the divisor, we have to make
sure that v is not equal to zero, our second parameter.
This is just standard parts of the algorithm.
While the v is not equal to zero, we're going to
put brackets for the loop.
What we're going to do is we're going to first assign the temp
to the modules value of u mod v.
We're then going to set u equal to v, and we're going
to set v equal to temp.
And then we want to return data from this function.
So how do we return data from a function? we use the return
keyword, and we just return the data that we want to return.
In this case, we want to return u.
Now remember that if this function didn't return any data, we would
have to change the type to void.
And then we could just have a return with no data.
But this is returning data.
So we have to match up.
And here's we would say return again u.
Also if we were not passing data to this function, we could put
void as the parameters or we could keep them empty and that would say
that the function takes no data, but we are passing two variables.
And these variables u and v are local variables to the GCD function.
We can use them inside the function.
And that's what we're doing.
These are all traits of a function.
The return value, the data that you're passing in, using local
variables and then returning data.
All those things pay attention to in the syntax with the brackets and then
also with the declaration at the top.
Now we want to try to test this function.
So we want to test it for all sorts of different things.
Let's go ahead and remember that this function returns data so we probably
want to create a local variable in our main, we'll just call it result.
We can initialize it to zero.
And then we want to basically call the function.
How do we invoke a function?
We just specify the function name followed by the data
that's being passed to it.
Because this function returns data, I'm going to have say result
equals and then the function name.
The function name is GCD.
And I'm going to pass it 150 for my first test and 35.
I'm going to do two other tests to just pass different numbers,
but what I want to do is i want to print out the data that's
being returned the result.
So I'm going to say printf, and i'm going to say the GCD of 150 and 35 is
percentd line feed and then result.
Right. So line 10 is important.
We're getting data back from GCD so we're assigning it to a variable.
And we can call the function passing in two constants here, 150 and 35.
We could also pass variables.
The way that we invoke the function with data passed to it is inside
the parentheses, we put the values separated by commas and then the
semicolon is at the end there.
I want to do multiple tests.
So I'm going to copy lines 10 and 11 and just put in some other data.
I'm going to put in 1026 and 405 and then also 83.
And actually what we could do is instead of returning the variable,
we could actually just put it the call of the function inside the
printf and print it out right there, we don't even have to save it.
So we could just say GCD 83, 240.
We would have to change what we're printing out in terms of
the hard-coded values here, say 1026, 405 and then also 240 and 83.
So let's go ahead and compile that.
Let's make sure we get no errors or warnings.
We have no errors and warnings.
So let's run it.
When we run it, we should see the greatest common divisor
three times for certain numbers.
So we see the GCD of 150 and 35 is 5.
The GCD of 1026 and 405 is 27.
And the GCD of 83 and 240 is 1.
Greatest common divisor means the factors that go into those two
numbers, what's the highest factor.
So 5 goes into 35, and 5 goes into 150.
And that's the highest one.
27 also goes into 405 and 1026, that's the highest one between the two.
So it looks like it's working.
And we covered the basics of passing data and returning data.
Now we want to practice a couple other things in terms of just
algorithms and problem solving.
Let's create another function called absolute value.
The absolute value function is going to return a float and take a float.
It's going to be a very simple function.
So we're going to declare the function up on line five.
We're going to say float absolute value, that's a name followed by
the parameters, and we're just going to say float x, and then
we're going to end a semicolon.
Again, notice the function declaration, the return value, the
parameters specifies with data types and then the name of the function.
We can then go ahead and define this function below the GCD function
and it's going to be very simple.
We define the function with the type that's going to be returned, the name
and then the parameter, just like the declaration except that now we have
brackets to start the block of code.
This is easy because all we have to do is check the parameter that's passing
and check if it's less than zero.
If it's less than zero, then we're just going to assign it the
inverse which would be a minus x.
So if it's a minus value, it's going to multiply by
a minus return a positive.
And we want to return that data.
So we're going to say return x.
Now one thing I mentioned in the lectures that I didn't get to
provide an example for was what if you return data all throughout.
Because we could have a bunch of if statements, and we could be
returning in each if statement.
And so your function can, in theory, have many return statements
if they're inside ifs or loops.
And then you could have one at the bottom.
The issue with this is it's really hard to follow.
If you need to return different parts of your code, basically,
just store the data in a variable and return it at the bottom.
But here this is a simple function.
We're just returning a value.
Let's go ahead and try to use this function and it's really nice
that it takes floats so we can use it with integers and floats.
So I'm going to create a couple variables here
that we're going to pass.
And I'm also going to create an integer.
I'm going to do that at the top of my main.
I'm going to create a float for F1 F2 F3.
And I'm going to create an integer I1.
And I'm going to create another variable that stores the result
but it has to be a float.
So I'm going to have to create another variable
and this is just going to say
absolute value result,
and I'll initialize that to 0.0.
Now I'm going to invoke the function and print out the results.
So I'm going to copy and paste some code here.
I can invoke the function and store the data that's returned or I can just
pass it to the printf function.
I probably want to do some comments here
testing absolute value function.
And when you use the asterisks on a single line, it kind of highlights it a bit.
So here I pasted in just a bunch of calls to the absolute value function and then displayed some results.
So here in 24, I'm calling absolute value with f1.
Remember, f1 is a float.
It's equal to negative 15.5.
I'm going to format the result and print it out.
And then I'm also going to print out f1.
So we're going to see if the result changes by calling the
function than the original.
So I'm going to print out the result of the calling the
function then the original value.
This will tell us if it changed at all.
If it was negative originally and changed to positive.
Doing that on multiple lines for multiple tests.
And then in line 37, the only difference here is that instead of
storing the value in a variable, I'm going to just print it.
So i have to change the results here to the right variable.
So let's do that and.
So down here, I want to do that that.
When I originally wrote the program, I wrote them as separate.
So hopefully, I make no errors here.
And change all the ones i need to change and that should do it.
The other ones actually aren't printing the results of all the
variables, only the ones on line 26.
Otherwise, we're just showing the results.
The first one just shows that it that it changed because
f1 is a negative value.
Well, let's build this.
We have no errors or no warnings.
The output that we want to pay attention to is just
the absolute value output.
So it might be better to actually add some line feeds.
After we display our last one, let's add a couple line feeds.
Easier to read and run this.
So now we see result is 15.5.
So it actually changed it from a negative to a positive
because f1 was originally 15.5.
And all the other results are also positive values.
The last print statement didn't print out the result, it just printed the
value returned from the function.
Looks like it's working.
The last function that i wanted to define was a square root function.
This would be a function that computes the square root of a number.
And if a negative argument is passed, a message will be displayed
and negative 1 will be returned.
So let's define the declaration of this function as float square root
and it takes a float with any name.
And square root is actually going to use the absolute value function.
So we can define it above it and still use it because
of the function declaration.
So let's define it, and it takes a float.
So we're getting pretty handy at defining these functions, data type
for return parameters, brackets.
We're going to create a couple local variables in here.
These can only be accessed inside the block.
This is just going to help with our square root algorithm.
You'll notice here on lines 59, I created a constant variable.
We haven't talked about that, but that's just a way to create a
constant as opposed to using a define.
We created a float variable named epsilon, it's .001, it helps with
our square root calculation to make sure it's in within a given range.
We have a guess which is 1.1 and an absolute value declaration here.
We don't actually need to provide the declaration because we defined
it at top, so I can get rid of that.
Now remember that we have to check the parameters, we want
to do parameter validation.
If the parameter is less than zero, we want to print out a comment
and return a negative value.
So if x is less than zero, print out negative argument to square
root and return a negative one.
Here's where we're going to have multiple return values, and I'll
show you how you can return once and just put it at the bottom.
Otherwise, we have our algorithm for square root.
I'm not going to explain the algorithm because it's not
pertinent to what we're learning.
But basically, to find the square root of a number, we get the
absolute value of it by multiplying it and then minus in the x.
So the guess is we're going to guess.
So originally we're going to guess and then check if this is the algorithm,
check if it's within a certain range.
And if it is, then we're going to set our guess to something and
divide it by two and that's going to be the guess that we return.
So at the very bottom, we would say return guess.
And so we're using the absolute value function.
It's defined below us, but we have our declaration at
the top, so that's good.
One thing here is we have multiple return statements.
This is perfectly legal, but it should be avoided because it's harder to
figure out the um what's going on.
So what I would do here is I would probably store this negative one
in a variable other than guess, but let's see here how we can do this.
So what I would do is guess is initialized to 1.0, and
we're returning a negative one.
I would probably just create another variable called float return value.
We can set this to 0.0.
And then before returning it here because this is jumping out of
the math function, I can just say return value equals negative
1.0 instead of having the return.
Then I can check and I can say if return value is not equal to
a negative 1.0 because I don't want to execute this if I already
have my invalidate number, non-valid number, and I could
wrap this in an if statement.
And then inside the while statement, I can say return value equals guess.
That way I'm returning the correct thing if it was a valid entry.
And then instead of returning guess what I do is I
return the return value.
And this code is a bit cleaner because it only returns once at the
bottom and it's easier to follow.
So return value is either negative one if it's an invalid argument or
it's going to be the actual square root if it's not an invalid argument.
And we could also even make this simple by just actually not
even checking the return value here would probably be easier
to just say else and make the else part of the original if.
So if it's a positive number that would even make it cleaner that way
you don't have that if statement.
Now we need to test it.
Let's go ahead and test this.
We'll just call the function a bunch of times.
We'll say testing square root.
I'm not going to do any fancy printing here.
I'll just make sure that i can add a bunch of line feeds
so that it's easier to read.
Hit the insert button there.
All right. So now I'll just do a bunch of printfs where I'll send in some good
and val data and some inval data and I'll format it the same way.
Let's just say the first call will be square root of what's
some good valid square roots.
Well, first we'll check it with a negative number.
So we'll just say negative 3 that should print out an error.
Otherwise, we'll test it with some valid numbers.
So we'll say the square root of 16, and we'll just pass an int, they'll be
converted, I might get some warnings.
Well, I don't want to get any warnings, and we'll do 165.
Now let's run this and test it.
Let's hopefully, it will compile.
I do have a misspelling with float.
Now when I run it, hopefully, we'll get good square root output.
So here we have a negative one.
And we actually printed out negative argument scores, so that's good.
And then the other ones are, I believe, the correct square roots.
So it looks like the function works pretty good.
We did square root of 16 which is 4, 25 which is 5,
9 which is 3, 165 is 12.85.
So I did some miscalculation there.
I was trying to think of 15 times 15 which is 225.
So if I put 225 in here, it would come back as 15 as a square root.
I'm going to provide this source code for you so you can analyze it, but
understand function declarations, understand how to define a function
with the return type and the parameters passing data, understand
local variables, understand how to return only once at the bottom.
The algorithm itself is not that important.
I hope this helped. Thank you.