parent
2238a8da3f
commit
c6a0441121
@ -0,0 +1,122 @@
|
||||
# Computer Programming Introduction
|
||||
|
||||
## Academic fraud - system detection
|
||||
#### Don't do:
|
||||
* Plagiarism
|
||||
* Sharing (parts of) your homework
|
||||
* ***Publishing*** (parts of) assignments, exams, answers
|
||||
* Using LLMs to solve assignments
|
||||
|
||||
#### Do:
|
||||
* Cite sources
|
||||
* Always check what is **allowed by the course**
|
||||
* Consult student advisor in case of time pressure
|
||||
|
||||
Plagiarism detection tools can detect **obsfucated** code based off of structure.
|
||||
|
||||
## Course elements
|
||||
|
||||
1. [Canvas](https://canvas.vu.nl/courses/72329)
|
||||
2. Programming labs
|
||||
3. zyBook
|
||||
4. Classroom sessions
|
||||
5. Exam
|
||||
|
||||
## Passing
|
||||
### Programming Lab Grade
|
||||
* Weighted average of 6 homeworg assignments (later weeks count more)
|
||||
* Homework grades go up to **8.5**
|
||||
* For a higher lab grade: **do challange assignments**
|
||||
* Warm-up and code review assignments to be done by deadline
|
||||
|
||||
### Pass the course
|
||||
* **Exam grade** >= 6
|
||||
* Overall grade: weighted average (lab assg. 35%, exam 65%)
|
||||
* Overall grade must be >= **5.5**
|
||||
* Completing zyBook results in overall grade + 1.0 (only if **passsed already**; **deadline**: exam day)
|
||||
|
||||
### More info
|
||||
* Passing the exam is a must
|
||||
* Passing with a lab grade below 5.5 is possible
|
||||
* No deadline extensions for assignments
|
||||
* **Resit**: only for the exam
|
||||
|
||||
## Modules
|
||||
1 module per week
|
||||
<br>
|
||||
Do the **zyBook** before class
|
||||
1. Data Types, Variables, Control Flow (start: *6 sept 2023*)
|
||||
<br> **Weight**: 10
|
||||
2. Vectors, Streams, Functions
|
||||
<br> **Weight**: 10
|
||||
3. Error Handling, Testing
|
||||
<br> **Weight**: 10
|
||||
4. Recursion
|
||||
<br> **Weight**: 20
|
||||
5. Classes and Objects
|
||||
<br> **Weight**: 25
|
||||
6. Pointers and memory management
|
||||
<br> **Weight**: 25
|
||||
|
||||
## Assigments
|
||||
#### Warmup assignments
|
||||
* You are allowed to form a group with another student (same lab group)
|
||||
* Explain solution to TA
|
||||
* Acceptance: *Pass or Fail*
|
||||
* **Fail** = improve + resubmit
|
||||
* Assignment must be accepted by the deadline (*or one week later + penalty*)
|
||||
|
||||
#### Code review
|
||||
* Understand someone else's program + give feedback
|
||||
* TA grades the review
|
||||
* Grading: *Pass or Fail*
|
||||
* Assignment must be accepted by the deadline (*or one week later + penalty*)
|
||||
|
||||
#### Homework
|
||||
Main grading assignment
|
||||
* Exercise the module's topic
|
||||
* Graded by a **randomly** assigned TA
|
||||
* Detailed grading
|
||||
* Feedback by peer review (code review)
|
||||
* Must be submitted by the **deadline** (1 point penalty per day late; 3 days late
|
||||
= fail)
|
||||
<br>
|
||||
|
||||
**!!! No resubmission once graded**
|
||||
|
||||
#### Challange
|
||||
* Only in weeks **2 - 6**
|
||||
* **!!!** Both warm-up and review of the same week have to be accepted
|
||||
* To be solved during a lab session
|
||||
* Inform your TA ahead that you want to do it
|
||||
* Begging of lab session, TA gives you the challenge
|
||||
* 10 = solve in 90 min, 8.5 = solve in 24h
|
||||
|
||||
## Schedule
|
||||
* Classroom sessions
|
||||
<br>
|
||||
3x current week, 2x coming weeks
|
||||
* Programming labs
|
||||
<br>
|
||||
1x current week, 3x coming weeks
|
||||
<br>
|
||||
**important** for questions and assignments acceptance; prepare assignments at home
|
||||
<br>
|
||||
challange assignments
|
||||
<br>
|
||||
**HOWTO:** See canvas
|
||||
* **! Exam**
|
||||
<br>
|
||||
23rd Octobor
|
||||
|
||||
## Good to know:
|
||||
* Contact TAs via [Canvas](https://canvas.vu.nl/courses/72329).
|
||||
* Lectures should not be used for knowledge transfer, instead use zyBook.
|
||||
* You are allowed to **resubmit** code that you already wrote.
|
||||
* Submit assigments through **CodeGrade** (available on Canvas)
|
||||
* You are allowed to resubmit code after the automatic test fails
|
||||
|
||||
## Course content
|
||||
* **Not** a C++ course
|
||||
* Test programs for correct behaviour
|
||||
* Analyse programs and correct programming mistakes
|
@ -0,0 +1,35 @@
|
||||
# Module 1 - Introduction to C++
|
||||
|
||||
## Binary prorgrams
|
||||
**Ways to write**:
|
||||
* Programming bit by bit
|
||||
* Write in human-friendy notation
|
||||
|
||||
## C++ the language
|
||||
* Compiled language
|
||||
* **GOOD TO KNOW:** Using **C++ 14**
|
||||
|
||||
## The computer, simplified model
|
||||
|
||||
`INPUT DEVICE` ->
|
||||
<br>
|
||||
{ <br>
|
||||
* `CENTRAL PROCESSING UNIT`
|
||||
* `CONTROL UNIT`
|
||||
* `ARITHMETIC / LOGIC`
|
||||
* `MEMORY UNIT`
|
||||
<br>
|
||||
|
||||
}
|
||||
<br>-> `OUTPUT DEVICE`
|
||||
|
||||
## Elements of a useful program
|
||||
* Input data, output data
|
||||
<br> If a program does not itneract with its environment it is plain **useless**
|
||||
* Data stored in **memory**
|
||||
* Computation that transforms data into results
|
||||
|
||||
## Types
|
||||
* Types are a **safety** net
|
||||
* Terrible example **JAVASCRIPT**
|
||||
* <span style="color:red">!!! **Do not use** `auto`</span>
|
@ -0,0 +1,59 @@
|
||||
# Module 1 - P2
|
||||
|
||||
# Constant expressions
|
||||
* Do **not** use numerical constants (unless obvious: 0, 1)
|
||||
* Declare values symbolically
|
||||
```cpp
|
||||
const double PI = 3.14159;
|
||||
```
|
||||
```cpp
|
||||
// Examples:
|
||||
PI = 7; // throws an error:
|
||||
// assignment to constant
|
||||
double c = 2 * PI * r; // OK: reading PI
|
||||
```
|
||||
* Using a constant `PI` allows us to change to precision at any point
|
||||
* Names avoid *magic constants*:
|
||||
```cpp
|
||||
const int SPEED_OF_LIGHT = 299792458;
|
||||
```
|
||||
|
||||
### Const variable assignment
|
||||
|
||||
```cpp
|
||||
const int MAX_SIZE = 100;
|
||||
void use(int n)
|
||||
{
|
||||
const int C1 = MAX_SIZE + 7;
|
||||
// OK: C1 is 107
|
||||
const int C2 = n + 7;
|
||||
// OK: and C2 is now *immutable*
|
||||
}
|
||||
```
|
||||
|
||||
* It is good style to declare values as `const`
|
||||
* Constant at runetime
|
||||
|
||||
# Computation and code structure
|
||||
|
||||
* Code organisation and a proper structure help keeping code maintainable
|
||||
when it grows beyond trivial size.
|
||||
* Avoid spaghetti code
|
||||
|
||||
## Structuring code
|
||||
* **Abstraction**: black boxes hide details of their internal workings
|
||||
* Example: using `sqrt()` achieving its job and not caring about how it works
|
||||
* *Stacking levels of abstraction*
|
||||
|
||||
## Indentation
|
||||
* Indentation is important to visualise program structure
|
||||
* Should be used **consistently**
|
||||
|
||||
# Rand
|
||||
* `rand()` internally starts from a seed number and computes from there
|
||||
* Seeding rand()
|
||||
```cpp
|
||||
// Seeding the random generator
|
||||
// Use once in main()
|
||||
void srand(unsigned int seed)
|
||||
```
|
@ -0,0 +1,83 @@
|
||||
# Module 2
|
||||
|
||||
# Functions in math
|
||||
|
||||
In maths, a function is a relation between a set of inputs and a set of permissible outputs with the property that each input is related to exactly one output. An example is the function that relates each real number $x$ to its square $x^2$. The output of a function f corresponding to an input x is denoted by $f(x)$ (read _f of x_)
|
||||
|
||||
# Functions in C++
|
||||
|
||||
A function is defiend by its sets (types) of input parameters, its name, the set of the return value, and the algorithm that computes the return value from the input values.
|
||||
|
||||
```cpp
|
||||
double square(double x)
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
|
||||
// Use call:
|
||||
double sq = square(5.3);
|
||||
```
|
||||
|
||||
# What makes a good function
|
||||
|
||||
- A good function operates in analogy to the notion from mathematics:
|
||||
|
||||
- Only use the input parameters (and nothing else, _no global variables_)
|
||||
- **return** the result
|
||||
|
||||
- Test: the function name should inidcate an activity, like _compute the square of x_
|
||||
|
||||
- A pure function (as in math) is **stateless**
|
||||
|
||||
- it reads only its inputs (and nothing else) and it only writes its return
|
||||
value
|
||||
- a stateless function has no memory (no state) across calls
|
||||
- a stateless function can be called over and over again, the results will be
|
||||
repoducibily the same, no matter if / how it got called before
|
||||
|
||||
- Sometimes, a function is still a good level of abstraction in a program, even
|
||||
if it violates what is said above
|
||||
|
||||
# State
|
||||
|
||||
- Computing is all about state: data stored in variables in memory, and about modifying this state
|
||||
- Problems arise when such state is freely accesible from all parts of a program
|
||||
- This opens the door for lazy, unintended interaction betweem seemingly unrelated pieces of code
|
||||
|
||||
## Function call and return
|
||||
|
||||
- When a function is called, the _thread of execution_ continues with the code of the function
|
||||
- As soon as the function returns, the code that had called the function continues
|
||||
|
||||
```cpp
|
||||
int f(int x)
|
||||
{
|
||||
return 2 * x;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int x = 7;
|
||||
int y = x + 2;
|
||||
x = f(y);
|
||||
|
||||
std::cout << x;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Return from a function
|
||||
|
||||
- A function returns in two cases
|
||||
1. It reaches a `return` statement
|
||||
2. It reaches the end of its code block
|
||||
- A `void` function (not returning a value) is allowed to reaech the end of its code block without returning anything
|
||||
- A function that does not return a value must, in any case, reach a `return` statement (or throw an _exception_)
|
||||
- Compilers cannot always analyse if this is true
|
||||
|
||||
# Vector
|
||||
|
||||
- A vector is a sequence of elements that can be accessed by their index
|
||||
- A vector has a notion of size
|
||||
- Is defined with the data type of its elements and with its size.
|
||||
- `v[2000]` is not checked at runtime **_BUT_** `v.at(2000)` is and throws an error if the index doesn't exist in the given vector. **_CONCLUSION_** Use `at()`
|
@ -0,0 +1,235 @@
|
||||
# Error handling
|
||||
|
||||
- Exceptions
|
||||
- Assertions
|
||||
|
||||
# Run-Time errors
|
||||
|
||||
```cpp
|
||||
/* ... other code ... */
|
||||
int area(int length, int width) {
|
||||
return length * width;
|
||||
}
|
||||
|
||||
int framed_area(int x, int y) {
|
||||
return area(x - 2, y - 2);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int x = -1;
|
||||
int y = 2;
|
||||
int z = 4;
|
||||
int area1 = area(x, y);
|
||||
int area2 = framed_area(1, z);
|
||||
int area3 = framed_area(y, z);
|
||||
|
||||
double ratio = static_cast<double>(area1) / area3;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
area3 = 0 => dividing by 0
|
||||
|
||||
### 1. The caller deals with errors
|
||||
|
||||
This causes lots of error handling code, making the program harder to understand (causing more errors).
|
||||
|
||||
### 2. The function deals with errors
|
||||
|
||||
Sometimes, this is impossible:
|
||||
|
||||
- When we cannot modify the function (e.g. in a library)
|
||||
- The called function does not know what to do in case of an error
|
||||
- The called function does not know where it was called from
|
||||
- Performance (error handling code adds instruction to both code size and execution time)
|
||||
|
||||
### Error reporting
|
||||
|
||||
- We could also make a function return an _error value_
|
||||
<br>Example: `main()` when it returns something **!= 0**
|
||||
|
||||
```cpp
|
||||
int area(int length, int width) {
|
||||
if (length <= 0 || width <= 0) return -1;
|
||||
return length * width;
|
||||
}
|
||||
```
|
||||
|
||||
**Drawbacks**:
|
||||
|
||||
- Not always possible (often, no _error value_ exists)
|
||||
- Now, both caller and function must check for errors
|
||||
|
||||
### So, what can we do?
|
||||
|
||||
- Check your arguments in a function unless you have a good reason not to.
|
||||
- Throw **an exception** in case of bad arguments
|
||||
|
||||
# Exceptions
|
||||
|
||||
- Are supposed to make error handling _easier_ (\*not _easy_)
|
||||
|
||||
<br>**Testing bad arguments**:
|
||||
|
||||
```cpp
|
||||
class BadArea {}; // trivial, user-defined type
|
||||
// just a name
|
||||
|
||||
int area(int length, int width) {
|
||||
if (length <= 0 || width <= 0) throw BadArea();
|
||||
return length * width;
|
||||
}
|
||||
```
|
||||
|
||||
<br>**_Try_ Some code and _Catch_ an exception**:
|
||||
|
||||
```cpp
|
||||
int main() {
|
||||
try {
|
||||
int x = -1, y = 2, z = 4;
|
||||
int area1 = area(x, y), area2 = framed_area(1, z), area3 = framed_area(y, z);
|
||||
|
||||
double ratio = area1 / area3;
|
||||
}
|
||||
catch (BadArea) {
|
||||
cout << "Error occured!\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Exceptions and control flow
|
||||
|
||||
- Throwing an exception disrupts the normal sequential control flow
|
||||
- Code immediately returns after an error occured
|
||||
|
||||
### Range errors (with Vectors)
|
||||
|
||||
The vecotr class throws a special `out_of_range` exception:
|
||||
|
||||
```cpp
|
||||
int main() {
|
||||
try {
|
||||
std::vector<int> v(5);
|
||||
int x = v.at(5);
|
||||
}
|
||||
catch (std::our_of_range) {
|
||||
std::cerr << "Oops! Range error\n";
|
||||
return 1;
|
||||
}
|
||||
catch (/*...*/) {
|
||||
std::cerr << "Unknown exception\n";
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
<br>**! _Useful note_**: use `std::cerr` when handling error messages.
|
||||
|
||||
### Exceptions in the standard library
|
||||
|
||||
- `out_of_range`
|
||||
- `runtime_error`, with a `string` param
|
||||
|
||||
### Catching in `main()`
|
||||
|
||||
```cpp
|
||||
int doSomething() {
|
||||
throw std::runtime_error("shit happens!");
|
||||
return 42;
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
int dummy = doSomething();
|
||||
return 0;
|
||||
}
|
||||
catch (std::runtime_error& e) {
|
||||
std::cerr << "runtime error: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>**! _Useful note_**: Use `std::runtime_error& err` not `std::runtime_error err` in the `catch` block.
|
||||
|
||||
### Exceptions are identified by their class (Type)
|
||||
|
||||
```cpp
|
||||
int main() {
|
||||
try {
|
||||
// our program code
|
||||
return 0;
|
||||
}
|
||||
catch (std::out_of_range& e) {
|
||||
cerr << "Oops1";
|
||||
return 2;
|
||||
}
|
||||
catch (std::out_of_range7 e) {
|
||||
cerr << "Oops2";
|
||||
return 1;
|
||||
}
|
||||
catch (/*...*/) {
|
||||
cerr << "OoopsN";
|
||||
return 42;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
# Assert
|
||||
|
||||
Your program makes certain assumptions under which it is going to work.
|
||||
|
||||
<br>**Examples**:
|
||||
|
||||
- The user does not enter incorrect data
|
||||
- the parameter n for a function `fibonacci(n)` is larger than 0
|
||||
- The vector given to `binarySearch(v)` is sorted
|
||||
|
||||
### Example of `assert()`
|
||||
|
||||
```cpp
|
||||
#include <cassert>
|
||||
|
||||
int factorial(int n) {
|
||||
assert(n >= 0);
|
||||
|
||||
int f = 1;
|
||||
for (int i = 1; i <= n; i++) {
|
||||
f *= i;
|
||||
assert(f>0); // DEBUG: no integer overflow
|
||||
}
|
||||
assert(i == n + 1); // DEBUG: loop cond
|
||||
return f;
|
||||
}
|
||||
```
|
||||
|
||||
### Assert pseudocode
|
||||
|
||||
`assert()` works usually like this:
|
||||
|
||||
```cpp
|
||||
void assert(int expression) {
|
||||
if (expression == 0) {
|
||||
// print error message
|
||||
// abort program
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Removing assert debugging
|
||||
|
||||
- Use cmake's `-DCMAKE_BUILD_TYPE=Release` option instead of _Debug_.
|
||||
<br> By default, cmake turns off debug messages from `assert()` when put into release mode.
|
||||
- Use `#define NDEBUG` at the begining of the code.
|
||||
|
||||
# Assert vs Exceptions vs Error handling
|
||||
|
||||
- **Assertions**: for debugging
|
||||
- **Exceptions**: for exceptional circumstances
|
||||
- **Error handling**: for conditions you must handle
|
||||
<br>You expect a number from `std::cin` but the user types something else
|
@ -0,0 +1,124 @@
|
||||
# Module 3 - Part 2
|
||||
|
||||
- File input and output, command line parameters
|
||||
- Unit testing
|
||||
- Scope
|
||||
|
||||
# Input & Output with files
|
||||
|
||||
- The stream abstraction can easily be extended to files
|
||||
- To do so, open a file and close it (also test if **opening worked**)
|
||||
|
||||
### File input
|
||||
|
||||
```cpp
|
||||
// new stuff
|
||||
std::ifstream inFS;
|
||||
inFS.open("file.txt");
|
||||
bool opened = inFS.is_open();
|
||||
inFS >> value1 >> value2;
|
||||
inFS.close();
|
||||
```
|
||||
|
||||
### File output
|
||||
|
||||
```cpp
|
||||
// new stuff
|
||||
std::ofstream outFS;
|
||||
outFS.open("outputfile.txt");
|
||||
bool opened = outFS.is_open();
|
||||
|
||||
outFS << "Hello, world\n";
|
||||
outFS.close();
|
||||
```
|
||||
|
||||
# Streams: hierarchial abstraction
|
||||
|
||||
- Input streams allow to read `>>` sequences of data (characters) into variables of different types -> `istream`
|
||||
- Output streams do the same with output `<<` -> `ostream`
|
||||
|
||||
**Types**:
|
||||
|
||||
- std::cin | std::cout
|
||||
- std::istringstream | std::ostringstream
|
||||
- std::ifstream | std::ofstream
|
||||
|
||||
# Command line parameters
|
||||
|
||||
```cpp
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
std::vector<std::string> argumentVector(int argc, char** argv) {
|
||||
std::vector<std::string> result(argc);
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
result.at(i) = argv[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::vector<std::string> arguments = arguments(argc, argv);
|
||||
|
||||
for(int i = 0; i < arguments.size(); i++) {
|
||||
std::cout << arguments.at(i) << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
# Unit testing
|
||||
|
||||
- **Good practice**: develop your code in small, independent **units** and test thhem separately before using them together
|
||||
- This is called _unit testing_
|
||||
- **Units**:
|
||||
- functions
|
||||
- classes (mod 5)
|
||||
|
||||
### Test harnesses are separate code
|
||||
|
||||
A test harness is a separate `main()` program, that verifies if our program's results are correct
|
||||
|
||||
# Scopes
|
||||
|
||||
A scope is a region of a program text
|
||||
<br>A name is declared in a scope and is valid (_in scope_) fro the point of its declaration until the end of its scope
|
||||
|
||||
```cpp
|
||||
void f() {
|
||||
g(); // error: g() is not in scope
|
||||
}
|
||||
|
||||
void g() {
|
||||
f(); // OK: f() is in scope
|
||||
}
|
||||
|
||||
void h() {
|
||||
int x = y; // error: y is not yet in scope
|
||||
int y = x; // OK
|
||||
|
||||
{
|
||||
int z; // OK
|
||||
}
|
||||
int whatever = z; // error: z is out of scope
|
||||
g(); // OK
|
||||
}
|
||||
```
|
||||
|
||||
### Scopes keep names local
|
||||
|
||||
```cpp
|
||||
int x = 42;
|
||||
|
||||
void f(int x) {
|
||||
int z = x + 7;
|
||||
}
|
||||
|
||||
void g(int x) {
|
||||
int f = x + 2;
|
||||
return 2 * f;
|
||||
}
|
||||
```
|
@ -0,0 +1,136 @@
|
||||
# Functions & Templates
|
||||
|
||||
# Function templates
|
||||
|
||||
Same functionality does not depend on the type of objects used:
|
||||
|
||||
```cpp
|
||||
void swap(double &d1, double& d2) {
|
||||
double temp = d1;
|
||||
d1 = d2;
|
||||
d2 = temp;
|
||||
}
|
||||
|
||||
void swap(std::string& s1, std::string& s2) {
|
||||
std::string temp = s1;
|
||||
s1 = s2;
|
||||
s2 = temp;
|
||||
}
|
||||
```
|
||||
|
||||
Implementing this functionality with `template`:
|
||||
|
||||
```cpp
|
||||
template <typename T> void swap(T& t1, T& t2) {
|
||||
T temp = t1;
|
||||
t1 = t2;
|
||||
t2 = temp;
|
||||
}
|
||||
|
||||
int main() {
|
||||
double d1 = 42.0, d2 = -7.5;
|
||||
swap(d1, d2);
|
||||
|
||||
std::string s1 = "aaa", s2 = "bbb";
|
||||
swap(s1, s2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
<br>A template can have more than one type parameter: `template <typename T1, typename T2, ...>`
|
||||
<br>**Example**:
|
||||
|
||||
- `std::vector<T>`
|
||||
- `std::map<Key, Value>`
|
||||
|
||||
# Compiling templates
|
||||
|
||||
A template function or class is just a code template (blueprint), not _real_ code
|
||||
<br>Template code will be created only when used
|
||||
|
||||
- Using `swap(double, double)` will cause the compiler to create an actual function: `void swap(double& d1, double& d2)`
|
||||
|
||||
<br>**Conclusion**: It is impossible to compile a template by its own.
|
||||
|
||||
### Solution
|
||||
|
||||
Put templates into a **header file** that will be included by the program.
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include "swap.h"
|
||||
|
||||
int main() {
|
||||
char c1 = 'a', c2 = 'X';
|
||||
swap(c1, c2);
|
||||
|
||||
int i1 = 1, i2 = 2;
|
||||
swap(i1, i2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
# Function activation record
|
||||
|
||||
When `expression()` is called, the C++ implementation sets aside space for:
|
||||
|
||||
- parameters
|
||||
- local variables
|
||||
- _stuff_ for returning the result
|
||||
|
||||
<br>This information is called _implementation record_
|
||||
|
||||
# The stack data structure
|
||||
|
||||
A stack is a container where we can put something on top of it, and can only get the topmost element back
|
||||
|
||||
<br>Each time a function is called, its activation record is pushed onto the execution stack (known as **_the stack_**)
|
||||
|
||||
# Recurssion
|
||||
|
||||
`expression()` indirectly calls itself. We call this indirect call loop: **recursion**
|
||||
|
||||
- A function that calls itself is called _recursive_
|
||||
- Keep the model of the stack activation records in mind
|
||||
- Think of a recursive function as a function that calls another function (that happens to use the very same code)
|
||||
|
||||
## Recursive functions (as in math)
|
||||
|
||||
- Toy example: factorial numbers
|
||||
|
||||
$$5! = 5 \times 4 \times 3 \times 2 \times 1 = 120$$
|
||||
$$n! = n \times (n-1)!$$
|
||||
|
||||
- Code example:
|
||||
|
||||
```cpp
|
||||
long long factorial(long long n)
|
||||
{
|
||||
assert(n > 0);
|
||||
|
||||
if (n == 1) return 1;
|
||||
return n * factorial(n - 1);
|
||||
}
|
||||
```
|
||||
|
||||
Unfortunately, `factorial()` uses tail recursion, which is a bad way of using recursion
|
||||
|
||||
## Fibonacci numbers recurisvely
|
||||
|
||||
```cpp
|
||||
long long fibonacci(long long n)
|
||||
{
|
||||
assert(n >= 0);
|
||||
|
||||
switch (n)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
return 1;
|
||||
default:
|
||||
return fibonacci(n - 1) + fibonacci(n - 2);
|
||||
}
|
||||
}
|
||||
```
|
Loading…
Reference in new issue