Functions

C Language

Breaking the Task Down

As the program gets more complicated, it becomes harder to fit all of your code in the main function that it becomes unclear and hard for people to read that much code, or, when you have something that you need to do multiple times throughout the program, it would be inconvenient if you have to write that same or similar block of code over and over, this is when you need functions. Functions help to break the program down. If the program completes a big task, each function completes a smaller task. For example, when you want to build a calculator program, you can have a function for addition, a function for subtraction, one for multiplication, and one for division. So functions helps to break the program down into clearer pieces where one does a specific task. A way of imagining this is comparing functions to factories, and you put different materials (passing arguments) into the factory and through a series of steps, a product is manufactured (return value).


Parts of a Function

Function in computer is very similar to function f(x) in mathematics. You have a function that does a specific task, for example, adds ten numbers together. Just like in mathematics, you can have f(x)=3x+5. You most likely would have to give the function some information or data needed to perform the operation. For example, in this case, we need to give the function the ten numbers. Just like in math, you need to give the function f(x) an input value, for example f(5) to calculate. The function usually returns a value, typically the result of its operation. So if I have a function that adds the ten numbers, I can return the sum as the return value, or the result of that operation. Similar to in mathematics, you have the result of f(5)=20.

In C, in order to use a function, you first need to declare it, declaring what type of return value it would have, the name of the function, and what parameters (or inputs) the function needs to perform its operations. Then you will write the actual function, and the function will be ready. You can call this function, give it the arguments needed, and let it calculate the result.

#include <stdio.h>

int add(int list [10]) /*This line declares a function add, which calls for
an integral array with 10 elements, and returns an integral result*/
{
  /*Do whatever operations needed here*/
  int i,result=0; /*You can declare variables the the function needs in the function*/
  for(i=0;i<10;i++)
   {
     result+=list [i];
   }
  return result; /*This line tells the computer what value it should return,
in this case, we want to return the sum, which is stored in variable result*/
}

int main() /*As we noted before, main is also a function*/
{
  int numbers [10]={78,29,39,-3,2,39,321,93,100,0};
  int sum;
  sum=add(numbers); /*This line calls the function, which tells the computer to execute the 
function that was called, passing numbers as an argument and storing the returned value in sum*/
  printf("The sum is %d.\n",sum);
}

The sum is 698.

Here is a diagram for calling a function:

We will explain each part of the function in detail below.


Declaration

In a function declaration, there are four basic parts: declaration of what type of value the function will return, the name, a list of parameters, and the actual body of the function. Put function declarations before you call the functions, so we normally put them at the top.
return-type function-name(list-of-parameters)
{
body
}
For example:
int add(int a,int b)
{
return a+b;
}

Return Type

The first part of a function declaration is what the function will return. As you may remember, the return value of a function can be understood as the result of the function's operations. For example, if we have a function for adding two numbers, our return value can be the sum. Therefore, our return type should be an int if both of the numbers are integers. If we have a function that adds two decimals, we an have a float as the return value sum, in that case, we would just change the int to float in then declaration:
float add(float a,float b)
If we have a function that picks out a capital letter in a word string, the return value can be that letter, so we need to return a char value, just change the first word in the declaration to char. In conclusion, whatever type of value your function returns as the result, your first part of the function declaration will be that type.

Sometimes, your function just completes a task or operation like print out a chess board and does not need to return a value. In this case, you can set the return type to void:
void print_board(int board [8][8])
{
/*Print out the board*/
}
By saying the return type is void, the computer will understand that you will not return a value.

Function Name

Function names is the second part of your function declaration following the return type. These names are just the same as variable names (contains only letters, numbers, and underscores). Remember to name your functions names that hints what the function does.

Parameters

Parameters are things that your function needs to perform its task. For example, we cannot calculate the sum of our numbers in the example above without knowing what the numbers are! So that's why we need parameters. You can have as much parameters as you need or not at all for a function. If you don't have any parameters, just put empty parenthesis: int example()
You can add as many parameters as you want, just separate them by commas. For each parameter, it is just like a normal variable declaration: first the type of that variable, and then the name for it (the name here does not need to be the same as the arguments you are passing in, see below for Arguments under Calling a Function section for details).

