# УДАЧИ НАМ

## Statement

> Наименьшая независимая еденица в языке C++

### Основные

* declaration:

    ```C++
    int i;
    ```

* assigment :

    ```C++
    i = 5;
    ```

* Output (хоть Коля и не согласен, что это основной)

    ```C++
    std::cout << i;
    ```

declaration и assigment можно вместе

```C++
int i = 5;
```

## Expression

> Любое выражение: число, строка, вызов функции, мат(на английском). выражения

## Функции

> Последовательность statement'ов. Исполнение начинается с функции main()

## Библиотеки

> Набор скомпилированного кода, для использования в других программах

### Примеры библиотек

* iostream - для ввода / вывода

## Коментарии

* Однострочные

    ```C++
    // Коментарий
    ```

* Многострочные

    ```C++
    /* Длинный
    Коментарий */
    ```

## Пример простой программы

```C++
#include <iostream>

int main() {
    std::cout << "Hello, world!\n";
}
```

## Переменные

> В C++ есть переменные, они жрут оперативку

* Копирующая инициализация

```C++
int val = 5;
```

* Прямая инициализация

```C++
int val(5);
```

### Неинициализированные переменные

> Неинициализированные переменные могут иметь в себе мусор, что может привести к ошибкам

### Инициализация и объявление нескольких переменных

```C++
int a, b;
```

```C++
int a = 5, b = 6;
```

## Типы данных

* void - ничего

### Числа

* short - число 16 бит
* int - число 16 или 32 бита
* long - число 32 бита
* long long - число 64 бита
* char - число или символ. 8 бит

#### Отрицательные числа

* signed - может быть отрицательным (по умолчанию, кроме char)
* unsigned - число не отрицательно

#### Переполнение

* Переполнение случается при потере бит из-за того, что значение после операции выходит за границу их значений

65635 как unsigned int + 1 выдаст 0

#### Целочисленное деление

Деление двух цилочисленных значений всегда выдаёт целое число (округление вниз)

### Символьные тип char

char представляет собой 1 символ (не всегда) и всегда весит 1 байт.

Для инициализации char символом используется *одинарные* ковычки

### Строки

Для строк используется библиотека string. Строки указываются в двойных ковычках

### Типы данных с плавающией точкой

Типы с плавающей могут показывать дробные числа

* float - 32 бита
* double - 64 бита (двойная точность по сравнению с float)
* long double - от 8 до 16 байт (зависит от компилятора)

### Логические значения

* true
* false

## Константы

> Величины, которые остаются неизменными. Они должны быть инициализированны при объявлении

## IOSTREAM

### Подключение IOSTREAM

```C++
#include <iostream>;
```

### *cout*

> *cout* - объект для вывода в терминал

```C++
#include <iostream>;

std::cout << 5 << '\n';
```

### *endl*

> endl можно использовать как '\n'

```C++
#include <iostream>;

std::cout << 5 << std::endl;
```

### *cin*

> cin используется для ввода значений из терминала

```C++
#include <iostream>;

int a = 0;
std::cin >> a;
```

## Ветвление

```C++
#include <iostream>;

int a = 5;
if (a == 5) {
    std::cout << 5 << '\n';
} else if (a == 6) {
    std::cout << 6 << '\n';
} else {
    std::cout << "Neither\n";
}
```

### Логические операторы

* && - и
* || - или
* ! - не

## Циклы

### Цикл for

> for (инициализация; условие; изменение)

```C++
#include <iostream>;

// Выводит числа от 0 до 5 включительно
for (int i = 0; i <= 5; i++) {
    std::cout << i << '\n';
}
```

### Цикл while (с пред условием)

```C++
#include <iostream>;

// Аналогичен коду сверху
int i = 0;
while (i <= 5) {
    std::cout << i << '\n';
    i++;
}
```

### Цикл do while

> Цикл do while выполнит тело хотя бы один раз, даже если условие изначально false

```C++
#include <iostream>;


// Выведет 0 (не смотря на то, что 0 чётное) и 1
int i = 0
do {
    std::cout << i << '\n';
    i++;
} while (i % 2 != 0)
```

### Операторы прерывания

* *break*
* *continue*

Они аналогичны оным из Python

## switch

```C++
int a = 5;
switch(a){
    case 1:
        std::cout << "1" << '\n';
        break;
    case 2:
        std::cout << "2" << '\n';
        break;
    default:
        std::cout << "Other" << '\n';
        break;
}
```

## Goto

> Goto позволяет перейти к исполнению другого блока кода. Если будете его использовать, то придёт страшный Николай и даст по рукам книжкой о правильном написании кода

```C++
mark:
    // do-something

// 1 eternity later (возможно даже в другой функции)

goto mark;
```

## Массивы

