diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..1f65da6 --- /dev/null +++ b/.clang-format @@ -0,0 +1,4 @@ +BasedOnStyle: Google +IndentWidth: 4 +BreakBeforeBraces: Attach +CommentStyle: Aligned \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8e8fdc7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,65 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Linters / Formatters +.ruff_cache/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0d12f80 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,51 @@ +{ + "files.associations": { + "iostream": "cpp", + "*.tcc": "cpp", + "limits": "cpp", + "ostream": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "new": "cpp", + "numbers": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "typeinfo": "cpp", + "fstream": "cpp", + "map": "cpp" + } +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..7b0448d --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: g++.exe build active file", + "command": "C:\\msys64\\ucrt64\\bin\\g++.exe", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}\\${fileBasenameNoExtension}.exe" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/CPP/Beginner/00. Getting started/README.md b/CPP/Beginner/00. Getting started/README.md new file mode 100644 index 0000000..63b9389 --- /dev/null +++ b/CPP/Beginner/00. Getting started/README.md @@ -0,0 +1,68 @@ +# Exercise 0: Hello World + +## Objective + +Getting familiarized with C++ files, their coding style and building the executable. + +## Task + +Create a file named 'hello_world.cpp'. The file must: + +- Have a single function `int main() { }` which returns 0 at the end. +- Print through the terminal 'Hello world!'. + +Once created, build the program and execute it. + +## Hints + +- Include the standard library ``. +- Use `sdt::cout << "My message"` to print a message through the terminal. +- End the terminal use with `std::endl`. +- You can use `using namespace std` to use `cout` instead of `std::cout`. + +# C++ theory +## Coding in C++ + +C++ files have an extension `.cpp` or `.cc`. +Inside, the code is defined by the following (basic) rules: + +- The executable file usually has a `main()` function, which returns `0` when has run without problems. +- The body of any block is defined by the keys `{ }`. +- Every line command ends with `;`. +- Libraries are included/imported into the code as `#include ` (for standard libraries) or as `#include "lib_name.h"` for header files. +- Standard calls are defined as `std::CALL`, for example `std::string` or `std::cout`. + +## Compiling & building + +Assuming a file `main.cpp`, the code is compiled as the following: + +``` +g++ main.cpp +``` + +This creates a file `a.exe`, which can be called through the command line to execute it. +It is also possible to create an executable with a custom name: + +``` +g++ -o my_program main.cpp +``` + +With the `-o` parameter, the output `my_program.exe` is created. + +# Environment setup + +This is a guide to setup your end to be able to code in C++. +For it, you will need: + +- **Code editor**: We will use Visual Studio Code. +- **Make**: If you are using Linux, you already have it. This has to be installed for Windows. + +## Code editor (VS Code) + +The first step is to have a code editor. +At this repo, I will continue with the VisualStudio code. +You can download it from the [official website](https://code.visualstudio.com/download). +Once downloaded, install is but don't open it yet. + +## Make for Windows + diff --git a/CPP/Beginner/00. Getting started/hello_world.cpp b/CPP/Beginner/00. Getting started/hello_world.cpp new file mode 100644 index 0000000..7e0d554 --- /dev/null +++ b/CPP/Beginner/00. Getting started/hello_world.cpp @@ -0,0 +1,9 @@ +#include + +// using namespace std; +using std::cout, std::endl; + +int main() { + cout << "Hello World!" << endl; + return 0; +} diff --git a/CPP/Beginner/01. Basic IO/README.md b/CPP/Beginner/01. Basic IO/README.md new file mode 100644 index 0000000..bcc680c --- /dev/null +++ b/CPP/Beginner/01. Basic IO/README.md @@ -0,0 +1,42 @@ +# Exercise 1: Basic Input and Output + +## Objective +Learn how to take user input and display it using `std::cin` and `std::cout`. + +## Task +Write a program that: +- Asks the user to input their name. +- Asks the user to input their age. +- Outputs a message saying: "Hello, [Name]! You are [Age] years old." + +## Expected Result +If the user inputs "Alice" as their name and "30" as their age, the program should output: +```commandline +Hello, Alice! You are 30 years old. +``` + +# C++ theory +## Using the console + +To use the terminal in C++ it is necessary to include the `iostream` library. + +```cpp +#include +``` + +This library allows to use `std::cin` (console input) and `std::cout` (console output). +The symbols `<<` are used for printing through the console output, and `>>` to obtain data through the console input. + +```cpp +int number; + +std::cout << "Write a number: "; +std::cin >> number; +std::cout << "You wrote the number " << number << std::endl; +``` + +The manipulator `std::endl` writes the special character `\n` (new line) and flushes the buffer. +In other words, the output is inmediately shown on the terminal. + +Writing `std::endl` and `\n` are different, as `\n` does not flush the buffer and it is faster. +Try to use `std::endl` only when the output is to be shown immediately or the code is done using the console. diff --git a/CPP/Beginner/01. Basic IO/greetings.cpp b/CPP/Beginner/01. Basic IO/greetings.cpp new file mode 100644 index 0000000..57f4932 --- /dev/null +++ b/CPP/Beginner/01. Basic IO/greetings.cpp @@ -0,0 +1,16 @@ +#include +#include + +int main() { + int age; + std::string name; + + std::cout << "What is your name?" << std::endl; + std::cin >> name; + std::cout << "How old are you?" << std::endl; + std::cin >> age; + + std::cout << "Hello, " << name << "! You are " << age << " years old." + << std::endl; + return 0; +} diff --git a/CPP/Beginner/02. Basic operations/README.md b/CPP/Beginner/02. Basic operations/README.md new file mode 100644 index 0000000..d95e699 --- /dev/null +++ b/CPP/Beginner/02. Basic operations/README.md @@ -0,0 +1,85 @@ +# Exercise 2: Basic Arithmetic Operations +## Objective +Learn how to perform basic arithmetic operations and work with different data types. + +## Task +Write a program that: + +- Asks the user to input two integers. +- Performs the following operations on those integers: + - Addition + - Subtraction + - Multiplication + - Division +- Outputs the result of each operation in a readable format. + +## Expected Result +If the user inputs 10 and 5 as the two integers, the program should output: + +```commandline +Addition: 10 + 5 = 15 +Subtraction: 10 - 5 = 5 +Multiplication: 10 * 5 = 50 +Division: 10 / 5 = 2 +``` + +# C++ Theory + +## Types of variables + +When defining a variable, the type of this one must be specified before its name. +Then, the variable must be initialized (its value must be set to a known value) before it is used. + +```cpp +#include + +int number; // integer variable, not initialized. +std::string dayOfTheWeek = "Monday"; // string variable, initialized +``` + +Some of the **basic types** for variables are: + +- `int`: Defines signed integers. +- `unsigned int`: Defines unsigned integers. +- `float`: A single-precision floating-point number (usually 32 bits). +- `double`: A double-precision floating-point number (usually 64 bits). +- `char`: A character type, usually 8 bits, which can represent ASCII values. +- `bool`: Represents a boolean, either 'true' or 'false'. +- `void`: Represents the absence of type. + +From C++11 and onwards, there are **fixed-width integer types** using the library ``: + +- `int8_t, int16_t, int32_t, int64_t`: Signed integers of fixed width (8, 16, 32, and 64 bits). +- `uint8_t, uint16_t, uint32_t, uint64_t`: Unsigned integers of fixed width. + +There exist also **standard types**, importing the correct library. +For example `std::string` can be defined when including ``. + +## Operations with variables + +The **basic operations** that can be perfomed in C++ are: + +- Sum (`+`): `int a = 1 + 2;`. As a result, `a = 3`. +- Substraction (`-`): `int a = 1 - 2;`. As a result, `a = -1`. +- Multiplication (`*`): `int a = 1 * 2;`. As a result, `a = 2`. +- Division (`/`): `float a = 1 / 2;`. As a result, `a = 0.5`. +- Modulus/Reminder (`%`): `int a = 1 % 2`. As a result, `a = 1` (reminder of the division 1 / 2). + +These operation can be directly assigned over variables. + +- `int a += 2;` is equivalent to `int a = a + 2;` +- `int a -= 2;` is equivalent to `int a = a - 2;` +- `int a *= 2;` is equivalent to `int a = a * 2;` +- `float a /= 2;` is equivalent to `int a = a / 2;` +- `int a %= 2;` is equivalent to `int a = a % 2;` + +When defining these operations with numbers, each number also has a type. +If a type is not define, these are the **literal types**: + +- In `a + 2`, the number '2' is a literal integer (type `int`). +- In `a / 2.0`, the number '2.0' is a literal decimal point (type `double`). + +It is of good practise to always define the type of the values you work with: + +- `2u` defines that '2' is type `unsigned`. +- `2.0f` defines that '2' is type `float`. diff --git a/CPP/Beginner/02. Basic operations/farenh2celsius.cpp b/CPP/Beginner/02. Basic operations/farenh2celsius.cpp new file mode 100644 index 0000000..2c694ca --- /dev/null +++ b/CPP/Beginner/02. Basic operations/farenh2celsius.cpp @@ -0,0 +1,17 @@ +/* Here mathematic operations are performed over a value given by the user. */ + +#include + +int main() { + float temp_f; + float temp_c; + + // Without 'std::endl' the user writes right next to the sentence: + std::cout << "Enter a temperature in fahrenheit: "; + std::cin >> temp_f; + + temp_c = (temp_f - 32u) * 5.0f / 9.0f; + std::cout << "Your temperature in celsius is " << temp_c << std::endl; + + return 0; +} diff --git a/CPP/Beginner/03. Conditional statements/README.md b/CPP/Beginner/03. Conditional statements/README.md new file mode 100644 index 0000000..f24b356 --- /dev/null +++ b/CPP/Beginner/03. Conditional statements/README.md @@ -0,0 +1,68 @@ +# Exercise 3: Grading System +## Objective + +Understanding of if-else statements by creating a program that uses multiple conditions. + +## Task + +Write a program that: + +- Asks the user to input a percentage grade (0-100). +- Determines the corresponding letter grade based on the following criteria: + - A: 90 - 100 + - B: 80 - 89 + - C: 70 - 79 + - D: 60 - 69 + - F: 0 - 59 +- Outputs the corresponding letter grade. + +## Expected Result +If the user inputs 85, the program should output: +```commandline +Your grade is B +``` + +If the user inputs 72, the program should output: +```commandline +Your grade is C +``` + +# C++ theory + +## If-else conditions + +An if-block defines a set of code which gets executed only a certain condition is met: + +```cpp +if (condition) { + // Code to be executed when 'condition' is true. +} +``` + +Additionaly, an else-block can be added after the if-block. +This contains code to execute when the previous condition was not met: + +```cpp +if (condition) { + // Code to be executed when 'condition' is true. +} else { + // Code to be executed when 'condition' is false. +} +``` + +These blocks can be placed sequentially, definining different blocks of code for different conditions: + +```cpp +if (condition_a) { + // Code to be executed when 'condition_a' is true. +} else if (!condition_b) { + // Code to be executed when 'condition_b' is false. +} else { + // Code to be executed when 'condition_a' is false and 'condition_b' is true. +} +``` + +The operand `!` negates the result: + +- `!true` is equivalent to `false`. +- `!false` is equivalent to `true`. \ No newline at end of file diff --git a/CPP/Beginner/03. Conditional statements/grade_scale.cpp b/CPP/Beginner/03. Conditional statements/grade_scale.cpp new file mode 100644 index 0000000..2b17932 --- /dev/null +++ b/CPP/Beginner/03. Conditional statements/grade_scale.cpp @@ -0,0 +1,26 @@ +/* This program looks onto the if-else block logic. */ + +#include + +int main() { + int grade; + + // It is assumed the given number is always valid: + std::cout << "Enter your grade mark (number among 0 and 100): "; + std::cin >> grade; + + if (grade >= 90) { + std::cout << "Your grade is A" << std::endl; + } else if (grade >= 80) { + std::cout << "Your grade is B" << std::endl; + } else if (grade >= 70) { + std::cout << "Your grade is C" << std::endl; + } else if (grade >= 60) { + std::cout << "Your grade is D" << std::endl; + } else if (grade >= 50) { + std::cout << "Your grade is E" << std::endl; + } else { + std::cout << "Your grade is F" << std::endl; + } + return 0; +} diff --git a/CPP/Beginner/04. While loops/README.md b/CPP/Beginner/04. While loops/README.md new file mode 100644 index 0000000..90ebf88 --- /dev/null +++ b/CPP/Beginner/04. While loops/README.md @@ -0,0 +1,111 @@ +# Exercise 4: Number Guessing Game + +## Objective +Learn how to use loops (while or do-while) and conditional statements together to create a simple game. + +## Task +Write a program that: +- Randomly generates a number between 1 and 100 (you can use rand() function). +- Asks the user to guess the number. +- Keeps asking the user for a guess until they guess the correct number. +- Provides feedback after each guess: + - If the guess is too high, print "Too high!" + - If the guess is too low, print "Too low!" + - When the user guesses the correct number, print "Congratulations! You've guessed the number!" + + +## Expected Result: +The program will continue asking for guesses until the correct number is guessed. + +```commandline +Guess the number (1-100): 50 +Too high! +Guess the number (1-100): 25 +Too low! +Guess the number (1-100): 37 +Congratulations! You've guessed the number! +``` + +# C++ theory + +## While loop + +The while-loop is defined to execute a code while a condition is true: + +```cpp +int index = 0; + +std::cout << "Initial index: " << index << '\n'; + +while (index < 5) { + index++; + std::cout << "Index value: " << index << '\n'; +} + +std::cout << "End of program" << std::endl; +``` + +We can expect the following output from this code: +```commandline +Initial index: 0 +Index value: 1 +Index value: 2 +Index value: 3 +Index value: 4 +Index value: 5 +End of program +``` + +However, the code within the block will not be executed if the condition is not met: + +```cpp +int index = 20; + +std::cout << "Initial index: " << index << '\n'; + +while (index < 5) { + index++; + std::cout << "Index value: " << index << '\n'; +} + +std::cout << "End of program" << std::endl; +``` + +With this code, we can expect the following output: + +``` +Initial index: 20 +End of program +``` + +## do-while loop + +The do-while loop is similar to the while loop, with two major differences: + +- The code is structured as `do { ... } while (condition)` +- The block will run at least once. + +Considering the following code as an example: + +```cpp +int index = 20; + +std::cout << "Initial index: " << index << '\n'; + +do { + index++; + std::cout << "Index value: " << index << '\n'; +} while (index < 5); + +std::cout << "End of program" << std::endl; +``` + +We can expect the following output: + +```cpp +Initial index: 20 +Index value: 21 +End of program +``` + +Thus, the 'do-while' is to be used whenever we want to execute its code at least once. \ No newline at end of file diff --git a/CPP/Beginner/04. While loops/guessing_game.cpp b/CPP/Beginner/04. While loops/guessing_game.cpp new file mode 100644 index 0000000..d52f058 --- /dev/null +++ b/CPP/Beginner/04. While loops/guessing_game.cpp @@ -0,0 +1,45 @@ +/* Game where a random number among 1 and 100 is chosen. + * The user has to guess the number. For every guess, the + * program will anounce if the number is too high, too low + * or it is the correct guess. + * + * This exercise practises the 'while' and 'do-while' operations. + */ + +#include // For 'rand()' and 'srand()' +#include // For 'time()' +#include + +int main() { + /* Seed random number generator. + * Without the seed, the random number will always be the + * same every time the program is execured. + */ + srand(time(0)); + + // Generate random number: + int random_number = rand() % 100 + 1; + int user_guess; + bool correct_guess = false; + + std::cout << "I have selected a number among 1 and 100 " + "and you have to guess it." + << std::endl; + + do { + std::cout << "Enter your guess: "; + std::cin >> user_guess; + + if (user_guess == random_number) { + std::cout << "Congratulations! You've guessed the number!" + << std::endl; + correct_guess = true; + } else if (user_guess < random_number) { + std::cout << "Too low!" << std::endl; + } else { + std::cout << "Too high!" << std::endl; + } + } while (!correct_guess); + + return 0; +} diff --git a/CPP/Beginner/05. For loops/README.md b/CPP/Beginner/05. For loops/README.md new file mode 100644 index 0000000..fdd6684 --- /dev/null +++ b/CPP/Beginner/05. For loops/README.md @@ -0,0 +1,81 @@ +# Exercise 5: Sum of an Array +## Objective +Learn how to work with arrays and loops in C++. + +## Task + - Create an array that holds 10 integers. + - Populate the array with values entered by the user. + - Write a loop that sums all the elements in the array. + - Display the sum to the user. + +## Expected Result: +The program should prompt the user to enter 10 integers. +After entering all the numbers, the program should output the sum of those integers. + +# C++ theory + +## For-loop + +A for-loop is analogous to a while-loop where the condition to finalize and the task to perform at the end of each loop is defined together. + +```cpp +for (int index = 0; index < 5; index++) { + std::cout << "Current index: " << index << '\n'; +} +std::cout << "End of program" << std::endl; +``` + +The following output is the result from this code: + +``` +Current index: 0 +Current index: 1 +Current index: 2 +Current index: 3 +Current index: 4 +End of program +``` + +## Arrays + +An array is a sequence of values, where every value is of the same type. +Arrays are defined with a fix size: + +```cpp +// Array which can contain 5 integer numbers +int array[5]; +``` + +An array can be initialized by using the keys `{}` or by populating it number by number: + +```cpp +// Defining and initializing an array: +int array[5] = {0, 1, 2, 3, 4} + +// Populating an array with the values {5, 6, 7, 8, 9} +for (int index = 0, num = 5; index < 5; index++, num++) { + array[index] = num; +} +``` + +Sequences in C++ are indexed at 0. +That means the first index is 0 and not 1. +Thus, the code `array[2]` access the third element of the array. + +For that reason, for loops are very useful to access all elements of an array. +From C++11, the following code also allows to iterate over all elements: + +```cpp +int array[3] = {0, 1, 2} + +for (int number : array) { + std::cout << number << " "; +} +std::cout << std::endl; +``` + +This code prints by the terminal: + +``` +0 1 2 +``` diff --git a/CPP/Beginner/05. For loops/sum_of_array.cpp b/CPP/Beginner/05. For loops/sum_of_array.cpp new file mode 100644 index 0000000..c338738 --- /dev/null +++ b/CPP/Beginner/05. For loops/sum_of_array.cpp @@ -0,0 +1,37 @@ +/* Program to sum the numbers in an array. + * + * This exercise practises: + * - Definition & initialization of an array. + * - for-loops + * - Understanding of 'sizeof()' + */ +#include + +int main() { + int result = 0; + // Definition of an array with 10 ints + int numbers[10]; + + /* Dynamic find of how long the array is: + * 'sizeof()' returns the number of bytes of an element. + * Because the array has all elements of the same type, each + * element has the same size. + * Thus, the total number of elements is defined by the + * total size in bytes of the array over the size of one element. + */ + int arr_size = sizeof(numbers) / sizeof(numbers[0]); + + // Populate the array with the user input: + std::cout << "Provide 10 numbers to be added:" << std::endl; + for (int i = 0; i < arr_size; i++) { + std::cin >> numbers[i]; + } + + // Next syntaxis is valid only from C++11 + for (int number : numbers) { + // Sum all numbers + result += number; + } + + std::cout << "The sum of the numbers is " << result << std::endl; +} diff --git a/CPP/Beginner/06. Input handling/README.md b/CPP/Beginner/06. Input handling/README.md new file mode 100644 index 0000000..0e82027 --- /dev/null +++ b/CPP/Beginner/06. Input handling/README.md @@ -0,0 +1,69 @@ +# Exercise 6: Robust User Input with Error Handling +## Objective +Learn how to handle errors gracefully, particularly when dealing with user input. + +## Task + +- Prompt the user to enter an integer between 1 and 100. +- Validate the input: + - If the user enters something that isn’t an integer, display an error message and prompt them to try again. + - If the user enters an integer outside the valid range (1-100), display an error message and prompt them to try again. +- Once a valid input is received, display a confirmation message. + +## Expected Result +The program should continue to prompt the user until they provide a valid integer within the specified range. +Display a confirmation message once the correct input is provided. + +Example interaction: +```commandline +Enter an integer between 1 and 100: +abc +Invalid input. Please enter an integer between 1 and 100: +150 +Input out of range. Please enter an integer between 1 and 100: +50 +Thank you! You entered 50. +``` + +# C++ theory + +## Stream Flags + +You might have realised that, even though a variable can be defined as an integer, nothing stops the user to give an invalid type as an input. +For example, the following promt might be correct from the perspective of a user: + +```commandlinme +Enter an integer between 1 and 100: +fifty two +``` + +To prevent these cases, the console input provides some tools: + +### std::cin.good() + +The function `std::cin.good()` is part of the stream state-checking functions. +It returns `true` when no errors have occurred at the stream (for example, the validity of the input type). + +Let's consider the user input "fifty two" from before for the example. +The following code will then print the correct message based on the input type: + +```cpp +int number; + +std::cout << "Please, write a number:" <> number; + +if std::cin.good() { + std::cout << "Your number is " << number << std::endl; +} else { + std::cout << "You have provided an invalid entry" << std::endl; + std::cin.clear(); +} +``` + +### Handling invalid inputs + +If the user provides an invalid input, there is two actions to consider: + +1. Clear the error flag with `std::cin.clear()`. Otherwise, if the second input of a user is correct, the function `std::cin.good()` would still consider there was an error within the stream. +2. Ignore the rest of the stream to avoid unexpected behavior. Use `std::cin.ignore(std::numeric_limits::max(), '\n')` to do so. diff --git a/CPP/Beginner/06. Input handling/wrong_number.cpp b/CPP/Beginner/06. Input handling/wrong_number.cpp new file mode 100644 index 0000000..5c6ff6d --- /dev/null +++ b/CPP/Beginner/06. Input handling/wrong_number.cpp @@ -0,0 +1,42 @@ +/* This program asks for a number from the user. + * The program will complain if an invalid input is given. + * + * This exercise practises: + * - Handling invalid input types. + * - Loop breaking and infinite loops. + */ + +#include +#include // For numeric limits + +int main() { + unsigned int user_input; + + while (true) { + // Get the user input: + std::cout << "Enter an integer among 1 and 100: "; + std::cin >> user_input; + + // Condition to break the loop. + // std::cin.good() checks if the input is valid. + if (std::cin.good() && user_input >= 1 && user_input <= 100) { + break; + } + + // Clear the error flag if the input is invalid: + std::cin.clear(); + /* Discard the invalid input: + * - std::ingore() ignores or discards a value + * - std::numeric_limits::max() defines a numeric + * limit of the maximum stream size. + * - All characteres are ignored until the special character '\n' + * is found. + */ + std::cin.ignore(std::numeric_limits::max(), '\n'); + + std::cout << "You provided an invalid input" << std::endl; + } + + std::cout << "You provided the valid input: " << user_input << std::endl; + return 0; +} diff --git a/CPP/Beginner/07. Functions/README.md b/CPP/Beginner/07. Functions/README.md new file mode 100644 index 0000000..e90aa6a --- /dev/null +++ b/CPP/Beginner/07. Functions/README.md @@ -0,0 +1,127 @@ +# Exercise 7: Functions +## Objective +Learn how to define, declare, and use functions in C++. + +## Task + +- Create a documented header (`.h`) file containing all the functions. +- Define a function named `square()` that takes an integer parameter and returns its square. +- Define a function named `greet()` that prints a simple greeting message to the console. +- Use both functions in the `main()` function to demonstrate how they work. + +## Expected Result + +- The `square()` function should calculate and return the square of a number. +- The `greet()` function should print a greeting message. +- The `main()` function should use these functions and display results to the console + +# C++ theory + +## Functions + +Functions are a self-contained block of code that performs a specific task. +They allow coders to break down complex problems into smaller manageable task, improving also its readability and reuse. + +Each function is composed by: + +- The **return type**, which is `void` when it does not return anything. +- The **parameters**, each one with its specified type. + +```cpp +int add(int a, int b) { + return a + b; +} +``` + +## Header files + +Header files contain code declarations, in other words, they don't contain actual code implementations. +A header file is defined in C++ with the `.h` or `.hpp` extension. + +Each header file should be linked to its `.cpp` file, which contains the code: + +```cpp +// math_operations.h +int add(int a, int b); +int subtract(int a, int b); +``` + +```cpp +// math_operations.cpp +#include "math_operations.h" + +int add(int a, int b) { return a + b; } +int subtract(int a, int b) { return a - b; } +``` + +### Safe include +C++ is also sensitive to multi-importing the same file. +For that, it is crucial to define an import flag within the header file: + +```cpp +// math_operations.h + +#ifndef MATH_OP_H + #define MATH_OP_H + + int add(int a, int b); + int subtract(int a, int b); +#endif +``` + +With this routine, `math_operations.h` can be included in multiple `.cpp` files safely. + +### Code documentation + +Another benefit of spliting the code in header files is documenting the code only at the implementation. +Like so, the declarations and documentation of the functions are separated from their code, leading to easier to understand code in projects with large code. + + +```cpp +// math_operations.h + +#ifndef MATH_OP_H + #define MATH_OP_H + + /* + * @brief Addition of two integers. + * + * @param a - The first integer to add. + * @param b - The second integer to add. + * @return int - The result of the addition. + */ + int add(int a, int b); +#endif +``` + +```cpp +// math_operations.cpp +#include "math_operations.h" + +int add(int a, int b) { return a + b; } +``` + +The block comments to document each function follow a set of rules: + +- They are defined with the keys `/* */`. +- Use of `@brief` to define a brief description of the function (no longer than one line). If a longer description/explanation is required, this can be written in the following lane, before the parameters. +- Use of `@param p_name` to define an input parameter. This can be omitted if the function takes no parameters. +- Use of `@return type` to define the returned value. This can be omitter if the function is `void` (does not return any value). + +## Code compilation + +Previously, when at C++ we worked with a single `main.cpp` file, the compilation was quite direct: + +```commandline +g++ main.cpp +``` + +This command would generate an `a.exe` file. +However, when we define new header files, this also needs to be parsed so the main program can compile correctly: + +```commandline +g++ main.cpp math_operations.cpp +``` + +As you can see, the difference is not very big. +The number of files to parse will grow the more header files we create, but worry not as there is also a solution (explained at the exercise #14) to keep this simple. diff --git a/CPP/Beginner/07. Functions/functions.cpp b/CPP/Beginner/07. Functions/functions.cpp new file mode 100644 index 0000000..6a72dc1 --- /dev/null +++ b/CPP/Beginner/07. Functions/functions.cpp @@ -0,0 +1,20 @@ +#include +#include "7-functions.h" + +int square(int num) { + return num * num; +} + +void greet() { + std::cout << "Hello, welcome to the program!" << std::endl; +} + +int main() { + greet(); + + int value = 5; + int result = square(value); + + std::cout << "The square of " << value << " is " << result << std::endl; + return 0; +} diff --git a/CPP/Beginner/07. Functions/functions.h b/CPP/Beginner/07. Functions/functions.h new file mode 100644 index 0000000..e276021 --- /dev/null +++ b/CPP/Beginner/07. Functions/functions.h @@ -0,0 +1,21 @@ +// Next block runs if 'FUNCTIONS_H' is not defined. +#ifndef FUNCTIONS_H + #define FUNCTIONS_H + + // Functions declarations + + /** + * @brief Calculates the square value. + * + * Given a number, calculates and returns the square value of itself. + * + * @param num - Value for which the square has to be calculated. + * @return int - Square value of the given integer. + */ + int square(int num); + + /** + * @brief Greets the user. + */ + void greet(); +#endif diff --git a/CPP/Beginner/08. File IO process/README.md b/CPP/Beginner/08. File IO process/README.md new file mode 100644 index 0000000..871d2dd --- /dev/null +++ b/CPP/Beginner/08. File IO process/README.md @@ -0,0 +1,118 @@ +# Exercise 8: File I/O Operations +## Objective +Practice reading from and writing to files in C++. This exercise will help you understand how to handle file streams, manage file input/output, and incorporate error handling. + +## Tasks + +- Create a Text File: Manually create a text file named "data.txt" in the same directory as your C++ program. Add the follwing numbers in the file: + +```commandline +42 +67 +89 +23 +``` + +- Read from the File: Write a C++ program that reads the integers from data.txt, one by one. +- Calculate the Sum: As you read each integer from the file, calculate their sum and display the result after all numbers have been read. +- Write the Result to Another File: Write the sum of the integers into a new file named "result.txt". +- Error Handling: Implement error handling to check if the files can be opened successfully. If a file can't be opened, display an appropriate error message. + +## Hints + +- File Reading: Use `std::ifstream` for reading from a file. +- File Writing: Use `std::ofstream` for writing to a file. +- Loops: You'll likely use a loop to read the numbers from the file. +- Error Handling: Check if the file stream is in a good state before proceeding with reading or writing operations. + + +## Expected Result +The program should print each number from data.txt to the console, display the sum, and write the sum to result.txt. + +# C++ theory + +## I/O stream classes for files + +To perform Input/Ouput operations with files, C++ requires the library `fstream` to be included. +Within this library, there can be found three classes: + +1. `std::ifstream` (Input File Stream) used to read data. + +```cpp +#include +std::ifstream inputFile("example.txt"); +``` + +2. `std::ofstream` (Output File Stream) used to write data. + +```cpp +#include +std::ofstream outputFile("example.txt"); +``` + +3. `std::ftream` (File Stream) to handle both I/O data. + +```cpp +#include +std::fstream file("example.txt", std::ios::in | std::ios::out); +``` + +Remember always to **close the file** to release system resources: + +```cpp +#include +inputFile.close(); +outputFile.close(); +``` + +### Reading from files + +Considering **text files**, the data can be read by: + +- Using the operator `>>`, where each data (words or numbers) is separated by whitespaces. + +```cpp +std::ifstream inputFile("data.txt"); +std::string word; +while (inputFile >> word) { + // Process word +} +``` + +- Using `std::getline` to read the entire line, until a newline character ('\n'). + +```cpp +std::ifstream inputFile("data.txt"); +std::string line; +while (std::getline(inputFile, line)) { + // Process line +} +``` + +Considering **binary files**, the method `read()` has to be used. +This requires to specify the buffer where the data is initialized and the size of the buffer to read. + +```cpp +std::ifstream inputFile("data.bin", std::ios::binary); +char buffer[100]; +inputFile.read(buffer, sizeof(buffer)); +``` + +### Writing to files + +Considering **text files**, the data can be written by using the operator `<<`. + +```cpp +std::ofstream outputFile("output.txt"); +outputFile << "Hello, World!" << std::endl; +``` + +> Note: Consider using `std::endl` only when flushing is required. Otherwise use `'\n'`. + +Considering **binary files**, the method `write()` has to be used. + +```cpp +std::ofstream outputFile("data.bin", std::ios::binary); +char buffer[100] = { /* ... data ... */ }; +outputFile.write(buffer, sizeof(buffer)); +``` \ No newline at end of file diff --git a/CPP/Beginner/08. File IO process/data.txt b/CPP/Beginner/08. File IO process/data.txt new file mode 100644 index 0000000..3612d4b --- /dev/null +++ b/CPP/Beginner/08. File IO process/data.txt @@ -0,0 +1,4 @@ +42 +67 +89 +23 \ No newline at end of file diff --git a/CPP/Beginner/08. File IO process/file_process.cpp b/CPP/Beginner/08. File IO process/file_process.cpp new file mode 100644 index 0000000..3385d78 --- /dev/null +++ b/CPP/Beginner/08. File IO process/file_process.cpp @@ -0,0 +1,60 @@ +#include +#include + +int read_file(std::string file_name) { + std::cout << "Reading a file to sum all the numbers within it..." + << std::endl; + + // Opening file (for reading only): + std::ifstream inFile(file_name); + + if (!inFile) { + throw std::runtime_error("Could not open the specified file."); + } + if (inFile.peek() == std::ifstream::traits_type::eof()) { + throw std::runtime_error("The given file is empty."); + } + + // Code here: + int result = 0; + int f_number; + + while (inFile >> f_number) { + result += f_number; + } + + // Closing file: + inFile.close(); + + return result; +} + +void write_file(int value) { + std::cout << "Writing the result into a new file..." << std::endl; + + // Opening file (for writing only): + std::ofstream outFile("result.txt"); + + if (!outFile) { + throw std::runtime_error("Could not open the specified file."); + } + + // Writing the data into the file: + outFile << value << std::endl; + + // Closing the file: + outFile.close(); +} + +int main() { + try { + int result = read_file("numbers.txt"); + write_file(result); + } catch (const std::exception& e) { + std::cerr << e.what() << '\n'; + } + + std::cout << "File 'result.txt' was created with the total sum " + << "of the numbers within 'numbers.txt'." << std::endl; + return 0; +} diff --git a/CPP/Beginner/08. File IO process/result.txt b/CPP/Beginner/08. File IO process/result.txt new file mode 100644 index 0000000..7b47338 --- /dev/null +++ b/CPP/Beginner/08. File IO process/result.txt @@ -0,0 +1 @@ +221 diff --git a/CPP/Beginner/09. Pointers/README.md b/CPP/Beginner/09. Pointers/README.md new file mode 100644 index 0000000..e0d9891 --- /dev/null +++ b/CPP/Beginner/09. Pointers/README.md @@ -0,0 +1,19 @@ +# Exercise 9: Understanding Pointers +## Objective +This exercise will help you get familiar with pointers by manipulating them in different ways. + +## Tasks + +- Pointer Basics: Declare an integer variable and a pointer that points to it. Output the value of the integer, the pointer, and the value at the pointer (dereferencing). +- Pointer Arithmetic:Use pointer arithmetic to manipulate the pointer and observe how it changes the value it points to. +- Using Pointers with Arrays: Create an array and use a pointer to iterate over the array elements. +- Swapping Values: Write a function that swaps the values of two integers using pointers. + + +## Expected result +The program will: + - Show the basics of pointer usage. + - Demonstrate pointer arithmetic. + - Swap two values using a pointer-based function. + + # C++ theory \ No newline at end of file diff --git a/CPP/Beginner/09. Pointers/pointers.cpp b/CPP/Beginner/09. Pointers/pointers.cpp new file mode 100644 index 0000000..91807ab --- /dev/null +++ b/CPP/Beginner/09. Pointers/pointers.cpp @@ -0,0 +1,63 @@ +/* Exercise to get familiar with pointers. + * + * BASICS + * - Declaration: Understand how to declare and reference pointers. + * - Dereferencing: Access the value a pointer references to. + * - Arithmetics: Incrementing pointers and how it affects the memory. + * - Functions: Parsing pointers to functions and manipulating them. + * + * REQUIREMENTS + * - Referencing pointers to variables. Reading their value and the variables' + * values. + * - Using pointer arithmetic to manipualte values. + * - Work with arrays and pointers. + * - Use pointers to swap values. + */ + +#include + +// Function to swap values. +void swap(int* a, int& b) { + int temp = *a; + *a = b; + b = temp; +} + +int main() { + // Basics of pointers + int x = 10; + int* p = &x; + + std::cout << "\n1. Basics\n ********** \n" + << "Value of 'x': " << x << '\n' + << "Pointer 'p' pointing to 'x': " << p << '\n' + << "Value at pointer 'p' (dereferencing): " << *p << std::endl; + + // Arithmetics + (*p)++; + std::cout << "\n2. Arithmetics\n ********** \n" + << "Value at 'x' after incrementing the value via pointer 'p': " + << x << std::endl; + + // Arrays + int arr[5] = {1, 2, 3, 4, 5}; + int* arrPtr = arr; + + std::cout << "\n3. Arrays operations\n ********** \n" + << "Array elements accessed via pointer arithmetics:" << '\n'; + for (int i = 0; i < 5; i++) { + // Accessing arr[i] via pointer: + std::cout << *(arrPtr + i) << " "; + } + std::cout << std::endl; + + // Swapping values + int a = 5, b = 10; + std::cout << "\n4. Pointers with functions\n ********** \n" + << "Before swap: a=" << a << ", b=" << b << std::endl; + + swap(&a, b); // Passing the memory addresses of 'a' and 'b'. + std::cout << "After swap: a=" << a << ", b=" << b << std::endl; + + return 0; +} diff --git a/CPP/Beginner/10. Vectors/README.md b/CPP/Beginner/10. Vectors/README.md new file mode 100644 index 0000000..bb8a2dd --- /dev/null +++ b/CPP/Beginner/10. Vectors/README.md @@ -0,0 +1,27 @@ +# Exercise 10: Statistical Analysis of Numbers + +## Objective +Understanding vectors and getting used to .h files. + +## Task +In this exercise, you'll write a program that reads a list of numbers from a file, stores them in a vector, and then calculates and outputs the following statistics: + +- Mean (Average) +- Median +- Mode + +## Steps + +- Reading the Numbers: +Read all the numbers from a file into a std::vector. +Ensure the file exists and is not empty. +Handle any potential errors (e.g., non-numeric data). + +- Calculating the Statistics: + - Mean: Calculate the average of the numbers. + - Median: Find the middle value when the numbers are sorted. If there’s an even number of values, the median is the average of the two middle numbers. + - Mode: Identify the number that appears most frequently. If there is a tie for the most frequent number, return all of them. +- Output the Results: +Display the mean, median, and mode(s) to the user. + +# C++ theory \ No newline at end of file diff --git a/CPP/Beginner/10. Vectors/main.cpp b/CPP/Beginner/10. Vectors/main.cpp new file mode 100644 index 0000000..7709582 --- /dev/null +++ b/CPP/Beginner/10. Vectors/main.cpp @@ -0,0 +1,60 @@ + +#include +#include +#include + +#include "statistics.h" + +// Function declaration +std::vector read_numbers(const std::string& filename); + +// Main function +int main() { + std::string f_name; + std::cout << "Specify the name of the file containing the numbers: "; + std::cin >> f_name; + + try { + std::vector numbers = read_numbers(f_name); + + double mean = calculate_mean(numbers); + double median = calculate_median(numbers); + std::vector modes = calculate_mode(numbers); + + std::cout << "Mean: " << mean << '\n' + << "Median: " << median << '\n' + << "Mode: "; + for (int mode : modes) { + std::cout << mode << " "; + } + std::cout << std::endl; + + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + } + + return 0; +} + +// Function: Open file and populate a vector. +std::vector read_numbers(const std::string& filename) { + std::ifstream inFile(filename); + if (!inFile) { + throw std::runtime_error("Could not open the given file."); + } + + std::vector numbers; + int number; + while (inFile >> number) { + numbers.push_back(number); + } + + if (numbers.empty()) { + // No integers into 'numbers', ergo the file data was not correct. + throw std::runtime_error( + "The file is empty or contains non-numeric data."); + } + + inFile.close(); + return numbers; +} diff --git a/CPP/Beginner/10. Vectors/numbers.txt b/CPP/Beginner/10. Vectors/numbers.txt new file mode 100644 index 0000000..5837adc --- /dev/null +++ b/CPP/Beginner/10. Vectors/numbers.txt @@ -0,0 +1 @@ +4 1 2 2 3 5 5 5 6 7 7 7 8 \ No newline at end of file diff --git a/CPP/Beginner/10. Vectors/statistics.cpp b/CPP/Beginner/10. Vectors/statistics.cpp new file mode 100644 index 0000000..0f017f2 --- /dev/null +++ b/CPP/Beginner/10. Vectors/statistics.cpp @@ -0,0 +1,53 @@ +/** + * Here is contained the code of the functions to use. + * When compiling, the file that imports this module must be compiled and linked with it: + * + * g++ main.cpp statistics.cpp -o my_program + */ + +#include +#include +#include + +double calculate_mean(const std::vector& numbers) { + double sum = 0; + for (int num : numbers) { + sum += num; + } + return sum / numbers.size(); +} + +double calculate_median(std::vector& numbers) { + std::sort(numbers.begin(), numbers.end()); + int nof_digits = numbers.size(); + + if (nof_digits % 2 == 0) { + return (numbers[nof_digits / 2 - 1] + numbers[nof_digits / 2]) / 2.0; + } else { + return numbers[nof_digits / 2]; + } +} + +std::vector calculate_mode(const std::vector& numbers) { + // Mappint which defines the count of each number. + std::map frequency; + for (int num : numbers) { + frequency[num]++; + } + + int max_count = 0; + for (const auto& [num, count] : frequency) { + if (count > max_count) { + max_count = count; + } + } + + std::vector modes; + for (const auto& [num, count] : frequency) { + if (count == max_count) { + modes.push_back(num); + } + } + + return modes; +} diff --git a/CPP/Beginner/10. Vectors/statistics.h b/CPP/Beginner/10. Vectors/statistics.h new file mode 100644 index 0000000..d44eabc --- /dev/null +++ b/CPP/Beginner/10. Vectors/statistics.h @@ -0,0 +1,45 @@ +/** + * Here are contained the declaration and docstrings of the functions to use. + */ + +#ifndef STATISTICS_H +#define STATISTICS_H + +#include + +/** + * @brief Calculates the mean (average) of a sequence of numbers. + * + * This function takes a vector of integers and calculates the mean of it. + * + * @param numbers The vector of integers for which to calculate the mean. + * @return double The mean of the numbers. + */ +double calculate_mean(const std::vector& numbers); + +/** + * @brief Calculates the median of a sequence of numbers. + * + * This function takes a vector of integers and calculates the median value. If + * the vector has an even number of elements, the median is the average of the + * two middle numbers. Note that the input vector may be modified as this + * function sorts the vector to determine the median. + * + * @param numbers The vector of integers for which to calculate the median. + * @return double The median of the numbers. + */ +double calculate_median(std::vector& numbers); + +/** + * @brief Calculates the mode(s) of a list of numbers. + * + * This function takes a vector of integers and finds the mode(s), which is the + * most frequently occurring number(s) in the list. It returns a vector + * containing all modes (in case of a tie). + * + * @param numbers The vector of integers for which to calculate the mode(s). + * @return std::vector A vector containing the mode(s) of the numbers. + */ +std::vector calculate_mode(const std::vector& numbers); + +#endif diff --git a/CPP/Beginner/11. OOP and Classes/BankAccount.cpp b/CPP/Beginner/11. OOP and Classes/BankAccount.cpp new file mode 100644 index 0000000..af2d486 --- /dev/null +++ b/CPP/Beginner/11. OOP and Classes/BankAccount.cpp @@ -0,0 +1,49 @@ +/** + * Classes and Object-Oriented Programming (OOP) + * Create a BankAccount class that represents a simple bank account with basic + * operations like depositing money, withdrawing money, and checking the + * balance. + * + * REQUIREMENTS + * - The class 'BankAccount' must have the following private members: + * * std::string account_holder (the name of the account holder) + * * int account_number (the account number) + * * double balance (the current balance) + */ + +#include "BankAccount.h" + +#include +#include + +BankAccount::BankAccount(const std::string& holder, int number, + double initial_balance) + : account_holder(holder), + account_number(number), + balance(initial_balance) {} + +void BankAccount::deposit(double amount) { + if (amount > 0) { + balance += amount; + } else { + std::cerr << "Deposit amount must be positive." << std::endl; + } +} + +void BankAccount::withdraw(double amount) { + if (amount > 0) { + if ((balance > 0) && (amount <= balance)) { + balance -= amount; + } else { + std::cerr << "Insuficient funds." << std::endl; + } + } else { + std::cerr << "Withdrawl amount must be positive." << std::endl; + } +} + +double BankAccount::get_balance() const { return balance; } + +std::string BankAccount::get_account_holder() const { return account_holder; } + +int BankAccount::get_account_number() const { return account_number; } diff --git a/CPP/Beginner/11. OOP and Classes/BankAccount.h b/CPP/Beginner/11. OOP and Classes/BankAccount.h new file mode 100644 index 0000000..b00ce65 --- /dev/null +++ b/CPP/Beginner/11. OOP and Classes/BankAccount.h @@ -0,0 +1,24 @@ +#ifndef BANKACCOUNT_H +#define BANKACCOUNT_H + +#include + +class BankAccount { + private: + std::string account_holder; + int account_number; + double balance; + + public: + // Constructor + BankAccount(const std::string& holder, int number, double initial_balance); + + // Public methods + void deposit(double amount); + void withdraw(double amount); + double get_balance() const; + std::string get_account_holder() const; + int get_account_number() const; +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/11. OOP and Classes/README.md b/CPP/Beginner/11. OOP and Classes/README.md new file mode 100644 index 0000000..e958758 --- /dev/null +++ b/CPP/Beginner/11. OOP and Classes/README.md @@ -0,0 +1,43 @@ +# Exercise 11: Implement a Simple BankAccount Class +## Objective +Create a BankAccount class that represents a simple bank account with basic operations like depositing money, withdrawing money, and checking the balance. + +## Task + +- Class Definition: Create a class named BankAccount with the following private members: + - std::string account_holder (the name of the account holder) + - int account_number (the account number) + - double balance (the current balance) +- Constructor: Define a constructor that initializes the account holder’s name, account number, and starting balance. +- Public Methods: + - void deposit(double amount): Adds money to the account. + - void withdraw(double amount): Subtracts money from the account if there are sufficient funds. + - double get_balance() const: Returns the current balance. + - std::string get_account_holder() const: Returns the name of the account holder. + - int get_account_number() const: Returns the account number. +- Error Handling: Ensure that the withdraw method does not allow the balance to go negative. If the withdrawal amount exceeds the current balance, print an error message. + +In the main function, create an instance of the BankAccount class. +Simulate some transactions like depositing money, withdrawing money, and printing the account balance after each transaction. + +## Expected result +``` +Account Holder: John Doe +Account Number: 123456 +Initial Balance: $500.00 + +Depositing $150.00... +Current Balance: $650.00 + +Withdrawing $100.00... +Current Balance: $550.00 + +Attempting to withdraw $600.00... +Insufficient funds! Current Balance: $550.00 +``` + +## Hints +- Use const for methods that do not modify the state of the object. +- Consider how to encapsulate the account data properly, exposing only the necessary methods to interact with the class. + +# C++ theory diff --git a/CPP/Beginner/11. OOP and Classes/main.cpp b/CPP/Beginner/11. OOP and Classes/main.cpp new file mode 100644 index 0000000..920b2ce --- /dev/null +++ b/CPP/Beginner/11. OOP and Classes/main.cpp @@ -0,0 +1,27 @@ +#include + +#include "BankAccount.h" + +int main() { + // Create a BankAccount object: + BankAccount myAccount("John Doe", 123456, 500.00); + + // Display initial status: + std::cout << "Account holder: " << myAccount.get_account_holder() << '\n' + << "Account number: " << myAccount.get_account_number() << '\n' + << "Initial Balance: $" << myAccount.get_balance() << std::endl; + + // Perform transactions: + std::cout << "Deposit $150.25..." << std::endl; + myAccount.deposit(150.25); + std::cout << "Current balance: $" << myAccount.get_balance() << std::endl; + + std::cout << "Withdrawing $100.00..." << std::endl; + myAccount.withdraw(100.0); + std::cout << "Current balance: $" << myAccount.get_balance() << std::endl; + + std::cout << "Attempting to withdraw E800.00" << std::endl; + myAccount.withdraw(800.0); + + return 0; +} diff --git a/CPP/Beginner/12. Class inheritance/Circle.h b/CPP/Beginner/12. Class inheritance/Circle.h new file mode 100644 index 0000000..89ff3eb --- /dev/null +++ b/CPP/Beginner/12. Class inheritance/Circle.h @@ -0,0 +1,41 @@ +#ifndef CIRCLE_H +#define CIRCLE_H + +#include "Shape.h" +#include // For M_PI + +/** + * @brief Derived class representing a circle. + * + * This class inherits from Shape and implements specific functionalities + * to calculate the area and the permieter (circunference) of a circle. + */ +class Circle : public Shape { + private: + double radius; + + public: + /** + * @brief Constructor for the Circle class. + * @param r Radius of the circle. + */ + Circle(double r) : Shape("Circle"), radius(r) {} + + /** + * @brief Calculates the area of the circle. + * @return The area as a double. + */ + double area() const override { + return M_PI * pow(radius, 2); + } + + /** + * @brief Calculates the perimeter of the circle. + * @return The perimeter as a double. + */ + double perimeter() const override { + return 2 * M_PI * radius; + } +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/12. Class inheritance/README.md b/CPP/Beginner/12. Class inheritance/README.md new file mode 100644 index 0000000..47f5e98 --- /dev/null +++ b/CPP/Beginner/12. Class inheritance/README.md @@ -0,0 +1,51 @@ +# Exercise 12: Inheritance in C++ + +## Objective +Create a program that models a simple hierarchy of classes using inheritance. You will create a base class Shape and derive two classes Rectangle and Circle from it. Each derived class will implement functions to calculate the area and perimeter of the shapes. + +## Task + +- Base Class Shape: Define a base class named Shape containing + - A protected attribute name to hold the name of the shape. + - A public method printName() that prints the shape's name. + - Two pure virtual functions: + - double area() to calculate the area of the shape. + - double perimeter() to calculate the perimeter of the shape. + +- Derived Class Rectangle: + - Inherit from Shape and represent a rectangle. + - Add private attributes width and height. + - Implement the area() and perimeter() functions. + +- Derived Class Circle: + - Inherit from Shape and represent a circle. + - Add a private attribute radius. + - Implement the area() and perimeter() functions. + +- Main Function: + - Create instances of Rectangle and Circle. + - Set their dimensions. + - Print their names, areas, and perimeters. + +## Hints + +- Use the keyword virtual in the base class to define pure virtual functions, making Shape an abstract class. +- Use the override keyword in the derived classes when implementing the inherited virtual functions. +- For the Rectangle, the area is calculated as width * height, and the perimeter is 2 * (width + height). +- For the Circle, the area is π * radius * radius, and the perimeter (circumference) is 2 * π * radius. +- Use the constant M_PI from for π. + +## Expected Result +When you run your program, it should print something like: + +```commandline +Shape: Rectangle +Area: 20 +Perimeter: 18 + +Shape: Circle +Area: 28.2743 +Perimeter: 18.8496 +``` + +# C++ theory diff --git a/CPP/Beginner/12. Class inheritance/Rectangle.h b/CPP/Beginner/12. Class inheritance/Rectangle.h new file mode 100644 index 0000000..f9e1d9a --- /dev/null +++ b/CPP/Beginner/12. Class inheritance/Rectangle.h @@ -0,0 +1,38 @@ +#ifndef RECTANGLE_H +#define RECTANGLE_H + +#include "Shape.h" + +/** + * @brief Derived class representing a rectangle. + * + * This class inherits from Shape and implements specific functionality + * to calculate the area and perimeter of a rectangle. + */ +class Rectangle : public Shape { + private: + double width; + double height; + + public: + /** + * @brief constructor for a Rectangle object + * @param w The width of the rectangle. + * @param h The height of the rectangle. + */ + Rectangle(double w, double h) : Shape("Rectangle"), width(w), height(h) {} + + /** + * @brief Calculates the area of the rectangle. + * @return The area as a double. + */ + double area() const override { return width * height; } + + /** + * @brief Calculates the perimeter of the rectangle. + * @return The perimeter as a double. + */ + double perimeter() const override { return 2 * (width + height); } +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/12. Class inheritance/Shape.h b/CPP/Beginner/12. Class inheritance/Shape.h new file mode 100644 index 0000000..a9cb05b --- /dev/null +++ b/CPP/Beginner/12. Class inheritance/Shape.h @@ -0,0 +1,45 @@ +#ifndef SHAPE_H +#define SHAPE_H + +#include +#include + +/** + * @brief Class representing a generic shape. + * + * This class serves as a base class for other shapes. + * It contains the protected name attribute and pure virtual functions + * for calculating the area and perimeter, making this class abstract. + */ +class Shape { + protected: + std::string name; + + public: + /** + * @brief Construct a shape with a given name. + * @param shapeName The name of the shape. + */ + Shape(const std::string& shapeName) : name(shapeName) {} + + /** + * @brief Prints the main name. + */ + void printName() const { std::cout << "Shape: " << name << std::endl; } + + /** + * @brief Calculates the area of the shape. + * Pure virtual fucntion to be implemented by derived classes. + * @return double The area of the shape. + */ + virtual double area() const = 0; + + /** + * @brief Perimeter of the shape. + * Pure virtual function to be implemented by derived classes. + * @return double The perimeter of the shape. + */ + virtual double perimeter() const = 0; +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/12. Class inheritance/main.cpp b/CPP/Beginner/12. Class inheritance/main.cpp new file mode 100644 index 0000000..404648a --- /dev/null +++ b/CPP/Beginner/12. Class inheritance/main.cpp @@ -0,0 +1,22 @@ +#include + +#include "Circle.h" +#include "Rectangle.h" + +int main() { + // Creating a rectangle of width 4 and height 5 + Rectangle rect(4, 5); + rect.printName(); + std::cout << "Area: " << rect.area() << '\n' + << "Perimeter: " << rect.perimeter() << '\n' + << std::endl; + + // Create a circle of radius 3 + Circle circ(3); + circ.printName(); + std::cout << "Area: " << circ.area() << '\n' + << "Perimeter: " << circ.perimeter() << '\n' + << std::endl; + + return 0; +} diff --git a/CPP/Beginner/13. Polymorphism/Circle.h b/CPP/Beginner/13. Polymorphism/Circle.h new file mode 100644 index 0000000..3ce497a --- /dev/null +++ b/CPP/Beginner/13. Polymorphism/Circle.h @@ -0,0 +1,34 @@ +#ifndef CIRCLE_H +#define CIRCLE_H + +#include "Shape.h" +#include // For M_PI and 'pow()' + +/** + * @brief Derived class representing a circle. + * + * This class inherits from Shape and implements specific functionalities + * to calculate the area and the permieter (circunference) of a circle. + */ +class Circle : public Shape { + private: + double radius; + + public: + /** + * @brief Constructor for the Circle class. + * @param r Radius of the circle. + */ + Circle(double r) : Shape("Circle"), radius(r) {} + + /** + * @brief Calculates the area of the circle. + * @return The area as a double. + */ + double area() const override { + return M_PI * pow(radius, 2); + } + +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/13. Polymorphism/README.md b/CPP/Beginner/13. Polymorphism/README.md new file mode 100644 index 0000000..909e18a --- /dev/null +++ b/CPP/Beginner/13. Polymorphism/README.md @@ -0,0 +1,29 @@ +# Exercise 13: Implementing Polymorphism with Shapes + +## Objective +Create a base class called Shape and derive two classes from it: Circle and Rectangle. Implement a virtual function area() in the base class and override it in the derived classes to calculate the area of each shape. +You can reuse the classes from the last exercise. + +## Task +- Base Class (Shape): + - Should have a pure virtual function double area() const. + - Include a virtual destructor which defined from which shape it was called. +- Derived Class (Circle): + - Constructor should take the radius as a parameter. + - Implement the area() function to calculate the area of a circle. + - Include a destructor. +- Derived Class (Rectangle): + - Constructor should take the width and height as parameters. + - Implement the area() function to calculate the area of a rectangle. + - Do not include a destructor. +- Main Function: + - Create a list of pointers to Shape objects. + - Add different shapes (Circle, Rectangle) to the list. + - Iterate through the list and display the area of each shape using polymorphism. + +## Expected result +The program should display the calculated areas for each shape in the list. + +This exercise will help you understand how to use polymorphism to handle objects of different derived types through a common base class interface. Let me know if you need guidance at any point! + +# C++ theory \ No newline at end of file diff --git a/CPP/Beginner/13. Polymorphism/Rectangle.h b/CPP/Beginner/13. Polymorphism/Rectangle.h new file mode 100644 index 0000000..f73f122 --- /dev/null +++ b/CPP/Beginner/13. Polymorphism/Rectangle.h @@ -0,0 +1,35 @@ +#ifndef RECTANGLE_H +#define RECTANGLE_H + +#include "Shape.h" + +/** + * @brief Derived class representing a rectangle. + * + * This class inherits from Shape and implements specific functionality + * to calculate the area and perimeter of a rectangle. + */ +class Rectangle : public Shape { + private: + double width; + double height; + + public: + /** + * @brief constructor for a Rectangle object + * @param w The width of the rectangle. + * @param h The height of the rectangle. + */ + Rectangle(double w, double h) : Shape("Rectangle"), width(w), height(h) {} + ~Rectangle() { + std::cout << "Derived class 'Rectangle' destructor called." << std::endl; + } + + /** + * @brief Calculates the area of the rectangle. + * @return The area as a double. + */ + double area() const override { return width * height; } +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/13. Polymorphism/Shape.h b/CPP/Beginner/13. Polymorphism/Shape.h new file mode 100644 index 0000000..76d0bc0 --- /dev/null +++ b/CPP/Beginner/13. Polymorphism/Shape.h @@ -0,0 +1,44 @@ +#ifndef SHAPE_H +#define SHAPE_H + +#include +#include + +/** + * @brief Class representing a generic shape. + * + * This class serves as a base class for other shapes. + * It contains the protected name attribute and pure virtual functions + * for calculating the area and perimeter, making this class abstract. + */ +class Shape { + protected: + std::string name; + + public: + /** + * @brief Construct a shape with a given name. + * @param shapeName The name of the shape. + */ + Shape(const std::string& shapeName) : name(shapeName) {} + + /** + * @brief Prints the main name. + */ + void printName() const { std::cout << "Shape: " << name << std::endl; } + + /** + * @brief Calculates the area of the shape. + * Pure virtual fucntion to be implemented by derived classes. + * @return double The area of the shape. + */ + virtual double area() const = 0; + + // Virtual destructor. + virtual ~Shape() { + std::cout << "Base class destructor called from Shape: " << name + << std::endl; + } +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/13. Polymorphism/main.cpp b/CPP/Beginner/13. Polymorphism/main.cpp new file mode 100644 index 0000000..ac18339 --- /dev/null +++ b/CPP/Beginner/13. Polymorphism/main.cpp @@ -0,0 +1,27 @@ +#include + +#include "Circle.h" +#include "Rectangle.h" +#include "Shape.h" + +int main() { + // Create a vector of shapes: + std::vector shapes; + + // Add different shapes: + shapes.push_back(new Circle(5)); + shapes.push_back(new Rectangle(2, 4)); + shapes.push_back(new Circle(2.5)); + + // Iterate over the shapes, print the area and clean up + // the allocated memory: + for (const Shape* shape : shapes) { + std::cout << "*******\n"; + shape->printName(); + std::cout << shape->area() << "\n"; + delete shape; // Calls the destructor + } + std::cout << std::endl; + + return 0; +} \ No newline at end of file diff --git a/CPP/Beginner/14. Makefiles/Makefile b/CPP/Beginner/14. Makefiles/Makefile new file mode 100644 index 0000000..d23f7c0 --- /dev/null +++ b/CPP/Beginner/14. Makefiles/Makefile @@ -0,0 +1,26 @@ +# The following makefile is defined only for Windows + +# Folders +SRC_FOLDER := src +HEAD_FOLDER := include + +# The name of the executable. +PROG_NAME = myprog + +# Program files +SRC_NAMES := Circle.cpp Rectangle.cpp Triangle.cpp +SRC_FILES := $(addprefix $(SRC_FOLDER)/, $(SRC_NAMES)) +HEAD_FILES := $(addprefix $(HEAD_FOLDER)/, $(SRC_NAMES:.cpp=.h)) +OBJS_FILES := $(SRC_NAMES:.cpp=.o) + +output: main.o my_lib.o + g++ main.o $(OBJS_FILES) -o $(PROG_NAME) + +my_lib.o: $(SRC_FILES) + $(CXX) -c $(SRC_FOLDER)/*.cpp -I $(HEAD_FOLDER) + +main.o: main.cpp + $(CXX) -c main.cpp -I $(HEAD_FOLDER) + +clean: + del myprog.exe $(OBJS_FILES) main.o diff --git a/CPP/Beginner/14. Makefiles/README.md b/CPP/Beginner/14. Makefiles/README.md new file mode 100644 index 0000000..69cb486 --- /dev/null +++ b/CPP/Beginner/14. Makefiles/README.md @@ -0,0 +1,24 @@ +# Exercise 14: Makefiles + +## Objective + +Understanding the importance of multiple .cpp with .h files and how Makefiles help. + +## Task + +- Create a Makefile for the project. +- Define a base class `Shape` (only header file). +- Define the following derived classes from `Shape`: + - `Circle` + - `Rectangle` + - `Triangle` +- Each class must have a header file (with only declarations) and a .cpp file (with all the code). +- Each derived class must be able to calculate the area and perimeter. + +Create a file `main.cpp` which performs the following operations: +- Create one instance of each derived class. +- Create a vector of pointers to store each created instance. +- Iterate over all shapes printing the area. +- Clear the vector once finished with it. + +# C++ theory \ No newline at end of file diff --git a/CPP/Beginner/14. Makefiles/include/Circle.h b/CPP/Beginner/14. Makefiles/include/Circle.h new file mode 100644 index 0000000..7406b55 --- /dev/null +++ b/CPP/Beginner/14. Makefiles/include/Circle.h @@ -0,0 +1,17 @@ + +#ifndef CIRCLE_H +#define CIRCLE_H + +#include "Shape.h" + +class Circle : public Shape { + private: + double radius; + + public: + Circle(double r); + double area() const override; + double perimeter() const override; +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/14. Makefiles/include/Rectangle.h b/CPP/Beginner/14. Makefiles/include/Rectangle.h new file mode 100644 index 0000000..8c16bae --- /dev/null +++ b/CPP/Beginner/14. Makefiles/include/Rectangle.h @@ -0,0 +1,16 @@ +#ifndef RECTANGLE_H +#define RECTANGLE_H + +#include "Shape.h" + +class Rectangle : public Shape { + private: + double width, height; + + public: + Rectangle(double w, double h); + double area() const override; + double perimeter() const override; +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/14. Makefiles/include/Shape.h b/CPP/Beginner/14. Makefiles/include/Shape.h new file mode 100644 index 0000000..0e2b5d1 --- /dev/null +++ b/CPP/Beginner/14. Makefiles/include/Shape.h @@ -0,0 +1,25 @@ +#ifndef SHAPE_H +#define SHAPE_H + +#include + +class Shape { + protected: + std::string name; + + public: + // Constructor of a shape to define its name: + Shape(const std::string& shapeName) : name(shapeName) {}; + + // Virtual functions to override: + virtual double area() const = 0; + virtual double perimeter() const = 0; + + // Common destructor for all shapes: + virtual ~Shape() = default; + + // Function to get the name: + std::string getName() const { return name; }; +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/14. Makefiles/include/Triangle.h b/CPP/Beginner/14. Makefiles/include/Triangle.h new file mode 100644 index 0000000..3a08f9c --- /dev/null +++ b/CPP/Beginner/14. Makefiles/include/Triangle.h @@ -0,0 +1,16 @@ +#ifndef TRIANGLE_H +#define TRIANGLE_H + +#include "Shape.h" + +class Triangle : public Shape { + private: + double a, b, c; + + public: + Triangle(double side1, double side2, double side3); + double area() const override; + double perimeter() const override; +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/14. Makefiles/main.cpp b/CPP/Beginner/14. Makefiles/main.cpp new file mode 100644 index 0000000..3607537 --- /dev/null +++ b/CPP/Beginner/14. Makefiles/main.cpp @@ -0,0 +1,48 @@ +#include +#include + +#include "Circle.h" +#include "Rectangle.h" +#include "Triangle.h" + +int main() { + // Defining the vector of pointers to the shapes: + std::vector shapes; + + // Adding three different shapes to the vector: + shapes.push_back(new Rectangle(2, 3)); + shapes.push_back(new Circle(4)); + shapes.push_back(new Triangle(2, 2, 2)); + + // Printing the shape parameters and recovering memory: + for (Shape* shape : shapes) { + std::cout << "\n*********\nShape: " << shape->getName() + << "\nArea: " << shape->area() + << "\nPerimeter: " << shape->perimeter() << '\n'; + + delete shape; + } + std::cout << std::endl; + + // Checking if the array is empty: + std::string result; + if (shapes.empty()) { + result = "Yes"; + } else { + result = "No"; + } + std::cout << "Is array empty after deleting the shapes individually?: " + << result << std::endl; + + // Cleaning the array and checking again: + shapes.clear(); + if (shapes.empty()) { + result = "Yes"; + } else { + result = "No"; + } + std::cout << "Is array empty after using 'clear()'?: " << result << '\n' + << std::endl; + + return 0; +} diff --git a/CPP/Beginner/14. Makefiles/src/Circle.cpp b/CPP/Beginner/14. Makefiles/src/Circle.cpp new file mode 100644 index 0000000..d3a53a5 --- /dev/null +++ b/CPP/Beginner/14. Makefiles/src/Circle.cpp @@ -0,0 +1,10 @@ +#include "Circle.h" + +#define _USE_MATH_DEFINES +#include + +Circle::Circle(double r) : Shape("Circle"), radius(r) {} + +double Circle::area() const { return M_PI * radius * radius; } + +double Circle::perimeter() const { return 2 * M_PI * radius; } diff --git a/CPP/Beginner/14. Makefiles/src/Rectangle.cpp b/CPP/Beginner/14. Makefiles/src/Rectangle.cpp new file mode 100644 index 0000000..b31c327 --- /dev/null +++ b/CPP/Beginner/14. Makefiles/src/Rectangle.cpp @@ -0,0 +1,8 @@ +#include "Rectangle.h" + +Rectangle::Rectangle(double w, double h) + : Shape("Rectangle"), width(w), height(h) {} + +double Rectangle::area() const { return width * height; } + +double Rectangle::perimeter() const { return 2 * (width + height); } diff --git a/CPP/Beginner/14. Makefiles/src/Triangle.cpp b/CPP/Beginner/14. Makefiles/src/Triangle.cpp new file mode 100644 index 0000000..efb9cf7 --- /dev/null +++ b/CPP/Beginner/14. Makefiles/src/Triangle.cpp @@ -0,0 +1,13 @@ +#include "Triangle.h" + +#include + +Triangle::Triangle(double side1, double side2, double side3) + : Shape("Triangle"), a(side1), b(side2), c(side3) {} + +double Triangle::area() const { + double s = perimeter() / 2; + return sqrt(s * (s - a) * (s - b) * (s - c)); +} + +double Triangle::perimeter() const { return a + b + c; } \ No newline at end of file diff --git a/CPP/Beginner/15. Final Project/Makefile b/CPP/Beginner/15. Final Project/Makefile new file mode 100644 index 0000000..8c24ee1 --- /dev/null +++ b/CPP/Beginner/15. Final Project/Makefile @@ -0,0 +1,24 @@ +# Folders where the .cpp and .h files are contained: +SRC_FOLDER := sources +INCL_FOLDER := includes + +# Names of the .cpp files for the code: +SRC_NAMES = Book.cpp EBook.cpp Library.cpp +SRC_FILES = $(addprefix $(SRC_FOLDER)/, $(SRC_NAMES)) +HEAD_FILES = $(addprefix $(INCL_FOLDER)/, $(SRC_NAMES:.cpp=.h)) +OBJ_FILES = $(SRC_NAMES:.cpp=.o) + +TARGET = Library + +all: main.o files.o + g++ main.o $(OBJ_FILES) -o $(TARGET) + +main.o: main.cpp + g++ -c main.cpp -I $(INCL_FOLDER) + +files.o: $(SRC_FILES) $(HEAD_FILES) + g++ -c $(SRC_FOLDER)/*.cpp -I $(INCL_FOLDER) + +# Clean rule to remove compiled files +clean: + del $(OBJ_FILES) $(TARGET).exe main.o \ No newline at end of file diff --git a/CPP/Beginner/15. Final Project/README.md b/CPP/Beginner/15. Final Project/README.md new file mode 100644 index 0000000..9886025 --- /dev/null +++ b/CPP/Beginner/15. Final Project/README.md @@ -0,0 +1,55 @@ +# Exercise 15: Building a Library Management System +In this exercise, you will create a simple library management system using classes, inheritance, and polymorphism. The system will manage a collection of books and allow users to perform basic operations like adding, listing, and searching for books. + +## Objective + +- Use classes and inheritance to model a library system. +- Apply polymorphism to handle different types of books. +- Implement functions to add, list, and search for books. +- Use file I/O to save and load book data. + +## Task + +- Base Class: Book + - Attributes: + - title (string) + - author (string) + - isbn (string) + - Methods: + - Constructor to initialize the book's details. + - `display()` to show the book's details (virtual function). +- Derived Class: EBook + - Inherits from Book. + - Additional Attribute: + - fileSizeMB (double) — the size of the ebook file in megabytes. + - Override `display()` to show ebook-specific details. +- Library Class: + - Attributes: + - A vector of pointers to Book objects. + - Methods: + - `addBook(Book* book)` — Adds a book to the library. + - `listBooks()` — Lists all books in the library. + - `searchByTitle(const std::string& title)` — Searches for a book by title and displays its details. + - `saveToFile(const std::string& filename)` — Saves the library data to a file. + - `loadFromFile(const std::string& filename)` — Loads library data from a file. + +Provide a menu-driven interface to: +- Add new books (both regular and ebooks). +- List all books. +- Search for books by title. +- Save the library data to a file. +- Load the library data from a file. + +### Expected Behavior + +- Users can interact with the library system through the console. +- Books are correctly managed and displayed according to their type (regular or ebook). +- The system should gracefully handle file I/O errors and invalid user input. + +## Tips + +- Use polymorphism to handle different book types in the Library class. +- Ensure proper memory management (delete allocated objects when done). +- Use file I/O to persist the library's state between program runs. + +# C++ theory \ No newline at end of file diff --git a/CPP/Beginner/15. Final Project/includes/Book.h b/CPP/Beginner/15. Final Project/includes/Book.h new file mode 100644 index 0000000..f7b3db0 --- /dev/null +++ b/CPP/Beginner/15. Final Project/includes/Book.h @@ -0,0 +1,40 @@ +#ifndef BOOK_H +#define BOOK_H + +#include + +/** + * @brief Base class for generic a book. + * + * Class representing a generic book. + * Private attributes: titile, author, isbn. + * Public methods: display() + */ +class Book { + private: + std::string title; + std::string author; + std::string isbn; + + public: + /** + * @brief Constructor of the class. + * @param title - title of the book. + * @param author - author of the book. + * @param isbn - isbn code of the book. + */ + Book(const std::string& title, const std::string& author, + const std::string& isbn); + virtual ~Book(); + + std::string getTitle() const; + std::string getAuthor() const; + std::string getIsbn() const; + + /** + * @brief Displays the information about the book. + */ + void display() const; +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/15. Final Project/includes/EBook.h b/CPP/Beginner/15. Final Project/includes/EBook.h new file mode 100644 index 0000000..b952aae --- /dev/null +++ b/CPP/Beginner/15. Final Project/includes/EBook.h @@ -0,0 +1,33 @@ +#ifndef EBOOK_H +#define EBOOK_H + +#include "Book.h" + +class EBook : public Book { + private: + double fileSizeMB; + + public: + /** + * @brief Constructor for EBook class. + * + * @param title - Title of the ebook. + * @param author - Author of the ebook. + * @param isbn - ISBN code of the ebook. + * @param size - MB that occupies the ebook. + */ + EBook(const std::string& title, const std::string& author, + const std::string& isbn, double size); + + double getSize() const; + + /** + * @brief Displays the information of the ebook. + * + * This function first calls the parent's function 'display()', + * then appends the file size as a new line. + */ + void display() const; +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/15. Final Project/includes/Library.h b/CPP/Beginner/15. Final Project/includes/Library.h new file mode 100644 index 0000000..d7a31b7 --- /dev/null +++ b/CPP/Beginner/15. Final Project/includes/Library.h @@ -0,0 +1,81 @@ +#ifndef LIBRARY_H +#define LIBRARY_H + +#include +#include +#include +#include + +#include "Book.h" +#include "EBook.h" + +/** + * @brief Represents a library that manages a collection of books. + * + * This class allows adding, removing and displaying books stored + * in a library. It can handle both physical books and ebooks. + */ +class Library { + private: + std::vector books; + + public: + // No constructor is needed, as it is desired for the attribute + // to be initialized empty. + + // Destructor: + ~Library(); + + /** + * @brief Adds a books to the library. + * + * This function adds a book (or ebook) to the collection. + * Whenever the book is added, the original object is removed. + * + * @param book - A unique pointer to a book object. + */ + void addBook(Book* book); + + /** + * @brief Displays all the books in the library. + * + * This function iterates over the library's collection and + * displays the details of each book. + */ + void listBooks() const; + + /** + * @brief Search a book by its title. + * + * @param title - Exact title of the book to look for. + * @param displayMatch - If true, the book information is displayed on the + * terminal (only if the book is found). + * @return bool - True if the book is found, otherwise false. + */ + bool searchByTitle(const std::string& title, bool displayMatch) const; + + /** + * @brief Saves the information of the library in a file. + * + * This functions stores the information of all the books in + * the collection in a file. Afterwards, it removes all the books + * in the collection. + * + * @param filename - Name of the output file. + * @return bool - True if the save was successful, false otherwise. + */ + bool saveToFile(const std::string& filename); + + /** + * @brief Loads the library from a file. + * + * This function updates the library with the books from a file. + * It avoids storing copies of the same book. + * + * @param filename - Name of the input file. + * @return bool - True if the load was successful, false otherwise. + */ + bool loadFromFile(const std::string& filename); +}; + +#endif \ No newline at end of file diff --git a/CPP/Beginner/15. Final Project/main.cpp b/CPP/Beginner/15. Final Project/main.cpp new file mode 100644 index 0000000..be8e7c4 --- /dev/null +++ b/CPP/Beginner/15. Final Project/main.cpp @@ -0,0 +1,46 @@ +#include "Book.h" +#include "EBook.h" +#include "Library.h" + +int main() { + // Declarations: + Library myBooks = Library(); + std::string title, author, isbn; + double fileSize; + + std::cout << "Checking first the library is empty:" << std::endl; + myBooks.listBooks(); + + // Adding a book and an ebook: + std::cout << "\nAdding 'Harry Potter' and 'Jungle Book'..." << std::endl; + title = "Harry Potter and the Philosopher's Stone"; + author = "J.K. Rowling"; + isbn = "978-0747532699"; + myBooks.addBook(new Book(title, author, isbn)); + + title = "The Jungle Book"; + author = "Rudyard Kipling"; + isbn = "978-1503215678"; + fileSize = 1.5; + myBooks.addBook(new EBook(title, author, isbn, fileSize)); + myBooks.listBooks(); + + // Populating the library from files: + std::cout << "Loading the repertory of books and ebooks..." << std::endl; + myBooks.loadFromFile("my_books.txt"); + myBooks.loadFromFile("my_ebooks.txt"); + + std::cout << "All books loaded. Please check for no duplicates:\n" + << std::endl; + myBooks.listBooks(); + + // Exporting the data into a new file: + std::cout << "Saving all books into 'my_library.txt'..." << std::endl; + myBooks.saveToFile("my_library.txt"); + + std::cout << "Exporting done, now the library should be empty:" + << std::endl; + myBooks.listBooks(); + + return 0; +} \ No newline at end of file diff --git a/CPP/Beginner/15. Final Project/my_books.txt b/CPP/Beginner/15. Final Project/my_books.txt new file mode 100644 index 0000000..01f116b --- /dev/null +++ b/CPP/Beginner/15. Final Project/my_books.txt @@ -0,0 +1,3 @@ +Book:To Kill a Mockingbird,Harper Lee,978-0-06-112008-4 +Book:1984,George Orwell,978-0-452-28423-4 +Book:The Great Gatsby,F. Scott Fitzgerald,978-0-7432-7356-5 \ No newline at end of file diff --git a/CPP/Beginner/15. Final Project/my_ebooks.txt b/CPP/Beginner/15. Final Project/my_ebooks.txt new file mode 100644 index 0000000..9f65849 --- /dev/null +++ b/CPP/Beginner/15. Final Project/my_ebooks.txt @@ -0,0 +1,3 @@ +EBook:The Pragmatic Programmer,Andrew Hunt & David Thomas,978-0135957059,4.2 +EBook:Clean Code,Robert C. Martin,978-0132350884,3.8 +EBook:Clean Code,Robert C. Martin,978-0132350884,3.8 \ No newline at end of file diff --git a/CPP/Beginner/15. Final Project/my_library.txt b/CPP/Beginner/15. Final Project/my_library.txt new file mode 100644 index 0000000..ca7262e --- /dev/null +++ b/CPP/Beginner/15. Final Project/my_library.txt @@ -0,0 +1,7 @@ +Book:Harry Potter and the Philosopher's Stone,J.K. Rowling,978-0747532699 +EBook:The Jungle Book,Rudyard Kipling,978-1503215678,1.5 +Book:To Kill a Mockingbird,Harper Lee,978-0-06-112008-4 +Book:1984,George Orwell,978-0-452-28423-4 +Book:The Great Gatsby,F. Scott Fitzgerald,978-0-7432-7356-5 +EBook:The Pragmatic Programmer,Andrew Hunt & David Thomas,978-0135957059,4.2 +EBook:Clean Code,Robert C. Martin,978-0132350884,3.8 diff --git a/CPP/Beginner/15. Final Project/sources/Book.cpp b/CPP/Beginner/15. Final Project/sources/Book.cpp new file mode 100644 index 0000000..4f79b03 --- /dev/null +++ b/CPP/Beginner/15. Final Project/sources/Book.cpp @@ -0,0 +1,17 @@ +#include "Book.h" +#include + +Book::Book(const std::string& title, const std::string& author, + const std::string& isbn) + : title(title), author(author), isbn(isbn) {} +Book::~Book() {}; + +std::string Book::getTitle() const { return title; } +std::string Book::getAuthor() const { return author; } +std::string Book::getIsbn() const { return isbn; } + +void Book::display() const { + std::cout << "Title: " << title << '\n' + << "Author: " << author << '\n' + << "ISBN: " << isbn << std::endl; +} diff --git a/CPP/Beginner/15. Final Project/sources/EBook.cpp b/CPP/Beginner/15. Final Project/sources/EBook.cpp new file mode 100644 index 0000000..f1e88e4 --- /dev/null +++ b/CPP/Beginner/15. Final Project/sources/EBook.cpp @@ -0,0 +1,14 @@ +#include "EBook.h" + +#include + +EBook::EBook(const std::string& title, const std::string& author, + const std::string& isbn, double size) + : Book(title, author, isbn), fileSizeMB(size) {} + +double EBook::getSize() const { return fileSizeMB; } + +void EBook::display() const { + Book::display(); + std::cout << "File size: " << fileSizeMB << std::endl; +} \ No newline at end of file diff --git a/CPP/Beginner/15. Final Project/sources/Library.cpp b/CPP/Beginner/15. Final Project/sources/Library.cpp new file mode 100644 index 0000000..a42e75a --- /dev/null +++ b/CPP/Beginner/15. Final Project/sources/Library.cpp @@ -0,0 +1,100 @@ +#include "Library.h" + +void Library::addBook(Book* book) { books.push_back(book); } + +void Library::listBooks() const { + if (books.empty()) { + std::cout << "No books stored in the library." << std::endl; + } else { + for (const auto& book : books) { + book->display(); + std::cout << '\n'; + } + std::cout << std::endl; + } +} + +bool Library::searchByTitle(const std::string& title, bool displayMatch) const { + for (const auto& book : books) { + if (book->getTitle() == title) { + if (displayMatch) { + book->display(); + } + return true; + } + } + return false; +} + +bool Library::saveToFile(const std::string& filename) { + if (books.empty()) { + std::cerr << "The library does not contain any book." << std::endl; + return false; + } + + std::ofstream outFile(filename); + if (!outFile) { + std::cerr << "Error opening the file." << std::endl; + return false; + } + + for (auto& book : books) { + // Using 'dynamic_cast' to identify if the book is an ebook. + // This returns a pointer to the EBook or a nullptr if the object is not + // an ebook. + EBook* ebook = dynamic_cast(book); + if (ebook) { + outFile << "EBook:" << ebook->getTitle() << ',' + << ebook->getAuthor() << ',' << ebook->getIsbn() << ',' + << ebook->getSize() << '\n'; + } else { + outFile << "Book:" << book->getTitle() << ',' << book->getAuthor() + << ',' << book->getIsbn() << '\n'; + } + } + books.clear(); + outFile.close(); + return true; +} + +bool Library::loadFromFile(const std::string& filename) { + std::ifstream inFile(filename); + if (!inFile) { + std::cerr << "Error opening the reading file: " << filename + << std::endl; + return false; + } + + std::string bookType, title, author, isbn, fileSizeStr; + while (std::getline(inFile, bookType, ':')) { + // Obtaining the common parameters: + std::getline(inFile, title, ','); + std::getline(inFile, author, ','); + + // Checking the book is not already in the library: + bool inLibrary = searchByTitle(title, false); + if (inLibrary) { + // Skip to the next iteration if the book is already stored: + continue; + } + + if (bookType == "EBook") { + std::getline(inFile, isbn, ','); + std::getline(inFile, fileSizeStr); + double fileSize = std::stod(fileSizeStr); + + addBook(new EBook(title, author, isbn, fileSize)); + } else { + std::getline(inFile, isbn); + addBook(new Book(title, author, isbn)); + } + } + + return true; +} + +Library::~Library() { + for (auto& book : books) { + delete book; + } +} \ No newline at end of file diff --git a/CPP/Intermediate/01. Dynamic memory management/Readme.md b/CPP/Intermediate/01. Dynamic memory management/Readme.md new file mode 100644 index 0000000..6a56fe1 --- /dev/null +++ b/CPP/Intermediate/01. Dynamic memory management/Readme.md @@ -0,0 +1,81 @@ +# Exercise 1: Dynamic Memory Management + +## Objective +Understand how to manually manage memory using `new` and `delete`, and how to avoid memory leaks and dangling pointers. + +## Task +Create a C++ program that: + +- Dynamically allocates memory for an array of integers using `new`. +- Fills the array with integers from 1 to 10. +- Prints the content of the array. +- Deletes the allocated memory using `delete[]`. +- After deleting the array, attempt to access the array and demonstrate what happens when you try to use a dangling pointer. + +## Expected Result + +- The program should print the numbers 1 to 10. +- After the memory is deleted, accessing the array should either produce an error or garbage values. +- You should avoid any memory leaks by ensuring proper memory deallocation. + +## Hints +- Use a pointer to allocate memory for the array. +- Always check if memory has been allocated before accessing it. +- Once memory is deleted, make the pointer nullptr to avoid accessing a dangling pointer. + +# C++ theory + +Dynamic memory allocation allows allocating memory during runtime. +This is useful when the memory size of a program is unknown. + +## Operators `new` and `delete` + +The `new` operator allocates memory on the heap (dynamic memory) at runtime. +It returns a pointer to the block of memory allocated. + +```cpp +// Pointer to an integer +int* ptr = new int; + +// Pointer to the first element of an array +int* array_ptr = new int[10]; +``` + +The `delete` operator is used to free the dynamically allocated memory, ensuring the memory is no longer in use. +Failing to free the memory can lead to **memory leaks**. + +```cpp +// Freeing memory of a normal pointer +delete ptr; + +// Freeing memory of the entire array +delete[] array_ptr; +``` + +## Memory leaks + +Allocated memory occupies space in the systems's memory. +If the allocated memory is not free, it can lead to **memory leaks**, where the system runs out of memory. + +## Dangling pointers + +After using `delete`, the pointer still holds the old memory address (although it is not valid anymore). +It is of good practice to assign the pointer to a `nullptr` to prevend undefined behavior and potential crashes. + +```cpp +#include + +int main() { + // Dynamically allocate memory for an integer + int* num = new int; + *num = 42; + + std::cout << "Value of num: " << *num << std::endl; + + // Deallocate memory + delete num; + num = nullptr; // Avoid dangling pointer + + return 0; +} +``` \ No newline at end of file diff --git a/CPP/Intermediate/01. Dynamic memory management/memory.cpp b/CPP/Intermediate/01. Dynamic memory management/memory.cpp new file mode 100644 index 0000000..0d2f589 --- /dev/null +++ b/CPP/Intermediate/01. Dynamic memory management/memory.cpp @@ -0,0 +1,44 @@ +#include + +int main() { + // Dinamically allocate an array of 10 integers: + int* array = new int[10]; + + // Fill the array with values from 1 to 10: + for (int i = 0; i < 10; i++) { + array[i] = i + 1; + } + + // Print the content of the array: + std::cout << "Array content:\n"; + for (int i = 0; i < 10; i++) { + std::cout << array[i] << " "; + } + std::cout << std::endl; + + // Delete the allocated array: + delete[] array; + + // Attempt to access the array values: + /** + * Warning: This is unsafe and can lead to undefined beahvior. + * Some possible outcomes are: + * - See the old values (if the memory has not been reused by the system). + * - Get garbage values. + * This might lead in some ocations to leading a crash on the program. + */ + std::cout << "Attempting to access the array after deletion: "; + for (int i = 0; i < 10; ++i) { + std::cout << array[i] << " "; + } + std::cout << std::endl; + + // Best practise: setting the array to a null pointer: + array = nullptr; + + std::cout << "Attempting to access the array after assigning to a null " + "pointer:\n" + << array << std::endl; + + return 0; +} diff --git a/CPP/Intermediate/02. Deep copy and rule of three/Readme b/CPP/Intermediate/02. Deep copy and rule of three/Readme new file mode 100644 index 0000000..42ef248 --- /dev/null +++ b/CPP/Intermediate/02. Deep copy and rule of three/Readme @@ -0,0 +1,26 @@ +# Exercise 2: Deep Copy and the Rule of Three +## Objective +- Learn how to implement proper copy constructors, assignment operators, and destructors to manage resources in classes that handle dynamic memory. +- Understand the Rule of Three, which states that if a class requires a user-defined destructor, copy constructor, or copy assignment operator, it probably requires all three. + +# Task: +1. Create a class IntArray that: + - Dynamically allocates an array of integers. + - Implements the Rule of Three by providing: + - A destructor to free the allocated memory. + - A copy constructor to perform a deep copy of the object. + - A copy assignment operator to properly assign one object to another. +2. The class should include: + - A constructor that takes an integer to specify the size of the array. + - A method to set the values of the array. + - A method to print the contents of the array. +3. Test the deep copy by creating an object, copying it to another object, and modifying the original object. The changes should not affect the copied object (i.e., no shallow copying). + +## Expected Result +- The copied object should have its own separate copy of the array, so modifying one object’s array should not affect the other’s. +- No memory leaks should occur, and all resources should be properly managed. + +## Hints +In the copy constructor, allocate new memory for the copied object and copy the elements manually. +In the assignment operator, check for self-assignment (i.e., when an object is assigned to itself). +Ensure proper memory deallocation before reassigning memory in the assignment operator. \ No newline at end of file diff --git a/CPP/README.md b/CPP/README.md new file mode 100644 index 0000000..0fa0f01 --- /dev/null +++ b/CPP/README.md @@ -0,0 +1,39 @@ +# C++ roadmap + +This repository contains a set of exercises with the purpose of learning/improving C++ for anyone. + +## Exercises + +Each exercise is defined with a 'readme' file, containing the following sections: + +- **Objective**: Brief explanation of the main objective of the exercise. +- **Task**: Instructions to be included in the program. +- **Expected result**: The expected outcome when the program runs. +- **C++ theory**: The needed theory to complete the exercise. + +Additionally, within each exercise folder are contained the `.cpp` and `.h` files needed to create and run the program successfully. + +> Note: Each exercise assumes that the theory from the previous exercises is known. + +## Index + +- Beginner: + - [00: Getting started (hello world)](Beginner/00.%20Getting%20started/README.md) + - [01: Basic terminal IO](Beginner/01.%20Basic%20IO/README.md) + - [02: Variable types and math operations](Beginner/02.%20Basic%20operations/README.md) + - [03: Conditional statements](Beginner/03.%20Conditional%20statements/README.md) + - [04: While-loops](Beginner/04.%20While%20loops/README.md) + - [05: Arrays and for-loops](Beginner/05.%20For%20loops/README.md) + - [06: Input handling](Beginner/06.%20Input%20handling/README.md) + - [07: Functions and header files](Beginner/07.%20Functions/README.md) + - [08: File IO process](Beginner/08.%20File%20IO%20process/README.md) + - [09: Pointers](Beginner/09.%20Pointers/README.md) + - [10: Vectors](Beginner/10.%20Vectors/README.md) + - [11: Classes and OOP](Beginner/11.%20OOP%20and%20Classes/README.md) + - [12: Class inheritance](Beginner/12.%20Class%20inheritance/README.md) + - [13: Polimorphism](Beginner/13.%20Polymorphism/README.md) + - [14: Makefiles](Beginner/14.%20Makefiles/README.md) + - [15: Final project](Beginner/15.%20Final%20Project/README.md) +- Intermediate: + - [01: Dynamic Memory Management](Intermediate/01.%20Dynamic%20memory%20management/Readme.md) +- Advanced: (TBD) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7955036 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Coding Exercises Roadmap + +In this repo you can find multiple exercises to master programming languages. + +Each language's roadmap is organized by different exercises (each one in its own folder) containing: +- The theory to understand the topic it is to teach. +- A small exercise to practice what is new to learn, as well as using previous knowlege. +- The program file with the solution to the exercise. + +--- + +## Current supported languages + +- [C/C++](CPP)