Here are some examples of more complex function declarations:
int expnt(int base,int power)
/*Function expnt with integral parameters of base and power, return a integral value*/
{ }
int greatest(int a,int b,int c)
/*Function greatest with integral parameters of a,b, and c, return a integral value*/
{ }
char capital(char word [20]) /*This function returns a char, and this is how arrays can be used as parameters*/
/*Function capital with a parameter of a string, return a character*/
{ }
void print_board(int board [3][3]) /*void indicating no return value, and the parameter a two dimensional array of a tic-tac-toe board is shown here*/
/*Function print_board with integral two-dimensional array as argument, no return value*/
{ }

Function Body

The body of the function is between the braces in the declaration. When the function is called, the body is executed.

Variables

Most of the times, you will also need to use variables in your functions. You can define new variables in your function that you need. The declaration of these variables is just the same and you will also use it the same way as variables in the main function. It is very important to know that any variables you declare in one function is only accessable in that function only, these variables are local to that function. On the other hand, variables you declared in the main function or other functions cannot be accessed in this function. If you want to have variables that can be accessed all through the program, you will need to declare global variables, discussed in the last section of this lesson.

Let's look at an example.

Example

#include <stdio.h>

/*Calculate exponents*/
int exponent(int base,int power)
{
  int current;
  int result=1;
  for(current=1;current<=power;current++)
   {
     result*=base;
   }
  return result;
}

In this example, the function named exponent with parameters base and power calculates the exponent of those two numbers. We demonstrated declaring and using local variables, and as you see, it is just the same as what you need to do in the main function.

Return Value

As you finish doing your operations in the function, you may need to return a value as the result of your operations. The return statement helps you to accomplish this: return value; after the keyword return, put a constant value (for example 0 or 1 or 'a') or a variable, as demonstrated in the above example, returning the variable result. In a function, you can have multiple return statements, but as soon as the computer encounters one, it returns that value to the calling function and terminates the function. That means, you can have some extra return statements in if-structures that covers unexpected situations. As soon as the computer encounters the return statement, it terminates the function immediately similar to what break statements do to a loop, but returning the value. However, no matter how many return statements you put, the function can only return 1 value, if your function's result is multiple values, you can either declare global variables (see below), or use pointers (next lesson). How this return value can be used is explained further in the section below: Calling a Function.

Other

Besides those, you can put anything in your function just like you do in main function to complete the function's task.

Calling a Function

Now the function is declared, but how do you use it? Using the function is called "calling" it. You can call a function in the main function, in another function, or even in that function itself. As you might know, printf and scanf you used are both examples of functions. As you use them, you are calling the function. To call a function, just put the function's name, and inside a pair of parenthesis, the list of arguments that you want to pass in. For example, to call the function in the example above, just put:
exponent(5,3);
and the function will calculate 5^3. The arguments you pass in, of course, can also be variables, like: exponent(input_b,input_p); As you probably noticed, we didn't do anything with the return value. The exponent function returns an integer as the result of the operation, so when you call that function, that expression actually evaluates to the return value, to get that value that is the result of the function, just have an assignment to a variable to get that value:
result=exponent(5,3);
This will assign result the return value of exponent(5,3), which is 125.

Another important thing to note is that although the arguments that you are passing needs to match the parameters exactly for the type of the variable and the amount of arguments, the names for the arguments and parameters does not need to match. For example, if I call the exponent function, the parameters asked for int base,int power; but you can pass in exponent(input_1,input_2), and it will work the same.

Also, it is very important to know that when you are calling a function and passing arguments in it, the arguments you passed in are evaluated to constant values and then assigned to the parameters, so any changes you make to these variables (the parameters) in a function will not take effect on the arguments you pass in. For example, if you pass a variable num to a function, and in that function you set num to 0, the original num will not be affected. Whatever you do in that function will only take affect on the variable in that function. This has the exception of pointers (see next lesson), and arrays (which are actually pointers), and strings (which are arrays), if you change the values of these variables in a function, the variables in the original function will be affected.

Here are some examples:

Examples

#include <stdio.h>

int exponent(int base,int power)
{
  int current;
  int result=1;
  for(current=1;current<=power;current++)
   {
     result*=base;
   }
  return result;
}

int main()
{
  int base,power;
  int result;
  printf("Enter an exponential expression:");
  scanf("%d^%d",&base,&power);
  result=exponent(base,power);
  printf("%d^%d=%d\n",base,power,result);
}

