Never confuse education with intelligence, you can have a PhD and still be an idiot.
- Richard Feynman -

# C:Functions

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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.

## Chapter videos

All videos in this chapter:

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.

## Invoking function

### 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
```

## 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.

### 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
```

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("-1 failed\n");
}
{
printf("0 failed\n");
}
{
printf("24 failed\n");
}
{
printf("25 failed\n");
}
{
printf("37 failed\n");
}
{
printf("38 failed\n");
}
{
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("-1,-1 failed\n");
}
{
printf("0,0 failed\n");
}
{
printf("0,1 failed\n");
}
{
printf("1,0 failed\n");
}
{
printf("1,1 failed\n");
}
{
printf("2, 1 failed\n");
}
{
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);
```