> Структура данных позволяющая хранить набор элементов одного типа. Объявление состоит из указания типа и размерности. Массивы в C++ имеют нумерацию элементов, начинающуюся с 0

### Объявление массива

```C++
int number[5]; // пять интов. Массив называется numbers
char chars[20];
bool flags[3];
```

### Инициализация массива

```C++
int numbers[3] = {10, 20, 30};
int foo[] = {10, 20, 30}; // Тоже будет на 3 элемента
int bar[10] = {10, 20, 30} // Оставшиеся 8 не инициализированны
```

### Обход массива

```C++
#include <iostream>

int numbers[] = {10, 20, 30}

for (int i = 0; i < 3; i++) {
    std::cout << i << '\n';
}
```

### Размер массива

```C++
int arr[5];

int n = sizeof(arr) / sizeof(int); // n - длинна массива
```

### Многомерные массивы

```C++
#include <iostream>

int arr[2][2] = {{10, 20}, {30, 40}};
for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
        std::cout << arr[i][j] << '\n';
    }
}
```

### Динамический массив

> Массив, размер которого может быть указан в runtime. Ключевое слово *new* используется для создания, a *delete* для освобождения памяти.

```C++
int* dynamic_array = new int[5]; // dynamic_array - список из 5 чисел
delete[] dynamic_array;
```

```C++
#include <iostream>

int n;
std::cin >> n;
int* nums = new int[n];

for (int i = 0; i < n; i++) {
    std::cin >> nums[i];
}

for (int i = 0; i < n; i ++) {
    std::cout << nums[i] << ' ';
}
std::cout << std::endl;

delete[] nums;
```

## Процедуры и функции

> Процедуры - функции, которые возвращают void

```C++
#include <iostream>

// Функция, возвращает int который получила
int foo(int n) {
    return n;
}

// Процедура
void bar(int n) {
    std::cout << n << '\n';
}
```

### Передача значений в функцию

> При передаче аргумента, как значения, создаётся его копия, а при передаче по ссылки, копия не создаётся и может менять его

```C++
#include <iostream>

void increment1(int i) {
    i++;
    std::cout << i << '\n';
}

void increment2(int& i) {
    i++;
    std::cout << i << '\n';
}

int main() {
    int i = 5;
    increment1(i) // Выведет 6, но i останется 5
    increment2(i) // Выведет 6, и i станет 6
}
```

### Передача массивов в функцию

> При передаче массивов в функцию, нужно кинуть туда ещё и длину. Функция может менять оригинальный массив. Копия не создаётся

```C++
#include <iostream>

void foo(int bar[], int size) {
    if (size >= 1) {
        std::cout << bar[1] << '\n';
    } else {
        std::cout << "Not enough elements\n";
    }
}
```

## Ссылки и указатели

> *Ссылка* (*reference*) - псевдоним джя существующей переменной. Может иметь не валидный адрес или быть не инициализированной

```C++
int a = 5;
int& b = a; // При изменении b, будет меняться a
b++; // a и b станут 6
```

> Указатель (*pointer*) содержит адрес существующей переменной

```C++
int a = 5;
int* b = &a; // При изменении b, будет меняться a
(*b)++ // a станет равна 6
```

## Строки (углубление)

```C++
#include <iostream>
#include <string>

int main() {
    std::string a = "abc";

    // b - копия a
    std::string b = a;

    // c содержит 'c'
    сhar c = a[2];

    // последний символ a стал z
    a[2] = 'z'
}
```

### Перебор символов

```C++
#include <string>

std::string a = "abc"
for (char c: a) {
    std::cout << c << '\n';
}

for (int i = 0; i < a.length(); i++) {
    std::cout << a[i] << '\n';
}
```

### Ввод строки с клавиатуры

```C++
#include <iostream>
#include <string>

std::string str;
// Ввести 1 слово
std::cin >> str;

// Ввести строку
std::getLine(std::cin, str);
```

### Полезные методы строк

* length(), size() - длина строки
* substr(start,length) - извлекает часть строки
* find(substring) - первое вхождение
* replace(oldString, NewString) - заменяет все вхождения из старой в новую строку (ничего не возвращает, изменения на месте)
* toupper(), tolower() - меняет регистр соответсвенно названию
* empty() - проверяет пустая ли строка
* compare() -сравнивает две строки. Возвращает 0, если строкми одинаковые.
* insert(index,string) - вставляет строку в указанную позицию.
* erase(start,length) - удалает часть строки

### Полезные функции для строк

* getLine(inputStream, string) - считывает строку из потока и тсохраняет в переменную str

## Способы передачи аргументов в функию

* по значению (pass by value) - создание копии
  * Изначальное не меняется
  * Создание копии может занимать много времени
  * Используется для передачи примитивов
* по сслылке (pass by reference) - передача в функцию указатель на объект
  * Изначальное значение может меняться
  * Копия не создаётся
  * Используется для составных типов и больших объектов
