- Richard Feynman -
C:Functions
Contents
Meta information about this chapter
Expand using link to the right to see the full content.
Introduction
We have discussed grouping together actions. Naming them was something that is obvious in real life. The same goes for programming - it is possible to give a block of code a name and ask the computer to execute the code.
In this lecture we will discuss the function (or method) concept. We will spend a lot of time on this concept since it is important to get right.
Before writing your own functions or methods we believe it is good to get familiar with how to use functions or methods written by someone else - a bit like reading first and then learning to write.
Imagine your friend is really good at calculating how long time it is to her birthday. You are curious and want to know how long time it is to your birthday and ask your friend to calculate that. She will say that she can't because she doesn't know when your birthday is. So you supply her with your birth date. The information you supply is called parameter.
Just as you want something back when asking a question you may want to store a value that a function/method has calculated. Using return values of function/methods is the way to do achieve this.
Purpose
In programming languages such as C, C++ and Java code is structured using functions/methods. In practice it would be pointless to learn such languages without proper knowledge of functions/methods.
The purpose of this lecture is to teach the function/method concept and in doing so making it possible for the student to write more meaningful programs.
It would be useless to have functions and methods and not being able to use them. This lecture introduces how to invoke a function/method.
Writing reusable, structured and more general way is easier achieved with using parameters to your function.
Using functions/methods is a good way to structure your code and to make your code reusable. Return types makes the function/method feature more powerful since you can, among other things, assign different variables the value returned by your function/method.
Requirements
The student shall be familiar with the following concepts:
- variable
- block
- operator
- expression
- type
Goal
The student shall:
- understand the function/method concept
- understand the life time of variables in functins/methods
- read and understand code using functions/methods
- write new functions/methods
- decide what return type to use for a method
- be able to invoke a simple function/method
- be able to create function/methods that takes data as input (arguments/parameters)
- be able to create function/methods that has a return type, as opposed to void.
Instructions to the teacher
Common problems
Chapter videos
All videos in this chapter:
- Functions (eng)
See below for individual links to the videos.
What is a function?
Description
Just a brief introduction to functions.
Videos
Whats is a function (eng) (pdf)
Exercises
1
What is a function?
Solutions
Expand using link to the right to see the full content.
1
A named block of code. The function can be used to reduce code (by reusing the block) and to separate your program into smaller modules.
Links
Invoking function
Description
Videos
Invoking functions (eng) (pdf)
Exercises
In the following exercises we want you to use the files time-date.c
and time-date.h
in
You can find complete source code to the suggested solutions below in the function/get-time
directory in this zip file or in the [{{{vcs-link}}} git repository]. (You can ignore the file main.c
).
In the folllowing exercises we assume you name the file inv-exercise-01.c
, inv-exercise-02.c
etc.
An API description for time-date.h can be found here: time-date.pdf
1
Write a program that invokes the function void
print_current_date();
. This function is located in the time-date.c
and
time-date.h
so you need to:
-
#include "time-date.h"
- add
time-date.c
to the gcc command line - write a main function - that invokes
void print_current_date();
Assuming the files time-date.c
and
time-date.h
have been downloaded to the same directory as
your c file, you can type:
gcc time-date.c inv-exercise-01.c -o inv-exercise-01 && ./inv-exercise-01
2
Write a program that invokes the function void
print_current_date();
five times. The function shall be called
explicitly (no loop of any kind).
3
Write a program that invokes the function void
print_current_date();
five time using a for-loop.
4
Write a program that invokes the function int
current_month();
and stores the result (returned value) in
a variable.
Print out the value of the variable.
5
Write a program that prints the day of the month (today).
Hint: Use the function int current_day();
Solutions
Expand using link to the right to see the full content.
1
Source code:
#include <stdio.h>
#include "time-date.h"
int main ()
{
print_current_date();
return(0);
}
To compile and execute:
gcc time-date.c inv-exercise-01.c -o inv-exercise-01 && ./inv-exercise-01
2
Source code:
#include <stdio.h>
#include "time-date.h"
int main ()
{
print_current_date();
print_current_date();
print_current_date();
print_current_date();
print_current_date();
return(0);
}
To compile and execute:
gcc time-date.c inv-exercise-02.c -o inv-exercise-02 && ./inv-exercise-02
3
Source code:
#include <stdio.h>
#include "time-date.h"
int main ()
{
int i ;
for (i=0; i<5; i++)
{
print_current_date();
}
return(0);
}
To compile and execute:
gcc time-date.c inv-exercise-03.c -o inv-exercise-03 && ./inv-exercise-03
4
Source code:
#include <stdio.h>
#include "time-date.h"
int main ()
{
int month = current_month();
printf("current month: %d\n", month);
return(0);
}
To compile and execute:
gcc time-date.c inv-exercise-04.c -o inv-exercise-04 && ./inv-exercise-04
5
Source code:
#include <stdio.h>
#include "time-date.h"
int main ()
{
printf("current month: %d\n", current_day());
return(0);
}
To compile and execute:
gcc time-date.c inv-exercise-05.c -o inv-exercise-05 && ./inv-exercise-05
Passing information
Description
Just a brief introduction to functions.
Videos
Passing information (eng) (pdf)
Exercises
1
Use printf
to output the text "Hello C".
2
Use printf
to output the text "Hello C\n".
What will differ between this and the previous exercise. Why?
3
In this and the following exercises we want you to use the files
time-date.c
and
time-date.h
in
You can find complete source code to the suggested solutions below in the function/get-time
directory in this zip file or in the git repository.
Use the function print_month_name
in the time-date.c
file. Print the name of the second (2) month using this function.
4
Use the function print_month_name
in the time-date.c
file. Print the name of all months in the same way you did in the previous exercise.
Hint: Use a for loop for (i=1; i<=12; i++)
5
Use the function print_month_name
in the time-date.c
file. Print the first 24 months in the same way you did in the previous exercise.
Hint: Use a for loop for (i=1; i<=24; i++)
Solutions
Expand using link to the right to see the full content.
1
Source code:
#include <stdio.h>
int main ()
{
printf("Hello C");
return(0);
}
To compile and execute:
gcc passing-exercise-01.c -o passing-exercise-01 && ./passing-exercise-01
2
Source code:
#include <stdio.h>
int main ()
{
printf("Hello C");
return(0);
}
To compile and execute:
gcc passing-exercise-02.c -o passing-exercise-02 && ./passing-exercise-02
This time, we've added "\n" to the argument. By doing this we ask
printf
to add a newline at the end of "Hello C". You
should see a difference, compared to the previous exercise, in the
output reflectiong this.
3
Source code:
#include <stdio.h>
#include "time-date.h"
int main()
{
print_month_name(2);
return(0);
}
To compile and execute:
gcc passing-exercise-03.c time-date.c -o passing-exercise-03 && ./passing-exercise-03
4
Source code:
#include <stdio.h>
#include "time-date.h"
int main()
{
int i;
for (i=1; i<=12; i++)
{
print_month_name(i);
}
return(0);
}
To compile and execute:
gcc passing-exercise-04.c time-date.c -o passing-exercise-04 && ./passing-exercise-04
5
Source code:
#include <stdio.h>
#include "time-date.h"
int main()
{
int i;
for (i=1; i<=24; i++)
{
print_month_name(i);
}
return(0);
}
To compile and execute:
gcc passing-exercise-05.c time-date.c -o passing-exercise-05 && ./passing-exercise-05
Links
Getting something back from a function
Description
Just a brief introduction to functions.
Videos
Getting something back from a function (eng) (pdf)
Exercises
In the following exercises we want you to use the files
time-date.c
and
time-date.h
in
You can find complete source code to the suggested solutions below in the function/get-time
directory in this zip file or in the git repository.
1
The function current_month_name()
gives you a string
containing the name of the current month - we currently don't need to
know more than this. To print this string you simple do:
printf("Current month: %s\n", current_month_name());
or
char *month = current_month_name();
printf("Current month: %s\n", month);
Note: Currently we do not yet know what char *
means. In short this is the way to store a string of characters, e g "Hi there".
2
The function month_name()
is a bit like the function
current_month_name()
. The difference is that instead
of using the current month it uses the month passed as an argument by
the caller.
So the following code should print out "March":
char *month = month_name(3);
printf("Month: %s\n", month);
Write a program that prints out the name of the first (1) month.
3
Loop through the month numbers (1..12) and print the month names.
Hint: Use a for loop for (i=1; i<=12; i++)
4
What happens if you pass a faulty argument, such as:
-
14
-
-1
5
Try compiling the previous code while adding -Wconversion
as an command line flag to gcc
.
gcc -Wconversion time-date.c getting-exercise-06.c -o getting-exercise-06 && ./getting-exercise-06
Try to explain what happens.
Solutions
Expand using link to the right to see the full content.
1
Source code:
#include <stdio.h>
#include "time-date.h"
int main ()
{
printf("Current month: %s\n", current_month_name());
/* alt.
char *month = current_month_name();
printf("Current month: %s\n", month);
*/
return(0);
}
To compile and execute:
gcc getting-exercise-01.c time-date.c -o getting-exercise-01 && ./getting-exercise-01
2
Source code:
#include <stdio.h>
#include "time-date.h"
int main ()
{
printf("Month: %s\n", month_name(1));
return(0);
}
To compile and execute:
gcc getting-exercise-02.c time-date.c -o getting-exercise-02 && ./getting-exercise-02
3
Source code:
#include <stdio.h>
#include "time-date.h"
int main ()
{
int i;
for (i=1; i<=12; i++)
{
printf("Month: %s\n", month_name(i));
}
return(0);
}
To compile and execute:
gcc getting-exercise-03.c time-date.c -o getting-exercise-03 && ./getting-exercise-03
4
Source code:
#include <stdio.h>
#include "time-date.h"
int main ()
{
printf("Month: %s\n", month_name(-1));
printf("Month: %s\n", month_name(14));
return(0);
}
To compile and execute:
gcc getting-exercise-04.c time-date.c -o getting-exercise-04 && ./getting-exercise-04
It compiles and it executes without any crash. The first month (14) seems to be printed ok ("February") but the second one ("March") seems to malfunction - one would expect month -1 to be December?
5
We instruct the compiler to look for implicit (not done explicit by us) type conversions. This is quite useful. The purpose of this exercise was to make you aware of that you can ask gcc to look for more errors.
From the gcc manual:
-Wconversion Warn for implicit conversions that may alter a value. This includes conversions between real and integer, like "abs (x)" when "x" is "double"; conversions between signed and unsigned, like "unsigned ui = -1"; and conversions to smaller types, like "sqrtf (M_PI)". Do not warn for explicit casts like "abs ((int) x)" and "ui = (unsigned) -1", or if the value is not changed by the conversion like in "abs (2.0)". Warnings about conversions between signed and unsigned integers can be disabled by using -Wno-sign-conversion.
We're not exepecting you to understand all of this. Again, the purpose was to make you aware that by adding options/flags to your command line you can get a lot of help from the compiler.
Links
Writing your own
Description
A brief introduction to how to write your own functions.
Videos
Writing your own functions (eng) (pdf)
Exercises
1
Write your own function to calculate and return the maximum value of two integers. The function shall:
- be called
max()
- return an integer value
- take two parameters/arguments
- be stored in a file called
mathematics.c
with a
corresponding file mathematics.h
.
- the function shall not print anything
Hint: The prototype of the function shall look like: int
max(int first, int second);
2
Write a small program to test the max function. The program shall be
stored in a separate file. Typically you test your max
like this:
int ret = max(12, 13);
if (ret != 13)
{
printf("Test failed\n");
}
ret = max(13, 12);
if (ret != 13)
{
printf("Test failed\n");
}
printf ("All tests passed\n");
Note: This is a rather expensive (lots of lines of code) way of writing code. Adding more tests will add lots of lines of code.
3
Add to your mathematics.c
with the
corresponding file mathematics.h
a function
min
that calculates the minimum value of two integeres
and returns it. The function shall not print anything.
4
Write a test of min in a similar way as you did with max.
5
If you want to give it a try - feel free to skip this exercise - you can use a small test program we've written so you can verify the min and max functions. Download [https://github.com/progund/programming-with-c/blob/master/function/writing-own/test-mathematics.c test-mathematics.c] and compile and execute like this:
gcc test-mathematics.c mathematics.c -o test-mathematics && ./test-mathematics
Note: did you know you can download the file using curl?. Try this:
curl
https://raw.githubusercontent.com/progund/programming-with-c/master/function/writing-own/test-mathematics.c
-o test-mathematics.c
.
6
Add a function print_max(int first, int second);
that
prints the maximum value of the two parameters. Use the operator
<
or >
to check which integer is the
biggest.
Write some tests of this function in a separate file.
7
Same as previous function but make sure you use the function
max
instead of the operator.
Use the same test file as in the previous exercise.
8
Add a function print_min(int first, int second);
that
prints the minimum value of the two parameters. Use the function
min
instead of the operator.
Write some tests of this function in a separate file.
9
We shall now use the time-date.c and time-date.h files again.
Write a program that uses the input given by the user on the command line (just as you give input to the compiler when typing something like gcc file.c
. We have provided a short template code how to do this:
int get_int(int argc, char **argv)
{
if (argc<2)
{
return -1;
}
int ret;
if (sscanf(argv[1], "%d", &ret) == 1 )
{
return ret;
}
return -1;
}
Copy/paste the code above to a new file and use the function like this:
int month = get_int(argc, argv);
Make sure that your main function looks like this:
int main(int argc, char **argv)
{
followed by the rest of the code. In short this is a way to get hold of the arguments supplied by the user. This is actually how gcc
is knwoing what files you pass to it.
If you want to test the get_int
function you can write your main function like this.
int main(int argc, char **argv)
{
printf(" the int from the user %d\n", get_int(argc, argv));
You now need to store the returned value and check if it is valid. The
function returns -1
if something went wrong and otherwise
an integer from 0 and upwards.
If the user supplies invalid data you should inform the user of that.
If the user supplies valid data you should print the name of the month.
Examples of how to run the program:
#./write-exercise-09 2
February
#./write-exercise-09 15
March
#./write-exercise-09 -1
Invalid month
10
Write a function int exam_grade(int points)
that
calculates the grade of an exam. The function be stored in a file
called exam.c (and of course a corresponding exam.h file) and shall
return values according to this:
- if points is less than 0 or bigger than 50 then return -1 (error)
- else if points is bigger than 37 , return 2 (pass with compliments)
- else if points is bigger than 24, return 1 (pass)
- else return 0 (fail)
Write a small test program (in a separate file).
Hint: check out the operators || and && by reading Logical operators
11
Write a function course_grade(int exam, int handin)
that
calculates the grade of a course exam based in the grade of an exam
(0, 1 or 2) and the grade of an assignment (0 or 1). The function be stored in the file
called exam.c (and of course the corresponding exam.h file) and shall
return values according to this:
- if any (or both) of the handin or exam has the value 0, then the course grade shall be 0
- else if the exam grade is 2 and the handin is 1, then the course grade shall be 2
- else if the exam grade is 1 and the handin is 1, then the course grade shall be 1
- else -1
Solutions
Expand using link to the right to see the full content.
1
mathematics.c:
int max(int first, int second)
{
if (first>second)
{
return first;
}
return second;
}
mathematics.h:
int max(int first, int second);
2
write-exercise-02.c:
#include <stdio.h>
#include "mathematics.h"
int main()
{
int ret = max(12, 13);
if (ret != 13)
{
printf("Test failed\n");
}
ret = max(13, 12);
if (ret != 13)
{
printf("Test failed\n");
}
printf ("All tests performed - if no error all passed\n");
}
To compile and execute:
gcc write-exercise-02.c mathematics.c -o write-exercise-02 && ./write-exercise-02
3
mathematics.c:
int max(int first, int second)
{
if (first>second)
{
return first;
}
return second;
}
int min(int first, int second)
{
if (first<second)
{
return first;
}
return second;
}
mathematics.h:
int max(int first, int second);
int min(int first, int second);
4
write-exercise-04.c:
#include <stdio.h>
#include "mathematics.h"
int main()
{
int ret = min(12, 13);
if (ret != 12)
{
printf("Test failed\n");
}
ret = min(13, 12);
if (ret != 12)
{
printf("Test failed\n");
}
printf ("All tests performed - if no error all passed\n");
}
To compile and execute:
gcc write-exercise-04.c mathematics.c -o write-exercise-04 && ./write-exercise-04
5
Not applicable.
6
Suggested solution is to add the following to mathematics.c:
#include <stdio.h>
void print_max(int first, int second)
{
if (first>second)
{
printf ("%d\n", first);
}
else
{
printf ("%d\n", second);
}
}
and to mathematics.h:
void print_max(int first, int second);
Suggested test code (write-exercise-06.c):
#include <stdio.h>
#include "mathematics.h"
int main()
{
print_max(12, 13);
print_max(13, 12);
}
To compile and execute:
gcc write-exercise-06.c mathematics.c -o write-exercise-06 && ./write-exercise-06
7
Suggested solution is to change the function print_max in mathematics.c to something like this:
void print_max(int first, int second)
{
// Using >
/*
if (first>second) {
printf ("%d\n", first);
} else {
printf ("%d\n", second);
}
*/
// Using our own max function
printf ("%d\n", max(first, second));
}
Suggested solution is to add the following to mathematics.c:
void print_min(int first, int second)
{
printf ("%d\n", min(first, second));
}
and to mathematics.h:
void print_min(int first, int second);
Suggested test code (write-exercise-08.c):
#include <stdio.h>
#include "mathematics.h"
int main()
{
print_min(12, 13);
print_min(13, 12);
}
To compile and execute:
gcc write-exercise-08.c mathematics.c -o write-exercise-08 && ./write-exercise-08
9
Suggested solution: Suggested test code (write-exercise-09.c):
#include <stdio.h>
#include "time-date.h"
int get_int(int argc, char **argv)
{
if (argc<2)
{
return -1;
}
int ret;
if (sscanf(argv[1], "%d", &ret) == 1 )
{
return ret;
}
return -1;
}
int main(int argc, char **argv)
{
int month = get_int(argc, argv);
if (month<0)
{
printf ("Invalid month\n");
}
else
{
// Any of two below:
//printf ("%s\n", month_name(month));
print_month_name(month);
}
}
To compile and execute:
gcc write-exercise-09.c mathematics.c -o write-exercise-09 && ./write-exercise-09
10
Suggested solution: Suggested test code (write-exercise-10.c):
#include <stdio.h>
#include "exam.h"
/*
*
* The test belows are by no means an optimal way to write tests, but
* they will do for now
*
*/
int main(int argc, char **argv)
{
printf ("Testing exam grade\n");
if (exam_grade(-1)!=-1)
{
printf("-1 failed\n");
}
if (exam_grade(0)!=0)
{
printf("0 failed\n");
}
if (exam_grade(24)!=0)
{
printf("24 failed\n");
}
if (exam_grade(25)!=1)
{
printf("25 failed\n");
}
if (exam_grade(37)!=1)
{
printf("37 failed\n");
}
if (exam_grade(38)!=2)
{
printf("38 failed\n");
}
if (exam_grade(51)!=-1)
{
printf("51 failed\n");
}
printf ("All tests performed - if no error all passed\n");
}
Suggested solution (exam.c):
int exam_grade (int points)
{
if (points<0 || points>50)
{
return -1;
}
else if (points > 37)
{
return 2;
}
else if (points > 24)
{
return 1;
}
return 0;
}
Suggested solution (exam.h):
int exam_grade (int points);
11
Suggested solution: Suggested test code (write-exercise-11.c):
#include <stdio.h>
#include "exam.h"
/*
*
* The test belows are by no means an optimal way to write tests, but
* they will do for now
*
*/
int main(int argc, char **argv)
{
printf ("Testing course grade\n");
if (course_grade(-1,-1)!=-1)
{
printf("-1,-1 failed\n");
}
if (course_grade(0,0)!=0)
{
printf("0,0 failed\n");
}
if (course_grade(0,1)!=0)
{
printf("0,1 failed\n");
}
if (course_grade(1,0)!=0)
{
printf("1,0 failed\n");
}
if (course_grade(1,1)!=1)
{
printf("1,1 failed\n");
}
if (course_grade(2,1)!=2)
{
printf("2, 1 failed\n");
}
if (course_grade(2,2)!=-1)
{
printf("2, 2 failed\n");
}
printf ("All tests passed if no fail messages above\n");
}
Suggested solution (exam.c):
int course_grade (int exam, int handin)
{
if ( (exam == 0) || (handin==0) )
{
return 0;
}
else if ( (exam==2) && (handin==1) )
{
return 2;
}
else if ( (exam==1) && (handin==1) )
{
return 1;
}
return -1;
}
Suggested solution (exam.h):
int course_grade (int exam, int handin);
Links
Chapter Links
Our C FAQ
External links
C Programming/Procedures and functions (from the C Programming wikibook).