Enter an exponential expression:5^3
5^3=125

#include <stdio.h>

float calc_mean(int list [10])
{
  int i,sum;
  float mean;
  sum=0;
  for(i=0;i<10;i++)
   {
     sum+=list [i];
   }
  mean=sum/10.0; /*We divided by 10.0 instead of 10 to make sure the division gets
a decimal result, not just a rounded integer*/
  return mean;
}

int main()
{
  /*Calculate the mean of a set of given numbers*/
  int numbers [10]={45,78,-3,98,23,36,29,93,92,-89};
  float mean;
  mean=calc_mean(numbers);
  printf("The mean of the ten numbers is:%f\n",mean);
  /*The result here should be 40.2, but the result printed is 40.200001 because just
like there are repeating decimals in base 10, in binary, some numbers cannot be represented
exactly*/
}
	

The mean of the ten numbers is:40.200001

#include <stdio.h>

void print_star()
{
  printf("  *  \n * * \n* * *\n * * \n  *  \n");
}

int main()
{
  print_star();
  /*Demonstrating calling a void function and a function with no parameters*/
}

  *  
 * * 
* * *
 * * 
  *  

Recursion

You can call a function anywhere, in main, in another function, or in the function itself. The concepts for the three works exactly the same. When the function is called, the computer executes the body of the function and returns the return value. When you call a function in the function itself, it is called recursion. It is sometimes very useful (but sometimes it can be very tricky to debug).

/*Exponent program, recursion version*/
#include <stdio.h>

/*Recursion can be very complex and abstract for new programmers*/
int exponent(int base,int power)
{
  int result;
  /*When power is greater than 1, simplifies the expression to: base^(power-1)*base*/
  if(power>1)
   {
     /*exponent function handles base^(power-1)*/
     result=exponent(base,power-1)*base; /*Recursion calling is just the same as normal ones*/
   }
  /*When power==1, set the result to base*/
  else
   {
     result=base;
   }
  return result;
}

int main()
{
  int base,power;
  printf("Enter an exponential expression:");
  scanf("%d^%d",&base,&power);
  printf("%d^%d=%d\n",base,power,exponent(base,power));
}

Enter an exponential expression:5^3
5^3=125

Global and Local

Sometimes, you want some values to be accessable for all functions. This is best done with pointers, which will be discussed in the next lesson, but another way of doing so is creating global variables (because there are pointers, it is not recommended for people to create global variables). Local variables are variables that can only be used inside the function it is declared in, while global variables are created so all of the program can access it.

Creating global variables is just the same as creating local ones, just that they are declared outside of functions, usually at the top of the program after the include statements. They are used just like local variables.

Again, global variables are not recommended, use pointers instead.

#include <stdio.h>

/*Declare a global variable*/
int greatest;
int least;

/*Find the greatest and least value*/
void find_gl(int list [10])
{
  int i;
  greatest=list [0];
  least=list [0];
  for(i=1;i<10;i++)
   {
     if(list [i]>greatest)
      {
        greatest=list [i]; /*Global variables can be accessed anywhere*/
      }
     if(list [i]<least)
      {
        least=list [i];
      }
   }
}

int main()
{
  int numbers [10]={56,82,-3,82,0,39,29,102,39,-32};
  find_gl(numbers);
  printf("The greatest number in the list is %d;\nThe least number in the list is %d\n",
greatest,least);
}
	

The greatest number in the list is 102;
The least number in the list is -32

Practice

Debug the following program:

#include <stdio.h>

/*This function counts how many sentences are in a string*/
int count_sntc(string)
{
  int i;
  for(i=0;i<500;i++)
   {
     if(string [i]=='.' || string [i]=='!' || string [i]=='?')
      {
        count++;
        return count;
      }
   }
}

int main()
{
  char string [500];
  int count;
  printf("Enter a string:");
  scanf("%s",string);
  count_sntc(string);
  printf("There are %d sentences.\n",count);
}

Write a program to calculate the factorial of an inputted number.

Write a program to sort an array of 10 numbers from least to greatest.

Challenge: write a program that has a function using recursion to print out the steps of solving the Hanoi Tower Problem, the user inputs the amount of disks.

Additional practice on functions:

Activity 10.2 (tic-tac-toe project)

<< Previous TOC Next >>