# Arrays and functions in C++
###### tags: `Computer Science` `IB`
[ToC]
:::warning
These notes supose that you have a very basic knowledge of programming in C++, what is the setup, the loop and how an instruction needs semicolon.
I will explain step by step but there are some parts that should be understood by now.
:::
## Functions in C++ (and other Programming Languages)
In programming since we have to deal with very complex problems we have a way to divide our algorithms in smaller parts using **functions** (also called "actions" in Object Oriented Programming, "subprocedures" in IB, "methods" in Java).
These functions are **portions of code that are executed anytime that they are called.**
One way to see this is a doorbell

([source](https://www.publicdomainpictures.net/es/view-image.php?image=212432&picture=viejo-timbre-de-puerta))
Anytime that you press the button (the call) the bell is going to ring (execute the function). If you press twice, the ring is going to ring twice and so on.
## Definition and call
To use a function it needs to be defined and implemented. That definition can be done by us or we can use a library and directly call it.
For example in the code of blink of arduino we have 5 intructions that are 5 calls of 3 functions:
```cpp=
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
```
In this case we are calling the functions called ```pinMode()```, ```digitalWrite()``` and ```delay()``` . In this case we don't have to implement (that means to actually do the inner workings) these functions. They are already defined in a **library** called arduino.h and we just access to it. In programming is common to use functions that are already defined.
But when we did the morse code we actually defined the dot() and dash() functions in our code.
In those examples we had a code similar to this
```cpp=
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
dot();
dash(); //repeated some times to get the message
}
void dot() {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
void dash() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
```
Here in the lines 6 and 7 we can see the call of the functions and in the lines 10 to 15 we see the **implementation** of dot() and from lines 18 to 23 the **implementation** of dash()
:::warning
In an exam you can be asked to write the implementation of a function (in IB it's called method or subprocedure) and/or just use it, using a call.
:::
We will get into more detail of the syntax later, before we need to get into the surroundings of it. We need to talk about parameters and return values.
:::info
**Call, definition an implementation**
To be precise
A **function call** is an expression containing the function name followed by the function call operator, usually "()". If the function has been defined to receive parameters, the values that are to be sent into the function are listed inside the parentheses of the function call operator. This will execute the function and return the value if it's defined [source](https://www.ibm.com/docs/en/i/7.3?topic=operators-function-call-expressions)
A **function definition** includes the name the parameters that are required and the return type if any.
The **implementation of a function** is the code that is actually executed. The particular solution that, in C++ is inside the brackets.
:::
## Parameters and return values
One of the best things that are implemented in functions in almost all modern programming languages is that functions can have parameters and return values. This means that we can make a function that can be used in different circumstances.
### Parameters
Take as an example the function delay(). This function accepts a parameter with the number of milliseconds that we want to wait.
```cpp=
void setup() {
}
void loop() {
delay(1000); // Wait for a second
delay(500); // Wait for a half a second
delay(2000); // Wait for 2 seconds
}
```
If we didn't have that, then we would have need to have a definition of a delay of a specific number of milliseconds (such as 10 milliseconds) that we would need to repeat as needed.
Being precise, a parameter (or argument) is a variable provided as an input to the function. A function can have none, one or several parameters. When the function is defined the number of parameters is set. When the function is called the parameters has to been sent.
:::info
We can define two functions with the same name and different number or type of parameters. This is called "method overload" because we are "charging" one name of a function (method) with more than one definition. This is called also polymorphism. This is done in Java (Option D for IB)
For more info in this [LINK](https://data-flair.training/blogs/polymorphism-in-java/) or this other [LINK](https://www.mygreatlearning.com/blog/polymorphism-in-java/)
:::
### Tone() an example of use in detail
An example of use in C++ is the function tone(pin, frequency, duration). You can check more on that in the reference of Arduino [here](https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/)
In the case o this method you need to send 3 parameters (or arguments) to this function to work.
The first is the pin (a number), the second is the frequency also as a number and the third is the duration of the sound.
So if we write a program like this:
```cpp=
void setup() {
tone(8, 440, 5000);
}
void loop() {
}
```
The arduino is going to emit a sound in the pin number 8 on a frequency of 440 Hertz (a A4) during 5 seconds.
We can use variables not to repeat values and be more clear. For example look at this example
```cpp=
const int BUZZER_PIN = 8;
int time = 500;
void setup() {
}
void loop() {
tone(BUZZER_PIN, 440, time);
delay(time);
noTone(BUZZER_PIN);
delay(1000);
time = time + 500;
}
```
This program will send a sound of half a second then will make a pause of a second (the second delay in line 11). After this it will repeat the same procedure but the time sounding will be longer (the silence will be the same). This will go on until we reach the end of the boundaries of the int type (around 32 000).
To avoid that limitation we can add an if that puts a limit when we go over 32000. We also may use another numeric type (long) for the same variable that can go on for longer. Long can get to values around [32 000 000 000](https://www.arduino.cc/reference/en/language/variables/data-types/long/) (way more than int).
This is the option if we have a cap and we decide to reset the duration, that use an if.
```cpp=
const int BUZZER_PIN = 8;
int time = 500;
void setup() {
}
void loop() {
tone(BUZZER_PIN, 440, time);
delay(time);
noTone(BUZZER_PIN);
delay(1000);
time = time + 500;
if (time > 30000) // the condition is not the limit but a little bit earlier
{
time = 500;
}
}
```
This is the version with the long option without cap.
```cpp=
const int BUZZER_PIN = 8;
long time = 500; //this is the only change
void setup() {
}
void loop() {
tone(BUZZER_PIN, 440, time);
delay(time);
noTone(BUZZER_PIN);
delay(1000);
time = time + 500;
}
```
#### Exercise 1
Create an Arduino sketch that creates pulses of 200 milliseconds of duration that increases of tone by 50 from 200 to 1500 and then repeats itself
You can see a solution in the spoiler section
:::spoiler
```cpp=
const int BUZZER_PIN = 8;
int pitch = 200; //this is the only change
void setup() {
}
void loop() {
tone(BUZZER_PIN, pitch, 200);
delay(200);
noTone(BUZZER_PIN);
delay(200);
pitch = pitch + 50;
if (pitch > 1500) {
pitch = 200;
}
}
```
:::
#### Using loops
We can also use a loop for or a loop while to repeat the instuction a certain number of times. Let's say that we want to make 4 times a tone in a pitch (440) and then 3 times a tone in another pitch (880) and then silence. All the tones have a duration of 0.2 seconds
In this example I'm going to use a for loop and a while loop. Can be done with both.
```cpp=
const int BUZZER_PIN = 8;
int time = 200; //the duration
void setup() {
for (int x = 1; x < 5, x ++) //we want to happen 4 times, 1, 2, 3, 4 and when we arrive to 5 it's going to stop
{
tone(BUZZER_PIN, 440, time);
delay(time);
noTone(BUZZER_PIN);
delay(time);
}
int y = 1;
while (y < 4) // 3 times. Values of y: 1, 2, 3
{
tone(BUZZER_PIN, 880, time);
delay(time);
noTone(BUZZER_PIN);
delay(time);
y++;
}
}
void loop() {
}
```
#### Exercise 2
Create an Arduino sketch that creates pulses of 200 milliseconds of duration that increases of tone by 50 from 200 to 1500 and doesn't repeat itself.
Solution in the spoiler section
:::spoiler
Using a while version:
```cpp=
const int BUZZER_PIN = 8;
int pitch = 200;
void setup() {
while (pitch <= 1500) {
tone(BUZZER_PIN, pitch, 200);
delay(200);
noTone(BUZZER_PIN);
delay(200);
pitch = pitch + 50;
}
}
void loop() {
}
```
Using a for version:
```cpp=
const int BUZZER_PIN = 8;
void setup() {
for (int pitch = 200; pitch <= 1500; pitch = pitch + 50) {
tone(BUZZER_PIN, pitch, 200);
delay(200);
noTone(BUZZER_PIN);
delay(200);
}
}
void loop() {
}
```
:::
To sumarize, tone is a function with 3 parameters, the three of them are numbers (pin, frequency and duration).
### Return value
Return of a function is a value (that in C++ or Java also need to have a type specified) that the function is going to return to the point where is it called.
An example would be a function that it's call "add(x, y)" that returns the value of adding x and y. In many programming languages we would use just the operator "+"
```cpp=
int x = 50;
int y = 100;
int z = x + y; //150
```
```cpp=
int x = 50;
int y = 100;
int z = add(x,y); //150
```
#### Example functions with return type
Even if we don't use "add" we have many mathematical functions that we might use in C++, Java or other programming languages. Here some math functions
* max(x,y) returns the maximum value of two values (variables or constants). More info [HERE](https://www.arduino.cc/reference/en/language/functions/math/max/)
* sqrt(x) readed square root, returns the square root of any number in a double type. More info [here](https://www.arduino.cc/reference/en/language/functions/math/sqrt/)
* random(max) and random(min, max). This give a pseudo random number either from zero to max -1 or from min to max - 1
:::warning
In any exam you're not suposed to know these functions, but the exam can describe them to you and you should be able to use them.
:::
#### Example of math functions
We can use random to generate a random melody. With pitches from 200 to 1500 Hz and constant duration
```cpp=
const int BUZZER_PIN = 8;
void setup() {
}
void loop() {
int pitch = random(200,1500);
tone(BUZZER_PIN, pitch, 200);
delay(200);
}
```
We can even make it more _one liner_ like this:
```cpp=
const int BUZZER_PIN = 8;
void setup() {
}
void loop() {
tone(BUZZER_PIN, random(200,1500), 200);
delay(200);
}
```
Remember that each time that we call random is going to return a different number.
#### Exercise 3
Create an Arduino sketch that creates pulses of random duration of milliseconds in a range from 300 to 1200 seconds and intersecated with silences of the same duration. The picth is 440.
Solution in the spoiler section
:::spoiler
```cpp=
const int BUZZER_PIN = 8;
void setup() {
}
void loop() {
int time = random(300,1201); //We need to use a variable to keep the same value the 3 times that we are using it
tone(BUZZER_PIN, 440, time);
delay(time);
noTone(BUZZER_PIN);
delay(time);
}
```
:::
#### Exercise 4
Create an Arduino sketch that creates pulses of random duration of milliseconds in a range from 300 to 1200 seconds and intersecated with silences of the same duration. The pitch is also a pseudo random number from 330 to 660 Hertz.
Solution in the spoiler section
:::spoiler
```cpp=
const int BUZZER_PIN = 8;
void setup() {
}
void loop() {
int time = random(300,1201); //We need to use a variable to keep the same value the 3 times that we are using it
tone(BUZZER_PIN, random(330,661), time);
delay(time);
noTone(BUZZER_PIN);
delay(time);
}
```
:::
#### Exercise 5
:::success
This is one that can be set in the exam since combines functions and also arrays.
:::
Create an Arduino sketch that creates pulses of random duration of milliseconds in a range from 300 to 1200 seconds and intersecated with silences of the same duration. The duration has to be a multiplier of 100 (300,400 and so on). The pitch is selected at random from these pitches 440,292, 880 and 653
The solution with the explanation in the comments is in the spoiler section
:::spoiler
```cpp=
const int BUZZER_PIN = 8;
const int frequencies[] = {440,292,880,653};
// we write the available frequencies in an array so then we select one of those.
void setup() {
}
void loop() {
int time = random(3,13) *100; //we have a random number from 3 to 12 inclusive and then we multiply it by 100
tone(BUZZER_PIN, frequencies[random(4)], time);
// we access to the pitch using a random index that goes from 0 (that points to 440) to 3 (that pints to 653)
delay(time);
noTone(BUZZER_PIN);
delay(time);
}
```
:::
#### Exercise 6
Create an Arduino sketch that creates pulses of random duration of milliseconds in a range from 300 to 1200 seconds. The duration has to be a multiplier of 100 (300,400 and so on). The pitch is selected at random from these pitches 440,292, 880 and 653. One over 3 notes should be a silence.
The solution with the explanation in the comments is in the spoiler section
:::spoiler
```cpp=
const int BUZZER_PIN = 8;
const int frequencies[] = {440,292,880,653,0,0};
// we write the available frequencies in an array so then we select one of those. We write 2 zeros because 2 out of six
void setup() {
}
void loop() {
int time = random(3,13) *100; //we have a random number from 3 to 12 inclusive and then we multiply it by 100
tone(BUZZER_PIN, frequencies[random(6)], time);
// we access to the pitch using a random index that goes from 0 (that points to 440) to 5 (that pints to the second 0)
delay(time);
}
```
:::
#### Other return types
Up to here we have discussed numeric return types but we can have other return types such as booleans, characters or strings. Characters and Strings will be discussed later in the Array section.
#### Boolean return types in funtions
Functions that return booleans usually are in 2 great branches
* Error-returning functions. Functions that do something else and return true if everything went well and false if there was any kind of error.
* Evaluating functions. Functions with the only purpose is to return true or false to validate some variables.
#### Error-returning functions
Error returning functions are common in tasks that can be difficult and may generate any kind of error so the algorithm can do something about it.
For example we might have a function that is called "proofTheLastFermatTheorem()" that makes a very complex mathematical work (more info [here](https://en.wikipedia.org/wiki/Fermat%27s_Last_Theorem)). Makes sense that this is something that sometimes will work and sometimes the computer may not finish. If it finish we print "Hooray" and if it doesn't we print "let's keep working on it"

[source](https://upload.wikimedia.org/wikipedia/commons/f/f3/Pierre_de_Fermat.jpg)
```cpp=
if (proofTheLastFermatTheorem()) {
Serial.println("Hooray!");
}
else {
Serial.println("Let's keep working on it")
}
```
Also sometimes we want to do something only if the things didn't went as expected. Let's say that we need to iniatilize a 3D printer with a method called "initalize3Dprinter(pin)" that has the pin as a parameter where is connected the 3Dprinter. We want to print an error message if something went wrong.
We are going to use the not operator '!' to make it work
```cpp=
if (!initalize3Dprinter(3D_PIN)) {
Serial.println("Something went wrong with the 3D printer initialization");
}
```
#### Exercise 7
We have a function called solveProblem(int numberOfProblem) that tries to solve our physics problems so we don't have to do it. However it doesn't always work as intended and it has implemented a boolean return type that tells if it was actually solved or not.
Create an Arduino sketch that try to solve the problems 3, 4 and 5. If something goes wrong it should print an error message with the problem that generated the error.
The solution with the explanation in the comments is in the spoiler section
:::spoiler
Without loops:
```cpp=
void setup() {
Serial.begin(9600); //since this is a complete skecth we need to remember to initialize the Serial communication
if(!solveProblem(3)) //remember that it's going to return True if everything goes well
{
Serial.println("There was an error in the problem 3");
}
if(!solveProblem(4))
{
Serial.println("There was an error in the problem 4");
}
if(!solveProblem(5))
{
Serial.println("There was an error in the problem 5");
}
}
void loop() {
}
```
Solution with a for loop:
```cpp=
void setup() {
Serial.begin(9600); //since this is a complete skecth we need to remember to initialize the Serial communication
for (int problem = 3; problem <=5; problem ++)
{
if(!solveProblem(problem)) {
Serial.print("There was an error in the problem "); //I added the space after problem and 5
Serial.println(problem);
}
}
}
void loop() {
}
```
:::
#### Exercise 8
We have a function called solveProblem(int numberOfProblem) that tries to solve our physics problems so we don't have to do it. However it doesn't always work as intended and it has implemented a boolean return type that tells if it was actually solved or not.
Create an Arduino sketch that try to solve the problems from 10 to 15. If something goes wrong it should print an error message with the problem that generated the error and continue. If everything goes well, we should print a message saying that that problem was solved.
#### Evaluating funtions
These functions are usually validating information that we have. For example validate an ID card or validate a form. We might also validate a character or a number. We can think of a isPrime(int n) for evaluating if a number is prime or not.
Usually these evaluating functions are going to be set as a condition or part of it (in combination with other conditions connected with operators)
Let's say that we have to validate an Spanish DNI. We may use a function called "validateDNI(string dni)" that will return true if the DNI is valid and false if it's not.
```cpp=
if (validateDNI("77799966X")) {
Serial.println("Identification valid");
}
else {
Serial.println("Identification not valid");
}
```
Some of these evaluating functions have names that start with "is" or "has". IsFormValid(form) or hasAttathment(email)
::: info
In Object Oriented Programming (in C++ and in Java) is very common to have accessors/getters that return booleans. We will cover it when we arrive to OOP
:::
#### Exercise 9
:::warning
Typical exam question. With an introduction of a function that you need to understand and a loop in the solution.
:::
We have an evaluating function called "isPrime(int number)" that returns true if a number is positive and prime.
Create an Arduino sketch that outputs how many prime numbers are in the first 100 numbers. Use isPrime() described before
The solution with the explanation in the comments is in the spoiler section
:::spoiler
```cpp=
void setup() {
Serial.begin(9600);
int counter = 0; //We need a variable to count how many primes we find
for (int x = 1; x < 101; x++) //for loop
{
if (isPrime(x)){
counter ++;
}
}
Serial.println(counter);
}
void loop() {
}
```
:::
#### Exercise 10
We have an evaluating function called "isPrime(int number)" that returns true if a number is positive and prime.
Create an Arduino sketch that outputs the biggest prime in the numbers from 1 to 300.
The solution with the explanation in the comments is in the spoiler section
:::spoiler
Solution 1. We increment in the for loop and we only save the last value that we're going to print. If we use this solution, we need to loop through all the values because we need the last value.
```cpp=
void setup() {
Serial.begin(9600);
int biggest = 0; //We need a variable to store the value
for (int x = 1; x < 300; x++) //for loop
{
if (isPrime(x)){
biggest =x;
}
}
Serial.println(biggest);
}
void loop() {
}
```
Solution 2. We descend from the maximum value to the minimum and we break the loop once we find a prime number.
```cpp=
void setup() {
Serial.begin(9600);
for (int x = 300; x > 1; x--) //for loop that is decreasing. Starts with x = 300 and then 299 and so on
{
if (isPrime(x)){
Serial.println(x);
break; // This instruction exits from the loop, preventing the printing of all the rest of prime numbers.
}
}
}
void loop() {
}
```
:::
### Syntax of an implementation of a function
Now that we have discussed return types and parameters we can arrive to the proper definition of the implementation of a function in C++.
```cpp=
[returnType] nameOfTheFunction([typeParameter1] internalNameOfParameter1, [typeParameter2] internalNameOfParameter2) {
//Code of the Function
}
```
We start with the return type, this means if the function returns an integer, a long, a boolean, a String or other type of variable. If it doesn't return anything we write "void".
:::info
In arduino this is why we have to write void setup() and void loop(). Because these functions don't return any type of values, they just execute instructions
:::
The nameOfTheFunction is written in camelCase, if we're writing code, this name should be meaningful enough. If we're more fluent in other language that it's not English is common to have names of functions in different languages.
The parameters are optional and they are written in the format of type and internal name. For example if we are implenting add(x,y) the definition of the function should be something like this:
```cpp=
double nameOfTheFunction(double x, double y) {
return x + y;
}
```
In this case the implementation is trivial (return x + y) but can be more complicated
:::danger
Remember that return and output are totally different concepts. Return is a value that goes into another part of the code and output will go out of the program (through a console, messaging, screen or somewhere else)
In the exams some questions will be about **outputing values** and others about **returning values**
In Arduino returning values is always done with return and output is done with Serial.println() or Serial.print()
:::
Another example would be a simple implementation of abs(x), a function that returns the absolute value of an input
```cpp=
double abs(double x) {
if (x<0) {
return -x;
}
return x;
}
```
:::info
Remember that the return statement ends the function so any other statement inside the function will be ignored.
:::
In this case if x is negative it will arrive to the line 3 and with that it's going to end the function so the line 5 is not going to be executed.
#### Exercise 11
Implement the function isOddAndMultiplierOf3 that has an input of an int and returns true if the number is Odd and also is a multiplier of 3 and false otherwise.
The solution with the explanation in the comments is in the spoiler section
:::spoiler
We don't need to write setup or loop since we only need to implement the function, not the whole sketch
```cpp=
//remember that in C++ boolean type is written "bool" for short
bool isOddAndMultiplierOf3 (int x) {
if (x%2 == 1 && x%3 == 0) //if the reminder of the number divided by 2 is one and the reminder of the number divided by 3 is 0
{
return true;
}
else
{
return false;
}
}
```
Another correct implementation
```cpp=
bool isOddAndMultiplierOf3 (int x) {
if (x%2 == 1 && x%3 == 0)
{
return true;
}
//Since return will finish the function, if it returns true it's not going to continue anymore.
return false;
}
```
:::
#### Exercise 12
Implement the function outputIfNegative(int x). This function outputs through serial a message only if the input is a negative number.
We can consider that the instruction Serial.begin(9600); has been already called.
The solution with the explanation in the comments is in the spoiler section.
:::spoiler
We don't need to write setup or loop since we only need to implement the function, not the whole sketch
```cpp=
//remember that this function doesn't say "RETURN" but "OUTPUT" this is why this function has a return type of void.
void outputIfNegative (int x) {
if (x<0) {
Serial.println("The input is a negative number");
}
}
```
Another correct implementation
```cpp=
```cpp=
//remember that this function doesn't say "RETURN" but "OUTPUT" this is why this function has a return type of void.
void outputIfNegative (int x) {
if (x<0) {
Serial.println("The input: " + x + " is a negative number");
}
}
```
In this case the statement doesn't specify if we have to output the actual negative number. If we do it's going to be fine.
:::
#### Exercise 13 A
:::success
This is an exam like question. You need to understand a problem that is given to you and give a solution.
:::

[source](https://www.instructables.com/Arduino-Plant-Watering-System/)
We are implementing in an arduino a program as a part of a project to grow plants. We have a connection to a humidifier that tells the percentage of water in the soil. We already have implemented a variable in percentage.
We need to implement a function called decide(int water).
The parameter of this function is the humidity in percentage.
The function decides if we need to call the function "activateWaterPump()" or "stopWaterPump()". If we activate the pump we need to output through serial "Started pumping" and when we stop the pump we need to output "Stopped pumping".
If the humidity is lower than 30 % the water pump should start working and it should stop if the humidity is over 35 %.
We can consider that the instruction Serial.begin(9600); has been already called.
Construct the code of this function.
The solution with the explanation in the comments is in the spoiler section
:::spoiler
We don't need to write setup or loop since we only need to implement the function, not the whole sketch
```cpp=
//remember that this function doesn't say "RETURN" but "OUTPUT" this is why this function has a return type of void.
void decide (int water) {
if (water<30) {
activateWaterPump();
Serial.println("Started pumping");
}
//two different ifs because start and stop are different things.
if (water>35) {
stopWaterPump();
Serial.println("Stopped pumping");
}
}
```
Another correct implementation:
```cpp=
void decide (int water) {
if (water<30) {
activateWaterPump();
Serial.println("Started pumping");
}
else if (water>35) { //we can consider also that we are not going to start and stop the pump in the same call
stopWaterPump();
Serial.println("Stopped pumping");
}
}
```
:::
#### Exercise 13 B (variation of 13)
This is a variation of exercise 13 with a little more complexity.

[source](https://www.instructables.com/Arduino-Plant-Watering-System/)
We are implementing in an arduino a program as a part of a project to grow plants. We have a connection to a humidifier that tells the percentage of water in the soil. We already have implemented a variable in percentage.
We need to implement a function called decide(int water).
The parameter of this function is the humidity in percentage.
The function decides if we need to call the function "activateWaterPump()" or "stopWaterPump()". Nevertheless these functions don't always work as intended. When they don't they return "false".
:::warning
In an exam you can find "false" and false. In almost all cases we are refering to the boolean and not a string that says the word "false".
:::
If the humidity is lower than 30 % the water pump should start working and it should stop if the humidity is over 35 %.
In the case that we find any kind of error we need to output that there was an error with the function that we called and return false to the code that has called "decide". If there were no errors during execution we should return "true".
We can consider that the instruction Serial.begin(9600); has been already called.
Construct the code of this function.
The solution with the explanation in the comments is in the spoiler section
:::spoiler
We don't need to write setup or loop since we only need to implement the function, not the whole sketch
In this case the statement talks about returning so we need to understand that if we are going to return true or false, we are returning a boolean (bool)
```cpp=
bool decide (int water) {
if (water<30) {
//Two different ifs because if we write (water<30 %% !activateWaterPump()) the water pump is going to activate in any case and we don't want that!
if(!activateWaterPump())
//This is calling a error returning function. We use the operator NOT (!) because we are going to care about if we have any errror
{
Serial.println("There was an error activating the pump"); //the message is up to the student but it should indicat that the error is related to activate the pump
return false; //Remember to write return AFTER printing the error
}
}
if (water>35) {
if(!stopWaterPump())
{
Serial.println("There was an error stopping the pump");
return false;
}
}
return true; //in the case that we didn't find an error we return true because there wasn't any kind of error
}
```
Another correct implementation:
```cpp=
bool decide (int water) {
if (water<30) {
//here we don't use the NOT operator so if everything goes well, we just return true as expeted. Else we send the message.
if(activateWaterPump())
{
return true;
}
else{
Serial.println("There was an error activating the pump");
return false;
}
}
if (water>35) {
if(stopWaterPump()){
return true;
}
else {
Serial.println("There was an error stopping the pump");
return false;
}
}
return true; //If we don't activate anything we still need to return true.
}
```
:::
#### Exercise 14 A
These are based in an exercise from IB (nov 2016)
In a school there are 1200 students and each students uses one locker has a unic number from 1 to 2400.
The lockers are to be painted in four colours: red, white, yellow and blue, order of locker numbers, as shown in the following table.
| Locker number | 1 | 2 | 3 | 4 | 5 | 6 | ... | 2400 |
| -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
| Colour | Red | White | Yellow | Blue | Red | White | ... | Blue |
The pattern of colours continues in this manner. For example, locker number 15 will be painted yellow
1) State the colour that the locker number 442 will be painted.
Solution and explanation in the spoiler section:
:::spoiler
It will be white
In this case we're dealing with the remainder (the modulus) of 4. If the locker is multiplier of 4 the locker will be blue. If it's a multiplier of 4 + 1 it will be red and so on like you can see in this table:
| Modulus (reminder) | 0 | 1 | 2 | 3 |
| -------- | -------- | ------- | -------- | -------- |
| Colour | Blue | Red | White | Yellow |
So if we divide 442/4 the reminder will be 2 (the quotient is 110).
:::
2) Construct an algorithm that given a locker number (in the variable locker) outputs the colour that this locker should be painted.
We can consider that the instruction Serial.begin(9600); has been already called.
Solution and explanation in the spoiler section:
:::spoiler
Remember that in this case we are not working with a function, just with a simple part of the algorithm.
Here a solution using a bunch of if/else
```cpp=
if (locker%4 ==0)
{
Serial.println("Blue");
}
else if (locker%4 ==1)
{
Serial.println("Red");
}
else if (locker%4 ==2)
{
Serial.println("White");
}
else //the only other posible result
{
Serial.println("Yellow");
}
```
Using switch case. Here more information about its grammar https://www.w3schools.com/cpp/cpp_switch.asp
```cpp=
switch (locker%4)
{
case 0:
Serial.println("Blue");
break;
case 1:
Serial.println("Red");
break;
case 2:
Serial.println("White");
break;
case 3:
Serial.println("Yellow");
break;
}
```
Another posible solution to not write locker%4 that many times
```cpp=
int x = locker%4
if (x ==0)
{
Serial.println("Blue");
}
else if (x ==1)
{
Serial.println("Red");
}
else if (x ==2)
{
Serial.println("White");
}
else
{
Serial.println("Yellow");
}
```
The advance solution using an array:
```cpp=
int colours[] = {"Blue", "Red", "White", "Yellow"};
Serial.println(colours[locker%4]);
```
This is the more one-liner solution where we access an array using the modulus and directly outputting it. Remember that this solution is not marked as better as the others.
Markers have considered right this other solution populating the complete array. Even this solution is way slower... it works. I post here a couple of versions using while and for loops
```cpp=
String lockers[2400]; //definition of an empty array with all the lockers
int i = 0;
while (i<2400){
lockers[i] = "Red";
i++;
lockers[i] = "White";
i++;
lockers[i] = "Yellow";
i++;
lockers[i] = "Blue";
i++;
}
Serial.println(lockers[locker-1]); //- 1 because the locker 1 has the index 0 in the array and so on. Remember that lockers is the array of strings and locker is the integer
```
```cpp=
String lockers[2400]; //definition of an empty array with all the lockers
for (int i = 0; i < 2400; i++)
lockers[i] = "Red";
i++;
lockers[i] = "White";
i++;
lockers[i] = "Yellow";
i++;
lockers[i] = "Blue";
//missing the last i++ because is included in the for loop
}
Serial.println(lockers[locker-1]); //- 1 because the locker 1 has the index 0 in the array and so on. Remember that lockers is the array of strings and locker is the integer
```
Or even this one is correct:
```cpp=
String lockers[2400]; //definition of an empty array with all the lockers
for (int i = 0; i < 2400; i= i+4)
lockers[i] = "Red";
lockers[i+1] = "White";
lockers[i+2] = "Yellow";
lockers[i+3] = "Blue";
}
Serial.println(lockers[locker-1]); //- 1 because the locker 1 has the index 0 in the array and so on. Remember that lockers is the array of strings and locker is the integer
```
Even that I have seen this kind of solution without any modulus also:
```cpp=
while (locker>=0){
if (x ==0)
{
Serial.println("Blue");
}
else if (x ==1)
{
Serial.println("Red");
}
else if (x ==2)
{
Serial.println("White");
}
else if (x ==3) //in this case we need to check all 4 posibilities
{
Serial.println("Yellow");
}
x = x -4;
}
```
It's very slow specially with big numbers but it works!
:::
## Arrays
:::info
For this section I'm relying heavily in this sources:
https://www.programiz.com/cpp-programming/arrays
https://www.w3schools.com/cpp/cpp_arrays.asp
:::
Arrays are a particular type of collection. The idea is that we are going to store in one variable more than one value. One way to do it is using an array.
This is the declaration of an array of integers (int) with 5 numbers:
```cpp=
int numbers[5] = {1, 10, 20, 30, 50};
```
**The length (or size) of a specific array is how many elements can contain.**
Arrays in most programming languages are very efficient (specially regarding memory usage) but they have some inconvenients. The main one is that once we have declared **the size of an array it cannot be changed** during the execution.
### Array index and values
The first problem that we need to address is that we want to access a particular element (also called member) of the array. To do that we need to use the concept of index. The index is the address inside of the array. To access one of the elements we need to write the name of the array and, in brackets write the number of the index.
Indexes in computer science start with zero, so the first element is the [0] element, the second is the [1] element and the last is [n-1] being n the length of the array.
Let's supose the example of the web in programiz. In C++ we can initialize the array like this:
```cpp=
// declare and initialize and array
int x[6] = {19, 10, 8, 17, 9, 15};
```
Here is the visualization of the elements

[source](https://www.programiz.com/cpp-programming/arrays)
So if we write this code we can use those members to asign other values or we can use it in if statements as we please.
For example
```cpp=
int x[6] = {19, 10, 8, 17, 9, 15};
int y = x[2]; //8
int z = 0;
if (x[4] < x[1]) //this happens because 9 is lesser than 10
{
z = x[3] + x[0]; //17+19 =36
}
else { //this doesn't happen
z = z + x[5];
}
```
#### Exercise 15
Write the output of this code that it's going to happen through serial.
:::info
This and the next is a typical exam exercise to see if you get the concept of index of arrays
:::
```cpp=
Serial.begin(9600);
int x[7] = {19, 10, 8, 17, 9, 15, -10};
int y = x[3];
Serial.println(y);
int z = 0;
if (x[6] < x[1])
{
z = x[4] + x[0];
Serial.println("Dinosaur");
}
else {
z = z + x[2] +10;
Serial.println("Shark");
}
Serial.println(z);
```
The solution with the explanation in the comments is in the spoiler section
:::spoiler
Solution:
```
17
Dinosaur
28
```
The answer in this case are separated through lines since we're using Serial.println but in an exam I will accept them separated in other ways as long as they are in the correct order.
```cpp=
Serial.begin(9600);
int x[7] = {19, 10, 8, 17, 9, 15, -10};
int y = x[3]; //forth element
Serial.println(y);
int z = 0;
if (x[6] < x[1]) //this happens
{
z = x[4] + x[0]; // 9 +19
Serial.println("Dinosaur");
}
else { //this doesn't happen
z = z + x[2] +10;
Serial.println("Shark");
}
Serial.println(z);
```
:::
#### Exercise 16
Write the output of this code that it's going to happen through serial.
::: success
In this case we are going to use also values as indexes. Beware!
:::
```cpp=
Serial.begin(9600);
int numbers[8] = {3, 1, 5, 8, 1, 2, 1, 3};
int x = numbers[1];
int y = numbers[x+1];
int z = numbers[numbers[2]];
Serial.println(x);
Serial.println(y);
Serial.println(z);
```
The solution with the explanation in the comments is in the spoiler section
:::spoiler
Solution:
```
1
5
2
```
The answer in this case are separated through lines since we're using Serial.println but in an exam I will accept them separated in other ways as long as they are in the correct order.
```cpp=
Serial.begin(9600);
int numbers[8] = {3, 1, 5, 8, 1, 2, 1, 3};
int x = numbers[1]; // Second element
int y = numbers[x+1]; // x is 1, so the third element. 5
int z = numbers[numbers[2]]; //the third element is 5, so the sixth element is 2
Serial.println(x);
Serial.println(y);
Serial.println(z);
```
:::
#### The length problem
As a teacher I observed that the concept of length of an array sometimes is not clear and is _key_ for understanding the loops through arrays.
::: warning
The length of the array will be usually given in a variable or as part of the problem "we have a hotel with 100 rooms, and each number of the room is stored in an array" means that we have an array of length 100.
:::
In C++ we cannot use length of an array as propiety so it's common to have something like this
```cpp=
int MyArrayLength = sizeof(MyArray) / sizeof(MyArray[0]);
```
This calculates the size in memory of the whole array and divides it by the size of the first element. This gives the numbers of elements.
Sometimes we have a more complex version of this. In the code that we used in the [melody player](https://github.com/robsoncouto/arduino-songs/blob/master/greenhill/greenhill.ino) we found this code in the line 172
```cpp=
int notes = sizeof(melody) / sizeof(melody[0]) / 2;
```
This was because in this code the melody array has 2 elements for each note (frequency and the divider of the duration).
More info [here](https://www.w3schools.com/cpp/cpp_arrays_size.asp)
In other programming languages (such as java) we usually can access the length of an array using a length propiety.
```java=
//BEWARE JAVA CODE
int[] exampleArray = {1,2,3,4,5};
int exampleArraySize = exampleArray.length;
System.out.print("This Java array size is: " + exampleArraySize );
//The Java array length example prints out the number 5
```
[source](https://www.theserverside.com/blog/Coffee-Talk-Java-News-Stories-and-Opinions/Java-array-size-explained-by-example)
### Loops with arrays
In class we have discussed the implementation of simple algorithms such as min, max and average. For doing that we need to use loops (for loops or while loops).
This types of algorithms are called **iterate through an array**.

[source](https://iterategame.com/)
Usually we can see 2 types of iteration algorithms (but there are more!).
* _Extensive loops._ This kind needs to go through each element to do something with that element (add to a sum when we find the average for example).
* _Selective loops._ that only want to do something to part of the elements or even just one (like when we do the min) but we need to check a condition to do that (With an if clause)
In the for loop usually will be something like this:
```cpp=
for (int i = 0; i < [ARRAY_LENGTH]; i ++) {
//code to execute
}
```
```
//PSEUDOCODE
loop I from 0 to [ARRAY_LENGTH]-1
//things to do
//the element will be accessed with ARRAY[I]
end loop
```
Is common to use i of index, but this is usually up to the programmer and I will consider correct any name for the variable.
The ARRAY_LENGTH is the array length given by the context. Consult [the length problem](#The-length-problem) to revise if you need.
In the code usually we want to do something with the element of the array. If the array is called "myArray" this would be "myArray[i]".
A selective loop would look like this
```cpp=
for (int i = 0; i < [ARRAY_LENGTH]; i ++) {
if (condition)
{
//code to execute
}
}
```
The condition usually will look for a condition of the specific element so we can expect to see in the condition "myArray[i]".
:::info
We can use for loops, while loops and for each loops. I haven't covered for each loops but I will mark it as correct (if they are correctly written). You can find more info about for each loops [in this LINK](https://www.w3schools.com/cpp/cpp_arrays_loop.asp)
:::
Now that we have discussed the abstraction we can see the basic algorithms.
#### Exercise 17
Now we're running a foodtruck about selling corn.

[source](https://www.achoclonados.cl/)
We have an array with all the prices of our products (23 different ways of having a cup of corn with stuff on it) with a range that goes from 2 euros to 10 euros.
The array is called prices and the type is double.
Output the minimum, the maximum and the average of the prices that are available.
We can consider that the instruction Serial.begin(9600); has been already called.
The solutions with the explanation in the comments is in the spoiler section
:::success
This exercise is not an exam like question but the student should know how these works in order to create more complex algorithms
:::
Maximum
:::spoiler
```cpp=
double max = prices[0]; //we initialize the maximum with the first value. It's a double because we're comparing doubles.
for(int i = 0; i < 23; i++) //the number is the name of different products that we can find
{
if (max < prices[i]) { //if the element that we are inspectinc has a bigger value that our max, we update the max
max = prices[i];
}
}
Serial.println(max);
```
:::
Minimum
:::spoiler
```cpp=
double min = prices[0]; //we initialize the maximum with the first value. It's a double because we're comparing doubles.
for(int i = 0; i < 23; i++) //the number is the name of different products that we can find
{
if (min > prices[i]) {//if the element that we are inspectinc has a smaller value that our min, we update the min
min = prices[i];
}
}
Serial.println(min);
```
:::
Average
:::spoiler
```cpp=
double sum = 0; // we're adding all the values on the array so we start with 0
for(int i = 0; i < 23; i++) //the number is the name of different products that we can find
{
sum = sum + prices[i]; //also
}
double average = sum / 23;
Serial.println(min);
```
:::
#### Exercise 18
We have an array of 50 different grades from students that go from 0.0 to 10.
We want to know the index of the highest array and the number of passes (they pass with a 5.0 or higher grade).
Construct a code that outputs this information. The name of the array is grades and is a double type.
We can consider that the instruction Serial.begin(9600); has been already called.
The solutions with the explanation in the comments is in the spoiler section.
:::success
This exercise is an exam like question.
:::
:::spoiler
We can do it in just one loop or two different loops. Both options are fine for this purpose.
```cpp=
int bestGradeIndex = 0; //we can initialize this as 0 or -1. It's an int because the
double bestGrade = grades[0]; //the same idea when we had the max. We need to use it because we still need to know the max.
for(int i = 0; i < 50; i++) //the number is the number of grades
{
if (bestGrade < grades[i]) { //if the element that we are inspectinc has a bigger value that our max, we update the max
bestGrade = grades[i];
bestGradeIndex = i; //We need to update the index that is the one that we're going to output
}
}
Serial.println(bestGradeIndex); //output the first task.
int passed = 0; //initialized counter of people that have passed.
for(int i = 0; i < 50; i++) //the number is the number of grades
{
if (grades[i] >= 5) { //if the element that we are inspectinc has a bigger value that our max, we update the max
passed ++;
}
}
Serial.println(passed);//output the second task.
```
Solution with only one loop (a bit more confusing but legal for the exam)
```cpp=
int bestGradeIndex = 0;
double bestGrade = grades[0];¡
for(int i = 0; i < 50; i++)¡
{
if (bestGrade < grades[i]) { ¡
bestGrade = grades[i];
bestGradeIndex = i; ¡
}
if (grades[i] >= 5) {
passed ++;
}
}
Serial.println(bestGradeIndex); //output the first task.
Serial.println(passed);//output the second task.
```
:::
#### Exercise 19
:::info
This exercise is the same as 18 but is asking about construting functions. Take notice of the differences in the statement
:::
We have an array of 50 different grades from students that go from 0.0 to 10.
We want to know the index of the highest array and the number of passes (they pass with a 5.0 or higher grade).
We're going to implement a couple of functions that return this information. The first one is "highestGradeIndex" and the second is "passes". The name of the array is grades and is a double type and is a global variable.
:::info
Remember that global variables are variables that we can access in any part of the code.
:::
We can consider that the instruction Serial.begin(9600); has been already called.
The solutions with the explanation in the comments is in the spoiler section.
:::spoiler
We need to split this into two different functions, we cannot do them in just one algorithm.
The highestGradeIndex function:
```cpp=
int highestGradeIndex () { //we need to return an integer
//we don't need any parameter but I would accept a version that takes as input the array
int bestGradeIndex = 0;
for(int i = 0; i < 50; i++){
if (bestGrade < grades[i]) {
bestGrade = grades[i];
bestGradeIndex = i;
}
}
return bestGradeIndex; //important that the return happens after the for loop.
}
```
```cpp=
int passes () {
int passed = 0;
for(int i = 0; i < 50; i++) {
if (grades[i] >= 5) {
passed ++;
}
}
return passed;
}
```
:::
### Strings: arrays of characters
::: success
Here you have more activities to do to practice (with pseudocode and C++)
https://hackmd.io/@dprieto/FLA-array
:::

Strings are arrays of characters. We have access to several functions that are going to do something
### Functions with arrays as inputs or outputs
TO-DO