David Prieto
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # 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 ![old-doorbell-1493998372dHV](https://hackmd.io/_uploads/Hkn_RgJup.jpg) ([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" ![Pierre_de_Fermat](https://hackmd.io/_uploads/ByGIa_x_a.jpg) [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. ::: ![imagen](https://hackmd.io/_uploads/SkB0TWz_p.png) [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. ![imagen](https://hackmd.io/_uploads/SkB0TWz_p.png) [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 ![imagen](https://hackmd.io/_uploads/HktB_0GOT.png) [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**. ![Sin título](https://hackmd.io/_uploads/ryvGWFmd6.png) [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. ![imagen](https://hackmd.io/_uploads/Hkts2FmdT.png) [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 ::: ![imagen](https://hackmd.io/_uploads/SkGotDrda.png) 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

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully