Extracting Repetitive Code Into a Function
Consider the following program:
// step 1.
#include <stdio.h>
int main()
{
double pi = 3.14159;
double radius1 = 3.0;
double area1 = radius1 * pi;
printf("The area of the circle is: %lf\n", area1);
double radius2 = 6.0;
double area2 = radius2 * pi;
printf("The area of the circle is: %lf\n", area2);
return 0;
}
This code repeats the the same logic for calculating the area of a circle in two different parts of the code.
We can reduce this with a function.
// step 2.
#include <stdio.h>
// first we define a basic function body without changing
// the rest of our code. Remember to save/recompile/run
// after each step.
void areaOfCircle()
{
}
int main()
{
double pi = 3.14159;
double radius1 = 3.0;
// we can see from this calculation that the value
// of the area calculation is of type double.
// therefore our function return type should be
// of type double
double area1 = radius1 * pi;
printf("The area of the circle is: %lf\n", area1);
double radius2 = 6.0;
double area2 = radius2 * pi;
printf("The area of the circle is: %lf\n", area2);
return 0;
}
// step 3.
#include <stdio.h>
// Here we've given the function the correct return type.
// What parameters if any should we define for this
// function - i.e. what arguments will we need to give
// to this function when we invoke it, so that it can
// calculate the radius?
double areaOfCircle()
{
return 0;
}
int main()
{
double pi = 3.14159;
// Radius is an obvious choice. In order to calculate
// the area of the circle we need to know its radius.
// What about the value of PI? We also need that to
// calculate area - should we make that a paremeter
// as a well?
double radius1 = 3.0;
double area1 = radius1 * pi;
println("The area of the circle is: %lf\n", area1);
double radius2 = 6.0;
double area2 = radius2 * pi;
println("The area of the circle is: %lf\n", area2);
return 0;
}
// step 4.
#include <stdio.h>
// We've added radius as a function parameter. We've given it a
// type of double. There is no reason for this calculation to
// use values of different types - therefore we make it consistent
// with the value of PI and the area that we will return. We don't
// need to pass the value of PI as an argument. The value of PI is
// constant and there is no reason when calling this function
// that we would ever want it to use a different value. So, what
// goes in the function body?
double areaOfCircle(double radius)
{
return 0;
}
int main()
{
double pi = 3.14159;
double radius1 = 3.0;
// the purpose of this function is to calculate a value, so
// naturally the function body should contain the calculation
// for the area of a circle.
double area1 = radius1 * pi;
printf("The area of the circle is: %lf\n", area1);
double radius2 = 6.0;
double area2 = radius2 * pi;
printf("The area of the circle is: %lf\n", area2);
return 0;
}
// step 5.
#include <stdio.h>
// In the function body, we calculate the value of the area
// by using the radius that is given to the function when invoked.
// We return that value to the code that called the function.
// Note that we could have assigned pi to a variable here like we did
// below, but it's not needed.
double areaOfCircle(double radius)
{
return radius * 3.14159;
}
int main()
{
double pi = 3.14159;
// now we can get replace most of this with a function call
double radius1 = 3.0;
double area1 = radius1 * pi;
printf("The area of the circle is: %lf\n", area1);
double radius2 = 6.0;
double area2 = radius2 * pi;
printf("The area of the circle is: %lf\n", area2);
return 0;
}
// step 6.
#include <stdio.h>
// remember to do one thing at a time and save/recompile/run each time
double areaOfCircle(double radius) {
return radius * 3.14159;
}
int main() {
double pi = 3.14159;
printf("The area of the circle is: %lf\n", areaOfCircle(3.0));
double radius2 = 6.0;
double area2 = radius2 * pi;
printf("The area of the circle is: %lf\n", area2);
return 0;
}
// step 7.
#include <stdio.h>
double areaOfCircle(double radius) {
return radius * 3.14159;
}
int main() {
// Note that we no longer need the variable for PI
printf("The area of the circle is: %lf\n", areaOfCircle(3.0));
printf("The area of the circle is: %lf\n", areaOfCircle(6.0));
return 0;
}
So what makes the code in step 7 better than the code in step 8?
For one thing the main logic of our program is more concise and in some ways easier to follow. While we now have to take into account there's a bit of misdirection when we call the function, as opposed to the normal top down flow, the function is clearly named - so it doesn't feel like we're doing anything out of sorts. You can read that code and clearly see that its intent is to print the area of two circles with different radii.
By reducing repetition of calculations we've reduced the likelyhood of bugs in our program. When logic is repeated there are more chances to make a mistake. Also, when logic is one place, and you do make a mistake, it's easier to fix it because you only need to do it one time and you know that it will be correct everywhere you use it.
Writing reusable units of code underpins the entire enterprise of computer programming. By consolidating important logic into functions or groups of functions called libraries, you're able to use it later in another program, share that work with others, sell it, etc. There's a bit more work involved in turning our area function into the start of a code library - we might cover that at later time in class.