# УДАЧИ НАМ ## 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 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 ; ``` ### *cout* > *cout* - объект для вывода в терминал ```C++ #include ; std::cout << 5 << '\n'; ``` ### *endl* > endl можно использовать как '\n' ```C++ #include ; std::cout << 5 << std::endl; ``` ### *cin* > cin используется для ввода значений из терминала ```C++ #include ; int a = 0; std::cin >> a; ``` ## Ветвление ```C++ #include ; 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 ; // Выводит числа от 0 до 5 включительно for (int i = 0; i <= 5; i++) { std::cout << i << '\n'; } ``` ### Цикл while (с пред условием) ```C++ #include ; // Аналогичен коду сверху int i = 0; while (i <= 5) { std::cout << i << '\n'; i++; } ``` ### Цикл do while > Цикл do while выполнит тело хотя бы один раз, даже если условие изначально false ```C++ #include ; // Выведет 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 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 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 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 // Функция, возвращает int который получила int foo(int n) { return n; } // Процедура void bar(int n) { std::cout << n << '\n'; } ``` ### Передача значений в функцию > При передаче аргумента, как значения, создаётся его копия, а при передаче по ссылки, копия не создаётся и может менять его ```C++ #include 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 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 #include 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 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 #include 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 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 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 #include 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 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 class Foo{ public: Person(std::string val) { this->name = val; } }; ``` ## ООП > Инкапсуляция - данные класса скрыты от прямого доступа и манипулиций извне класса > Наследование - создаёт классы-потомки > Полимарфизм - разные классы используют один и тот же интерфейс ```C++ #include 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; } ```