* Передача по указателю (pass by pointer) - pass by reference без кучки синтактического сахара
    Разименование - операция, которая позволяет получить доступ к значению, на которое указывает pointer.(*)

```C++
void boo(int* ptr) {
    (*ptr)++;
}
```

## Возврат значений из функции

* Возврат по значению return
* Важно не вернуть ссылку или указатель на локальную переменную

## Структуры

> Структура - тип данных, позоляющий объединить несколько переменных в одной еденице.

```C++
#include <iostream>

struct Employee {
    short id;
    int age;
    double salary;
};

Employee john = {5, 20, 30.0}; 
std::cout << john.id << ' ' << john.age << ' ' << john.salary << '\n';
```

## Перечисления

> Перечисление - это пользовательский тип данных, который представляет собой набор именованных констант, которым присваиваются целочисленные значения. Весит как *int*

```C++
#include <iostream>

enum Weekday {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday,
};

enum Weekday2 {
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
    Sunday = 7,
};

Weekday today = Saturday;
```

Weekday полностью аналогичен Weekday2

## Объединение

> Объединение - это пользовательский тип данных, позволяющий хранить различные типы данных в одной области памяти. Объединение занимает память, достаточную для хранения переменной имеющий самый большой размер.

```C++
union MyUnion{
    int intValue;
    char charValue;
};

MyUnion val = 65;
int a = val.intValue; // 65
char b = val.charValue; // 'A'
```

## Передача значений в функцию (Подробнее)

* Передача по значению (создаётся копия, может быть медленно, используется для примитивов)

    ```C++
    void increment(int a) {
        a++;
    }

    int a = 5;
    increment(&a); // a остаётся 5
    ```

* Передача по ссылке (копия не создаётся, используется для больших значений / структур, аналогична передаче по значению, но синтаксис проще)

    ```C++
    void increment(int& a) {
        a++;
    }

    int a = 5;
    increment(a); // a становится 6
    ```

* Передача по указателю (копия не создаётся, используется в основном для массивов)

    ```C++
    void increment(int* a) {
        (*a)++;
    }

    int a = 5;
    increment(&a); // a тоже становится 6
    ```

## Классы

> Классы - шаблон или описание, определяющее структуру поведения объектов.
> Объект - экземляр класса

```С++
class ClassName{
// Поля и методы класса
};
```

> Поля класса - переменные, котроые представляют состояие объетогв класса
> Методы класа - функции, которые определяют поведение объектов класса

```С++
ClassName objectName; // создание объекта класса просто

ClassName objectName = new ClassName(); //создание объекта класса сложно
delete objectName;
```

## Пример

```С++
#include <iostream>
#include <string>

class Person{
public:
std::string name;
int age;

void displayInfo(){
    std::count << "Name: " << name << ", Age: " << age << '\n';
}
}

int main(){
Person person1;
person1.name = "Alice";
person1.age = 25;
person1.displayInfo();

Person* person2 = new Person();
person2 -> name = "Bob";
person2 -> age = 30;
person2 -> displayInfo();

delete person2;
return 0;
}
```

> Пользовательский тип данных

### Модификаторы доступа

* public - доступно всем (по умолчанию в struct)
* private - доступно только внутри класса (по умолчанию в class)
* protected - достпуно внутри класса и наследникам

### Конструктор и деструктор

> Конструктор - функция, которая вызывается при инициализации класса (может быть несколько)
> Деструктор - функция, которая вызывается при уничтожении объекта

```C++
#include <iostream>

class MyClass {
public:
    MyClass() {
        std::cout << "Constructed\n";
    }

    MyClass(int val) {
        std::cout << "Constucted" << val << '\n';f
    }

    ~MyClass() {
        std::cout << "Destroyed\n";
    }
};
```

### this

> this - указатель на объект вызвовший метод

```C++
#include <string>

class Foo{
public:
    Person(std::string val) {
        this->name = val;
    }
};
```

## ООП

> Инкапсуляция - данные класса скрыты от прямого доступа и манипулиций извне класса
> Наследование - создаёт классы-потомки
> Полимарфизм - разные классы используют один и тот же интерфейс

```C++
#include <iostream>

class Figure {
public:
    virtual void draw() {
        std::cout << "Draw figure\n";
    }
};

class Circe: public Figure {
public:
    void draw() override {
        std::cout << "Draw circle\n";
    }
};

class Rectangle: public Figure {
public:
    void draw() override {
        std::cout << "Draw rectangle\n";
    }
};

int main() {
    Figure* figure = new Figure();
    Figure* circle = new Circle():
    Figure* rectangle = new Rectangle();

    figure->draw();
    circle->draw();
    rectangle->draw();

    delete figure;
    delete circle;
    delete rectangle;
}
```
