This project was developed for 42 school. For comprehensive information regarding the requirements, please consult the PDF file in the subject folder of the repository. Furthermore, I have provided my notes and a concise summary below.
+ keywords: object oriented programming
+ projects must comply with the C++98 standard (42 school requirement)
+ relation among types. Classes to define types (user-defined types, classes and enumerations)
+ C++ augments the built-in types and operations with a set of abstraction mechanisms (leap of abstraction from C - compact type performance code)
- C++11 (and derived forms) and Boost libraries are forbidden. The following functions are forbidden too: *printf(), *alloc() and free(). If you use them, your grade will be 0 and that’s it.
- You are allowed to use the STL in the Module 08 and 09 only. That means: no Containers (vector/list/map/and so forth) and no Algorithms (anything that requires to include the header) until then.
- When you allocate memory (by using the new keyword), you must avoid memory leaks.
- From Module 02 to Module 09, your classes must be designed in the Orthodox Canonical Form, except when explicitely stated otherwise.
- C++ module 00 - classes, member functions, stdio streams, initialisation lists, static, const
- C++ module 01 - memory allocation, pointers to members, references and switch statement
- C++ module 02 - create a class in Orthodox Canonical Form that represents a fixed-point number
- C++ module 03 - inheritance
- C++ module 04 - subtype polymorphism, abstract classes, interface
#include <iostream>
#include <string>
#include <vector>
class Person {
// private:
protected:
std::string first;
std::string last;
public:
Person(std::string first, std::string last): first(first), last(last) {} // constructor initialization list. It will remove the ability of creating a constructor without passing data as arguments
Person(std::string first, std::string last) {
this->first = first;
this->last = last;
} // constructor initialization list. Customer constructor
Person() = default; // default constructor still available
void setFirstName(std::string firstName) { this->first = firstName; }
void setLastName(std::string lastName) { this->last = lastName; }
std::string getFullName() { return first + " " + last };
void printFullName() { std::cout << first << " " << last << std::endl; }
virtual void printInfo() {
std::cout << "first name: " << first << std::endl;
std::cout << "last name: " << last << std::endl;
}
static void printPeople(std::vector<Person*> people) {
for(auto person : people) {
person->printInfo();
}
}
}
class Employee : Person {
std::string department; //it is private by default
public:
Employee(std::string firstName, std::string lastName, std::string department): Person(firstName, lastName), department(department) {}
std::string getDepartment() {
return department;
}
void setDepartment(std::string department) {
this->department = department;
}
void printInfo() override {
std::cout << "first name: " << first << std::endl; // won't work because it is set as private in the class Person (inaccessible error)... change private to protected instead
std::cout << "last name: " << last << std::endl;
std::cout << "name: " << getFullName() << std::endl;
std::cout << "department: " << department << std::endl; // it will work because the variable is set inside this class;
}
};
int main(void)
{
// Person p;
// p.setFirstName() = "Sofia";
// p.setLastName() = "Dias";
std::vector<Person*> people; // person pointer
Person p("Sofia", "Dias"); // custom constructor
p.printFullName();
std::cout << getFullName() << std::endl;
Person p2; // default constructor
p2.setFirstName() = "José";
p2.setLastName() = "Dias";
p2.printFullName();
// Employee e;
// e.setFirstName("Pesto");
// e.setLastName("The Dog");
Employee e("Nicholas", "Ghitti", "Sales Department");
e.printFullName();
std::cout << e.getDepartment() << std::endl;
e.printInfo();
people.push_back(&p); // address
people.push_back(&e); // pushing both to the base class
for(auto person : people) {
person->printInfo(); // it will print a different message, according to the reference pointed in the loop
}
Person::printPeople(people); // exactly the same output as the previous for loop
// invoking through the Person class (not its instace)
}
Bjarne Stroustrup: C++ | Lex Fridman Podcast #48
CPP00 - CPP01
A Tour of C++ (Second edition) Exercises
CPP02
Ep 018: Introduction to Floating-Point Binary and IEEE-754 Notation
Understanding and Using Floating Point Numbers
Floating point number representation
Printing floating point numbers
Introduction to Fixed Point Number Representation
Floating Point Numbers - Computerphile
class Vector {
public:
Vector(int s) :elem{new double[s]}, sz{s} {} // construct a vector
double& operator[](int i) {return elem[i];} // element access: subscripting
int size() {return sz;}
private:
double* elem; // pointer to the elements
int sz; // the number of elements
}
#include <ieee754.h>
#define LOG2_10 3.321928095
#define flt_zero(x) (fabs(x) < EPSILON)
int max_digs_rt = 3; /* maximum # of 0's right of decimal before using
scientific notation */
int max_digs_lf = 5; /* max # of digits left of decimal */
void print_real(double r, int width, int dec)
{
int mag;
double fpart, temp;
char format[8];
char num_format[3] = {'l',0,0};
union ieee754_double *dl;
dl = (union ieee754_double*)&r;
mag = (dl->ieee.exponent - IEEE754_DOUBLE_BIAS) / LOG2_10;
if (r == 0)
mag = 0;
if ((mag > max_digs_lf-1) || (mag < -max_digs_rt)) {
num_format[1] = 'e';
temp = r/pow(10, mag); /* see if number will have a decimal */
fpart = temp - floor(temp); /* when written in scientific notation */
}
else {
num_format[1] = 'f';
fpart = r - floor(r);
}
if (flt_zero(fpart))
dec = 0;
if (width == 0) {
snprintf(format, 8, "%%.%d%s", dec, num_format);
}
else {
snprintf(format, 8, "%%%d.%d%s", width, dec, num_format);
}
printf(format, r);
}
To run this project on Linux from a different OS, I'm using Multipass to create a virtual machine. Follow these steps to set it up:
- Download or upgrade multipass with HomeBrew
brew install multipass brew upgrade multipass multipass version
- Launch a Virtual Machine
- Customize your virtual machine during launch by specifying options like the Ubuntu release (--release), CPU count (--cpus), memory size (--mem), etc.
multipass launch --name my-vm
- Access the Virtual Machine
multipass shell my-vm multipass list
- Stop or delete the Virtual Machine
multipass stop my-vm multipass delete my-vm
- Create a SSH connection
- To speed up the process of linking the new instance with the SSH key from the previous step, we will use a little bit of cloud-init -> Copy and paste the below text into a file called vscode.yaml. Replace with the key found in id_rsa.pub, generated in an earlier step
groups: - vscode runcmd: - adduser ubuntu vscode ssh_authorized_keys: - ssh-rsa <public key>
- Next, open a terminal in the same location as this file, and launch a new instance referencing this cloud-init file:
multipass launch --cloud-init vscode.yaml
- Install SSH Server (if not installed): Ensure that SSH server is installed on your virtual machine. On Ubuntu, you can install it with:
sudo apt update sudo apt install openssh-server
- Check SSH Service Status: Verify that SSH service is running on the virtual machine:
sudo systemctl status ssh
- Determine the IP address of your virtual machine:
multipass list
-> 192.168.64.17 - Generate SSH keys to authenticate communication between the VM and host
ssh-keygen -t rsa
-> host machine - Download VSCode extension
Remote - SSH
- In VSCode, click on
Open a Remote Window
-> Connect to Host -> Add New SSH Host... -> ssh [email protected] - It will generate a new entry in config file
Include /Users/hincksof/.colima/ssh_config Host 192.168.64.17 HostName 192.168.64.17 User ubuntu IdentityFile /Users/hincksof/ubuntu_config/.ssh/id_rsa Host 192.168.64.13 HostName 192.168.64.13 User ubuntu IdentityFile /Users/hincksof/ubuntu_config/.ssh/id_rsa
- At this point, VSCode will ask you for the location of your SSH keys. The default location should be in a hidden directory named “.ssh” in the home directory.
IdentityFile
is the place where it is stored the public key generated previously in yout host machine ->ssh-keygen -t rsa