DNK_C_C++_Go_Rust
45 subscribers
14 photos
45 links
DNK - дневник кодера С и С++
Download Telegram
#77_ADM_DvOp_NTWK

NGINX (произносится как "энжин-экс") – это высокопроизводительный веб-сервер с открытым исходным кодом, который был создан Игорем Сысоевым в 2004 году.
Изначально он разрабатывался для решения проблемы обработки большого количества одновременных соединений, что особенно актуально для высоконагруженных сайтов.

Основные функции Nginx:

— ВЕБ - СЕРВЕР.
Основная функция Nginx заключается в обслуживании статического контента (HTML-файлы, изображения, CSS-стили, JavaScript). Он отлично справляется с обработкой множества параллельных запросов благодаря своей архитектуре событийного ввода-вывода.

— ОБРАТНЫЙ ПРОКСИ (reverse proxy).
Nginx может работать как промежуточный сервер между клиентом и основным сервером приложения.
Это позволяет распределять нагрузку между несколькими серверами, кэшировать ответы, балансировать трафик и защищать основной сервер от перегрузок.

— БАЛАНСИРОВЩИК НАГРУЗКИ:
Nginx способен равномерно распределять запросы между несколькими серверами, обеспечивая высокую доступность системы даже при больших нагрузках.

— КЭШИРОВНИЕ.
Nginx поддерживает различные виды кэширования, такие как кэширование HTTP-ответов, файлов и медиаконтента. Это помогает снизить нагрузку на основные сервера и ускорить время отклика.

— HTTPS и SSL/TLS.
Nginx поддерживает шифрование трафика через протоколы HTTPS и TLS, что обеспечивает безопасность передачи данных между пользователем и сервером.

— ФАЙЛОВЫЦ СЕРВЕР.
Nginx можно использовать для обслуживания файлов напрямую, например, для загрузки видео или других крупных файлов.

— API GATEWAY.
В некоторых случаях Nginx также применяется как шлюз для API, чтобы управлять маршрутизацией запросов к различным сервисам и приложениям.

— ПОЧТОВЫЦ ПРОКСИ.
Хотя эта функциональность менее популярна, Nginx может использоваться как почтовый прокси для работы с такими протоколами, как IMAP, POP3 и SMTP.

Преимущества использования Nginx:
— Высокая производительность и способность обрабатывать большое количество одновременных соединений.
— Низкое потребление ресурсов (CPU и памяти).
— Гибкость настройки и поддержка различных модулей.
— Простота развертывания и управления конфигурацией.
— Поддержка множества протоколов и технологий.


Примеры использования:

- Высоконагруженные сайты, такие как социальные сети, новостные порталы, интернет-магазины.
- Микросервисная архитектура, где Nginx выступает в роли обратного прокси и балансировщика нагрузки.
- Обеспечение безопасности приложений через поддержку HTTPS и SSL/TLS.
- Кэширование статических файлов и динамического контента для ускорения работы сайта.

Таким образом, Nginx является мощным инструментом для создания высокопроизводительных и надежных веб-приложений, которые могут справляться с большими объемами трафика и обеспечивать высокий уровень доступности.
#78_ADM_DvOp_NTWK

Технические особенности Nginx:

— У nginx есть один главный и несколько рабочих процессов.
Основная задача главного процесса — чтение и проверка конфигурации и управление рабочими процессами.
Рабочие процессы выполняют фактическую обработку запросов.

— Как работают nginx и его модули, определяется в конфигурационном файле.
По умолчанию конфигурационный файл называется nginx.conf.


О настройке конфигурационных файлов Nginx.

— Для настройки конфигурационных файлов Nginx используется специальный синтаксис, разработанный специально для этого веб-сервера.
Этот синтаксис не является полноценным языком программирования, но имеет свои особенности и правила, которые позволяют гибко настраивать работу Nginx.

— Основные элементы конфигурации включают директивы, блоки и комментарии.
Вот краткий обзор ключевых аспектов синтаксиса:

ДИРЕКТИВЫ.
Директива представляет собой команду, которая указывает Nginx, как выполнять определенные действия.

Например:
- LISTEN — задает порт, на котором будет слушать сервер;
- SERVER_NAME — определяет имя домена, которое будет обслуживаться этим блоком.

БЛОКИ.
Блоки представляют собой группы директив, объединённых общей задачей. Они начинаются с ключевых слов, таких как:

http, server, location и т.д.,

и заключаются фигурными скобками { }. Внутри блока могут быть другие директивы и вложенные блоки.

КОММЕНТАРИИ.

Комментарии в файле конфигурации обозначаются символом #. Всё, что идёт после этого символа до конца строки, игнорируется интерпретатором.

Пример простого конфигурационного файла nginx.conf:

worker_processes 1;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;

server {
listen 80;
server_name localhost;

location / {
root html;
index index.html index.htm;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

Этот пример демонстрирует использование основных элементов синтаксиса:
- директив (worker_processes, listen);
- блоков (events, http, server, location);
- комментариев (#).


Таким образом, хотя этот синтаксис и не является отдельным языком программирования, его знание необходимо для эффективной настройки и управления работой Nginx.
#79_ADM_DvOp

DOCKER — это платформа для разработки, доставки и запуска приложений в контейнерах.

Основные понятия:
Докер-образ – «упаковка» для приложения и зависимостей (в том числе системных);
Контейнер – экземпляр образа, то есть «оживший» образ.
Контейнер это новый «исполняемый файл», включающий в себя все необходимые продукту зависимости.
Главное преимущество контейнеризации – изоляция зависимостей и единая простая точка запуска ПО.


Docker – «де-факто» стандарт инструмента контейнеризации в индустрии, но он не является первым или последним среди технологий контейнеризации.
Предшественниками контейнеров Docker были виртуальные машины.
Виртуальная машина, как и контейнер, изолирует приложение и его зависимости от внешней среды.
Однако контейнеры Docker обладают преимуществами перед виртуальными машинами — они потребляют меньше ресурсов, их очень легко переносить, они быстрее запускаются и приходят в работоспособное состояние.
Докер-образ состоит из слоев. Каждый слой описывает какое-то изменение, которое должно быть выполнено с данными на запущенном контейнере.
Структура связей между слоями — иерархическая. Имеется базовый слой, на который «накладываются» остальные слои.
Для создания образа используется Dockerfile — каждая инструкция в нем создает новый слой.
Контейнеры Docker предоставляют лёгкую виртуализацию, позволяя упаковывать приложение со всеми необходимыми зависимостями в изолированную среду, которую затем можно легко переносить и запускать на разных системах без необходимости изменять код или настройки.


Для чего нужен Docker?

Упрощение разработки и тестирования:
Разработчики могут создавать и тестировать приложения в одинаковых условиях независимо от окружения. Это снижает вероятность возникновения проблем совместимости и упрощает процесс разработки.

Изоляция приложений:
Каждый контейнер работает в своём собственном пространстве, что предотвращает конфликты между разными приложениями, запущенными на одной машине.

Переносимость:
Приложение, упакованное в контейнер, можно легко перенести на другую машину или облачную платформу без необходимости заново устанавливать зависимости и конфигурировать окружение.

Масштабируемость:
Docker облегчает масштабирование приложений путём быстрого развёртывания новых экземпляров контейнеров по мере увеличения нагрузки.

Оптимизация ресурсов:
Контейнеры используют меньше ресурсов по сравнению с традиционными виртуальными машинами, так как они делят ядро операционной системы хоста.


Как устроен Docker?

Архитектура Docker состоит из нескольких компонентов:

- Docker Engine — ядро платформы, отвечающее за создание и управление контейнерами. Включает в себя демона Docker (dockerd) и клиентскую часть (docker CLI).

- Клиентская часть (CLI) — инструмент командной строки, позволяющий пользователям взаимодействовать с Docker Engine для выполнения таких операций, как создание, запуск и остановка контейнеров.

- Контейнер — изолированная среда, содержащая всё необходимое для запуска приложения: код, библиотеки, зависимости и настройки.
Контейнеры работают поверх ядра ОС хоста, используя общие ресурсы, но остаются независимыми друг от друга.

- Образы — шаблоны, на основе которых создаются контейнеры.
Образы содержат инструкции о том, какие файлы и команды должны быть включены в контейнер.

- Регистры образов — репозитории, где хранятся образы Docker.
Самый известный регистр — Docker Hub, но можно использовать и частные регистры.


Docker предоставляет мощный инструмент для упаковки, доставки и запуска приложений в любых средах, будь то локальная машина разработчика, сервер в дата-центре или облачная инфраструктура. Его простота и универсальность делают Docker популярным выбором среди разработчиков и системных администраторов во всём мире.
#80_ADM_DvOp

Процесс работы с Docker
.

Создание образа.
Разработчик создаёт файл Dockerfile, описывающий шаги сборки образа. Затем команда docker build собирает образ на основе этого файла.

Запуск контейнера.
После того как образ собран, его можно запустить командой docker run, создав новый контейнер.

Управление контейнерами.
Пользователь может останавливать, перезапускать, удалять и инспектировать контейнеры с помощью команд:
- docker stop;
- docker start;
- docker rm
;
- docker inspect.

Шеринг образов.
Готовые образы можно загружать в реестр образов (например, Docker Hub), откуда их могут скачивать и использовать другие пользователи.


Пример использования Docker.

Допустим, у вас есть веб-приложение на Python, использующее Flask. Чтобы создать контейнер для этого приложения, вы можете следовать следующим шагам:

Создайте файл Dockerfile:
FROM python:3.9
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
EXPOSE 5000
CMD ["python", "./
app.py"]

Соберите образ:
docker build -t my-app .

Запустите контейнер:
docker run -p 8080:5000 my-app

Теперь ваше приложение доступно по адресу localhost:8080.
#81_ADM_DvOp

Инструменты для работы с Docker:

DOCKLE.
Dockle — это инструмент для проверки безопасности образов контейнеров, который можно использовать для поиска уязвимостей.

Основные функции и преимущества Dockle:
- поиск уязвимостей в образах;
- помощь в создании правильного Dockerfile;
- простота в использовании, нужно указать только имя образа;
- поддержка CIS Benchmarks.


DOCKER COMPOSE.
Docker Compose — это инструментальное средство, которое предназначено для решения задач, связанных с развёртыванием проектов.
Docker Compose может пригодиться, если для обеспечения функционирования проекта используется несколько сервисов.
Docker Compose используется для одновременного управления несколькими контейнерами, входящими в состав приложения.
Этот инструмент предлагает те же возможности, что и Docker, но позволяет работать с более сложными распределенными приложениями, например микросервисными.
#82_ADM_BASH

Как убить процесс в Linux зная название приложения?

$ pkill -f "program_name"
#83_ADM_BASH_DvOp

Для проверки какой процесс занимает в настоещее время определенный порт мы можем воспользоваться следующей командой:

$ sudo lsof -i :[port_number]

Например:

$ sudo lsof -i :80

Если вам нужно освободить проверяемый порт, и вам удалось определить процесс которым он был занят, то мы можем сделать это посредством команды:

$ sudo systemctl stop [process_name]

Например если порт был занят процессом nginx, то введем в терминале:

$ sudo systemctl stop nginx

это остановит процесс nginx и освободит порт.
#84_ADM_BASH

EXEC
Команда exec в Bash используется для выполнения команд и управления файловыми дескрипторами. Она имеет несколько ключевых возможностей, которые делают её полезной в различных сценариях работы с оболочкой.

Базовый синтаксис:

$ exec [опции] [команды]

Основные функции и флаги:

- замена текущего процесса другим процессом
Если указать команду после exec, то текущий процесс заменяется новым процессом без создания нового дочернего процесса. Это полезно, если нужно запустить новую программу вместо текущей оболочки.

Пример:

$ exec ls -l

Этот код заменит текущую оболочку командой ls -l, которая выведет список файлов в текущем каталоге. После завершения команды оболочка завершится, потому что она была заменена.

- управление файловыми дескрипторами
Файловые дескрипторы позволяют управлять стандартными потоками ввода-вывода (stdin, stdout, stderr), а также создавать новые потоки.

Основные операции:

<file — перенаправление ввода;
>file — перенаправление вывода;
>>file — добавление вывода к файлу;
<&fd — копирование входного потока из другого дескриптора;
>&fd — копирование выходного потока в другой дескриптор;
<>file — открытие файла для чтения и записи.

Примеры:

$ exec 4> log.txt

открывает файл "log.txt" для записи и привязывает его к дескриптору 4;

$ echo "Запись в лог-файл" >&4

запишем строку в файл через дескриптор 4;

$ exec 4>&-

закроем файловый дескриптор 4.

В этом примере команда exec сначала открывает файл log.txt для записи и привязывает его к дескриптору 4. Затем строка записывается в этот файл, используя перенаправление вывода через дескриптор 4. Наконец, файл закрывается.

- переопределение стандартных потоков ввода-вывода
Можно переопределить стандартные потоки ввода-вывода (stdin, stdout, stderr), например, перенаправив их в файлы или другие процессы.

Пример:

$ exec > output.log

перенаправляем stdout в файл output.log

$ exec 2> error.log

перенаправляем stderr в файл error.log

Теперь все сообщения, которые обычно выводятся на экран, будут записаны в файл output.log, а ошибки — в error.log.

- использование в скриптах
Часто exec используют в конце скриптов, чтобы заменить выполнение самого скрипта на выполнение другой программы. Например, это может быть полезно при написании оберток над другими программами.

Пример:

#!/bin/bash
# Предположим, что скрипт выполняет некоторую подготовку перед запуском приложения
prepare_something

# Теперь запускаем приложение
exec my_application "$@"

Здесь my_application будет запущено вместо продолжения выполнения скрипта. Все аргументы, переданные скрипту, будут переданы приложению.

Когда удобно использовать exec:

- Замена текущей оболочки:
Если вам нужно завершить работу оболочки и передать управление другому процессу.

- Перенаправление ввода-вывода:
Для более гибкого управления стандартными потоками ввода-вывода в скриптах.

- Создание временных файловых дескрипторов:
Для открытия файлов и управления ими внутри скрипта.

- Обёртки для других приложений:
Для запуска программ с определёнными параметрами и аргументами, передавая им контроль над выполнением.


Примеры использования:

Пример 1: Перенаправление ошибок в файл

#!/bin/bash
exec 2> errors.log
some_command_that_might_fail
another_command


Все ошибки, возникающие во время выполнения этих команд, будут записываться в файл errors.log.

Пример 2: Обёрточный скрипт

#!/bin/bash
source some_environment_setup.sh
exec application --with-flags "$@"


Скрипт сначала загружает некоторые настройки окружения, затем запускает приложение application с флагами и переданными аргументами.

Пример 3: Временные файловые дескрипторы

#!/bin/bash
exec 5< input_file.txt
while read -u 5 line; do
echo "Read from file: $line"
done
exec 5>&-


Этот пример открывает файл input_file.txt для чтения и читает строки по одной до конца файла, после чего закрывает файл.
#85_ADM_BASH

Чтобы проверить наличие пакета в системе, зная его имя, можно использовать следующие команды:

$ dpkg -l | grep package_name

Команда

$ dpkg -l

выводит список всех установленных пакетов, а

$ grep package_name


его фильтрует по имени пакета.
#86_DvOp

Dockerfile – это текстовый файл, который содержит набор инструкций для создания образа Docker. Эти инструкции описывают шаги сборки и настройки контейнера, начиная от базового образа до конечного состояния приложения.

Основные команды Dockerfile:

FROM — указывает базовый образ, от которого будет наследоваться текущий контейнер. Это обязательная инструкция, которая должна быть первой в Dockerfile;

LABEL — добавляет метаданные к образу в виде пар "ключ-значение". Полезно для добавления информации о версии, авторе и т.д.;

RUN — выполняет команду во время сборки образа. Каждая команда RUN создает новый слой в образе;

CMD — определяет команду по умолчанию, которую нужно запустить при запуске контейнера. Может быть только одна такая команда в Dockerfile. Если указать несколько команд CMD, то будет выполнена последняя;

ENTRYPOINT — задает исполняемый файл, который будет запущен при старте контейнера. В отличие от CMD, аргументы передаются через CMD;

COPY — копирует файлы или директории из контекста сборки в контейнер;

ADD — похож на COPY, но также может распаковывать архивы и скачивать файлы по URL;

WORKDIR — устанавливает рабочую директорию для последующих команд (RUN, CMD, ENTRYPOINT);

ENV — устанавливает переменные окружения внутри контейнера;

EXPOSE — информирует Docker о том, что контейнер слушает указанный порт;

VOLUME — создает точку монтирования тома для хранения данных вне контейнера;

USER — устанавливает пользователя, под которым будут выполняться последующие команды;

ARG — определяет аргумент, который можно передать во время сборки;

ONBUILD — регистрирует команду, которая будет выполнена при сборке дочернего образа.
#87_C_Cpp_PkS_PPPO_TP

1. В чем заключаются ОСНОВНЫЕ ПРИНЦИПЫ ООП?

Основные принципы ООП:

- ИНКАПСУЛЯЦИЯ — это механизм сокрытия внутренней реализации объекта и предоставления доступа к его данным только через публичные методы.
Инкапсуляция позволяет скрыть детали реализации класса от пользователя, что делает код более гибким и защищенным;

- НАСЛЕДОВАНИЕ — это возможность создания новых классов на основе уже существующих с добавлением или изменением их функциональности.
Наследование позволяет повторно использовать существующий код и строить иерархии классов.

- ПОЛИМОРФИЗМ — это способность объектов разных типов реагировать на одни и те же сообщения по-разному.
Полиморфизм позволяет писать универсальный код, который может работать с объектами различных типов без необходимости знать конкретные типы этих объектов во время компиляции.

- АБСТРАКЦИЯ — это процесс выделения существенных характеристик объекта, которые отличают его от всех других видов объектов, и игнорирование несущественных деталей для упрощения представления этого объекта.
Абстракция помогает сосредоточиться на общих чертах объектов, а не на деталях их реализации.

Эти принципы позволяют создавать программы, которые легче поддерживать, расширять и адаптировать под изменяющиеся требования.
#88_ALG_PkS_TP

Что такое СЛОЖНОСТЬ АЛГОРИТМА?

СЛОЖНОСТЬ АЛГОРИТМА это мера того, насколько эффективно алгоритм использует ресурсы компьютера при решении задачи.

Обычно выделяют два основных вида сложности:

- ВРЕМЕННАЯ СЛОЖНОСТЬэто оценка времени выполнения алгоритма в зависимости от размера входных данных.
Она показывает, как изменяется время работы алгоритма при увеличении количества элементов ввода.
Временную сложность часто выражают с помощью "O-большого" (Big-O notation), которая описывает асимптотическое поведение функции времени выполнения.

Примеры временной сложности:
- O(1) — константное время (алгоритм работает за фиксированное время независимо от размера входа);
- O(logn) — логарифмическое время (например, бинарный поиск);
- O(n) — линейное время (время пропорционально размеру входных данных);
- O(n^2) — квадратичное время (часто встречается у простых сортировок, таких как пузырьковая сортировка).
- O(2^n) — экспоненциальное время (очень медленно растущая функция, характерна для задач перебора).


- ПРОСТРАНСТВЕННАЯ СЛОЖНОСТЬэто оценка объема памяти, необходимого для выполнения алгоритма.
Как и временная сложность, пространственная сложность зависит от размера входных данных.
Пространственную сложность также можно выразить через O-нотацию.

Примеры пространственной сложности:
- O(1) — постоянная память (независимо от размера ввода требуется одно и то же количество памяти);
- O(n) — линейная память (память растет прямо пропорционально количеству элементов ввода);
- O(n^2) — квадратичная память (редко встречающаяся ситуация, когда объем требуемой памяти пропорционален квадрату размера входных данных).

Пример оценки сложности.
Рассмотрим задачу поиска элемента в отсортированном массиве.
Если мы используем простой линейный поиск, где нужно проверить каждый элемент массива до тех пор, пока не найдем нужный, временная сложность будет O(n).
Однако если применить бинарный поиск, который делит массив пополам на каждом шаге, временная сложность снизится до O(logn).

Таким образом,
анализ сложности алгоритмов помогает понять, насколько эффективным является тот или иной подход к решению задачи, особенно при работе с большими объемами данных.
#89_DBG_PkS_TP

Код работает неправильно. Что делать?

Когда код ведет себя неожиданно или выдает ошибки, важно следовать систематическому процессу устранения неполадок.

Вот несколько шагов, которые могут помочь разобраться в проблеме:


- ПРОВЕРКА НАЛИЧИЯ ОШИБОК.
Если код выдает явные ошибки, анализируем сообщения об ошибках. Они обычно содержат информацию о том, какая строка кода вызывает проблему и почему она возникает. Пробуем исправить ошибку, основываясь на этих сообщениях;

- ИСПОЛЬЗОВАНИЕ ОТЛАДЧИКА.
Отладчики позволяют пошагово выполнять программу, наблюдая за значениями переменных и состоянием программы на каждом этапе.
Отладчик - это отличный инструмент, помогающий найти место, где программа начинает вести себя не так, как ожидалось;

- ДОБАВЛЕНИЕ ВЫВОДА ПРОМЕЖУТОЧНЫХ ЗНАЧЕНИЙ.
Иногда полезно вывести значения ключевых переменных в процессе выполнения программы. Это помогает увидеть, какие данные обрабатываются и где происходит сбой. Например, можно добавить printf() в C или std::cout в C++;

- ПРОВЕРКА КОРРЕКТНОСТИ ВХОДНЫХ ДАННЫХ.
Проверка правильности ввода данных в программу. Возможно, проблема кроется в неверном формате или типах данных, которые поступают на вход;

- ДЕКОМПОЗИЦИЯ ЗАДАЧИ.
Если программа состоит из нескольких сложных частей, разобьём её на небольшие модули и протестируем каждый модуль отдельно. Так можно локализовать источник проблемы;

- ПОИСК ПОХОЖИХ РЕШЕНИЙ.
Возможно, кто-то уже сталкивался с подобной проблемой. Ищем ответы на форумах разработчиков, таких как Stack Overflow, или смотрим документацию и примеры использования библиотек, которые используем;

- ПРОВЕДЕНИЕ РЕФАКТОРИНГА.
Иногда проблема может быть связана со сложностью или запутанностью кода.
Пробуем упростить и переписать проблемные участки, сделав их понятнее.
Рефакторинг может улучшить читаемость и выявить скрытые ошибки;

- НАПИСАНИЕ UNIT-тестов.
Чтобы убедиться, что код корректно обрабатывает различные варианты входных данных.
Например, граничные случаи — пустые списки, нулевые значения, большие числа и т.д. Часто именно эти ситуации вызывают неожиданное поведение;

- ПЕРЕРЫВ - ПЕРЕКЛЮЧЕНИЕ НА ДРУГУЮ ЗАДАЧУ.
Если ничего не помогает, иногда стоит сделать паузу и отвлечься. Свежий взгляд после перерыва может помочь заметить то, что раньше ускользало.
#90_ALG_PkS_TP

Объясните такие структуры данных, как СТЕК и ОЧЕРЕДЬ?

СТЕК и ОЧЕРЕДЬэто две фундаментальные структуры данных, используемые в программировании для хранения и обработки данных.
Каждая из них имеет свои особенности и правила добавления/удаления элементов.


СТЕК (STACK)это структура данных, работающая по принципу LIFO ("Last In, First Out", последний вошел — первый вышел)
Это означает, что элемент, добавленный последним, будет удален первым.

Примеры использования стека:
- обработка вложенности (например, обработка скобок в математических выражениях);
- управление возвратом в программах (например, вызов функций и возврат из них);
- реализация обратного порядка действий (например, отмена последних изменений в текстовом редакторе).


ОЧЕРЕДЬ (QUEUE)это структура данных, работающая по принципу FIFO ("First In, First Out", первый вошел — первый вышел).
Это означает, что элемент, добавленный первым, будет удален первым.

Примеры использования очередей:
- планирование задач (например, выполнение заданий в порядке поступления);
- организация процессов (например, управление потоками клиентов в банке);
- сетевое взаимодействие (например, буферизация пакетов данных).

СТЕКИ и ОЧЕРЕДИ являются важными инструментами в арсенале программиста. Выбор между ними зависит от конкретной задачи и требований к порядку обработки данных.
#90p2_ALG_Cpp_PkS_TP

В C++ работа со СТЕКОМ и ОЧЕРЕДЬЮ осуществляется с использованием стандартных контейнеров библиотеки STL (<stack> и <queue> соответственно).

Основные операции для работы со СТЕКОМ:
Для работы со стеком используется класс std::stack, который предоставляет следующие основные операции:

- конструкторсоздание нового стека;
std::stack<int> my_stack;

- pushдобавляет элемент в вершину стека;
my_stack.push(10);

- popудаляет верхний элемент из стека;
my_stack.pop();

- topвозвращает ссылку на верхний элемент стека (не удаляя его);
int top_element = my_stack.top();

- emptyпроверяет, пуст ли стек;
bool is_empty = my_stack.empty();

- sizeвозвращает количество элементов в стеке;
size_t stack_size = my_stack.size();

Пример использования стека:

#include <iostream>
#include <stack>

int main() {
// Создаем стек

std::stack<int> my_stack;

// Проверяем, пуст ли стек
if (my_stack.empty()) {
std::cout << "Стек пуст." << std::endl;
}

// Добавляем элементы в стек
my_stack.push(10);
my_stack.push(20);
my_stack.push(30);

// Выводим размер стека
std::cout << "Размер стека: " << my_stack.size() << std::endl;

// Получаем доступ к верхнему элементу
int top_element = my_stack.top();
std::cout << "Верхний элемент: " << top_element << std::endl;

// Удаляем верхний элемент
my_stack.pop();

// Выводим размер стека после удаления
std::cout << "Размер стека после удаления: " << my_stack.size() << std::endl;

return 0;
}

Основные операции для работы с ОЧЕРЕДЬЮ:
Для работы с очередью используется класс std::queue, который предоставляет следующие основные операции:

- конструктор создание новой очереди;
std::queue<int> my_queue;

- push добавляет элемент в конец очереди;
my_queue.push(10);

- pop удаляет элемент из начала очереди;
my_queue.pop();

- frontвозвращает ссылку на первый элемент очереди (не удаляя его);
int front_element = my_queue.front();

- back — возвращает ссылку на последний элемент очереди (не удаляя его);
int back_element = my_queue.back();

- empty — проверяет, пуста ли очередь;
bool is_empty = my_queue.empty();

- size — возвращает количество элементов в очереди;
size_t queue_size = my_queue.size();

Пример использования очереди:


#include <iostream>
#include <queue>

int main() {
// Создаем очередь
std::queue<int> my_queue;

// Проверяем, пуста ли очередь
if (my_queue.empty()) {
std::cout << "Очередь пуста." << std::endl;
}

// Добавляем элементы в очередь
my_queue.push(10);
my_queue.push(20);
my_queue.push(30);

// Выводим размер очереди
std::cout << "Размер очереди: " << my_queue.size() << std::endl;

// Получаем доступ к первому элементу
int front_element = my_queue.front();
std::cout << "Первый элемент: " << front_element << std::endl;

// Удаляем первый элемент
my_queue.pop();

// Выводим размер очереди после удаления
std::cout << "Размер очереди после удаления: " << my_queue.size() << std::endl;

return 0;
}

Эти структуры данных широко используются в различных приложениях, включая обработку событий, планирование задач и многое другое.
#91_Cpp_PkS

Что нового в стандартах С++17, С++20?

C++17 и C++20 привнесли множество улучшений и нововведений в язык программирования C++, делая его еще более мощным и удобным для разработки.
Давайте рассмотрим ключевые изменения и новые возможности, появившиеся в этих версиях стандарта.

C++17:

Structured Bindings: Позволяют легко распаковывать кортежи и структуры в отдельные переменные:

auto [a, b, c] = std::make_tuple(1, 2, 3);

Inline Variables: Теперь можно определять статические члены внутри класса:

struct MyClass {
static inline int x = 42;
};

Fold Expressions: Упрощает работу с вариативными шаблонами:

template<typename... Args>
void print_all(const Args&... args) {
(std::cout << ... << args) << '\n';
}

if constexpr: Улучшает условную компиляцию в шаблонах:

template<typename T>
void foo(T t) {
if constexpr (std::is_integral_v<T>) {
std::cout << "Integral type\n";
} else {
std::cout << "Non-integral type\n";
}
}

std::optional: Новый тип для опциональных значений:

std::optional<int> maybe_int = 42;
if (maybe_int.has_value()) {
std::cout << *maybe_int << '\n';
}

std::variant: Тип для безопасного хранения одного из нескольких возможных типов:

std::variant<int, float> v = 12;
std::visit([](auto&& arg) { std::cout << arg; }, v);

std::string_view: Легковесный вид строки, позволяющий избежать копирования:

std::string s = "Hello, world!";
std::string_view sv(s);
std::cout << sv << '\n';

Guaranteed copy elision: Гарантирует отсутствие ненужных копий при создании объектов:

Foo f = Foo{}; // Теперь гарантированно нет временных объектов


C++20:

Concepts: Концепты позволяют накладывать ограничения на параметры шаблонов:

template<typename T>
concept Integral = std::is_integral_v<T>;

template<Integral T>
void do_something(T value) {
// Код, зависящий от типа T
}

Ranges Library: Новая библиотека для работы с диапазонами:

std::vector<int> vec{1, 2, 3, 4, 5};
for (int i : vec | std::views::filter([](int x) { return x % 2 == 0; }))
std::cout << i << ' ';

Modules: Модули заменяют заголовочные файлы и устраняют необходимость включения:

export module my_module;
export int add(int a, int b) { return a + b; }

Coroutines: Поддержка корутин для написания асинхронного кода:

generator<int> count(int start = 0) {
while (true) co_yield start++;
}

Spaceship Operator (<=>): Определяет отношения между двумя объектами:

struct Point {
int x, y;
auto operator<=>(const Point&) const = default;
};

Designated Initializers: Инициализаторы с указанием имен полей:

struct S { int x; int y; };
S s{.x = 1, .y = 2}; // Теперь можно инициализировать поля по имени

Constexpr Improvements: Еще больше возможностей для вычислений на этапе компиляции:

constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}

std::span: Представляет непрерывный диапазон элементов:

std::array<int, 5> arr{1, 2, 3, 4, 5};
std::span<int> span(arr);
for (int i : span) std::cout << i << ' ';

Эти нововведения делают C++ более выразительным, безопасным и удобным языком для разработки современных приложений.
#92_Cpp_PkS

C++ прошел долгий путь развития, начиная с первых стандартов и заканчивая современными версиями.
Ниже представлен обзор основных стандартов C++ в хронологическом порядке, с краткими описаниями ключевых нововведений каждого из них.

1983: C with Classes первоначальная версия языка, разработанная Бьярном Страуструпом, была известна как "C with Classes".
Этот прототип включал базовые концепции классов, наследования и виртуальных функций.


1998: C++98 (ISO/IEC 14882:1998)первый официальный стандарт C++ был опубликован ISO в 1998 году. Он включает:
Стандартную библиотеку шаблонов (STL): коллекции, алгоритмы, итераторы.
Исключения.
Ручной менеджмент памяти с помощью new и delete.
Шаблоны.
Пространства имен.



2003: C++03 (ISO/IEC 14882:2003)обновление стандарта 1998 года, которое внесло незначительные исправления и уточнения.


2011: C++11 (ISO/IEC 14882:2011) — этот стандарт принес значительные улучшения и нововведения:
auto — автоматический вывод типов;
— nullptr — безопасный указатель на ноль;
— лямбда-функции;
— правило RVO (Return Value Optimization);
— constexpr — вычисления на этапе компиляции;
— умные указатели (unique_ptr, shared_ptr);
— переменное число аргументов (variadic templates);
— диапазоны (range-based for loop);
— правило перемещения (move semantics);
— ключевое слово override;
— атрибуты (attributes).


2014: C++14 (ISO/IEC 14882:2014) —улучшения и дополнения к C++11:
— более гибкий auto и лямбды;
— усовершенствования constexpr;
— динамические исключения (binary search, lower_bound, upper_bound);
— функциональный шаблон make_unique;
— универсальный инициализатор (unified initialization syntax).


2017: C++17 (ISO/IEC 14882:2017) — ещё одна значительная версия с множеством нововведений:
— structured bindings — распаковка кортежей и структур;
— inline variables — определение статических членов внутри класса;
— fold expressions — работа с вариативными шаблонами;
— if constexpr — условная компиляция в шаблонах;
— std::optional — опциональные значения;
— std::variant — хранение одного из нескольких возможных типов;
— std::string_view — легковесный вид строки;
— guaranteed copy elision — отсутствие ненужных копий при создании объектов.


2020: C++20 (ISO/IEC 14882:2020) — самая современная версия стандарта на момент написания:
— concepts — ограничения на параметры шаблонов;
— ranges library — работа с диапазонами;
— modules — замена заголовочных файлов;
— coroutines — асинхронный код;
— spaceship operator (<=>) — определение отношений между объектами;
— designated initializers — инициализация полей по имени;
— constexpr improvements — больше возможностей для вычислений на этапе компиляции;
— std::span — непрерывный диапазон элементов.
#92p2_CPP_PkS

Стандарт C++23 находится в стадии разработки, и окончательный список нововведений ещё не утверждён.
Тем не менее, некоторые предложения уже приняты комитетом по стандартизации, и они, вероятно, войдут в финальную версию стандарта.

Вот некоторые из наиболее ожидаемых нововведений:

— удаление некоторых устаревших особенностей — некоторые старые и редко используемые функции будут удалены из стандарта. Например, планируется убрать поддержку volatile для типов, не относящихся к аппаратуре (hardware-specific types);

— улучшение поддержки UTF-8предложение по улучшению поддержки UTF-8 в стандартной библиотеке, включая новую функцию u8string_view и другие связанные утилиты;

— дополнительные функции для работы с датами и временем — планируется расширение библиотеки chrono новыми функциями и возможностями, такими как поддержка часов, учитывающих летнее время (daylight saving time);

— модульные тестыдобавление поддержки модульных тестов непосредственно в стандартную библиотеку. Это позволит разработчикам легко интегрировать тестирование в свои проекты;

— исправления и улучшения концепцийдальнейшие усовершенствования системы концептов, введённых в C++20, чтобы сделать её более удобной и эффективной;

— интеграция зависимых типов в концепциирасширение возможностей концептов для работы с зависимыми типами, что упростит написание обобщённого кода;

— поддержка SIMD (Single Instruction, Multiple Data) — возможное введение средств для работы с векторизацией инструкций (SIMD), что позволит эффективнее использовать современные процессоры;

— шаблонные метапрограммы -- улучшенная поддержка метапрограммирования с использованием шаблонов, что сделает этот аспект языка более мощным и удобным;

— именованные аргументы — поддержка именованных аргументов при вызове функций, что повысит читаемость и удобство использования кода;

— функции проверки безопасности памятиновые средства для проверки безопасности работы с памятью, включая инструменты для обнаружения утечек памяти и предотвращения использования неинициализированных переменных;

— упрощённое использование std::format — дальнейшее развитие и улучшение функционала форматирования строк, представленного в C++20;

— атомарные целочисленные типы — добавление атомарных целочисленных типов, что улучшит поддержку многопоточного программирования;

— импорт модулей из заголовочных файловновая возможность импорта модулей из традиционных заголовочных файлов, что облегчит переход на систему модулей.

Эти нововведения направлены на дальнейшее совершенствование языка C++ и повышение удобства его использования в современном программировании.
Окончательная версия стандарта ожидается в ближайшие годы, и она может включать дополнительные изменения и улучшения.

Каждый новый стандарт добавляет важные функции и улучшает существующие, делая C++ все более мощным и удобным инструментом для разработки программного обеспечения.
#93_PkS_TP

ASCII (American Standard Code for Information Interchange) — это кодировка символов, которая определяет соответствие между числами (кодами) и символами.

ASCII таблица содержит 128 символов, пронумерованных от 0 до 127.
Эти символы включают буквы латинского алфавита, цифры, знаки препинания, управляющие символы и некоторые специальные символы.

Вот пример структуры ASCII таблицы:

%d %X char
====================
0 00 NUL
1 01 SOH
2 02 STX
... ... ...
32 20 Пробел
33 21 !
34 22 "
... ... ...
65 41 A
66 42 B
67 43 C
... ... ...
97 61 a
98 62 b
99 63 c
... ... ...
126 7E ~
127 7F DEL

Первые 32 символа (коды 0–31) представляют собой управляющие символы, которые не отображаются на экране и предназначены для управления устройствами и передачей данных.
Остальные символы (с коды 32–127) включают печатаемые символы, такие как буквы, цифры и знаки пунктуации.

ASCII таблица стала основой для многих последующих кодировок, таких как Unicode, но сама по себе она ограничена и поддерживает только латинские символы.
Для поддержки символов других языков были разработаны расширения ASCII, такие как ISO 8859 и Unicode.
#94_PkS_PPPO_TP

Что такое UNICODE?

Unicode — это стандарт кодирования символов, который позволяет представлять текстовые данные на различных языках и платформах с использованием единого набора символов.
Он был создан для решения проблемы, связанной с различными наборами символов (кодировками), которые использовались до его появления.

До Unicode существовали различные национальные стандарты кодировок, такие как ASCII для английского языка, KOI8-R для русского и другие.
Эти кодировки были ограничены по количеству поддерживаемых символов и не могли одновременно поддерживать символы разных языков, что создавало сложности при обмене данными между системами, использующими разные кодировки.

Unicode решает эту проблему, предоставляя единый набор символов, включающий практически все письменные системы мира, а также множество специальных символов, таких как математические знаки, эмодзи и т.д. Каждый символ в Unicode имеет уникальный числовой идентификатор, называемый кодовой точкой (code point).

Основные особенности Unicode:

— УНИВЕРСАЛЬНОСТЬ — поддержка более 140 тысяч символов, охватывающих большинство современных и древних письменных систем;

— ПЛАТФОРМОНЕЗАВИСИМОСТЬ — символы могут быть представлены одинаково на любой платформе, будь то Windows, macOS, Linux или мобильные устройства;

— РАСШИРЯЕМОСТЬ — стандарт постоянно обновляется, добавляются новые символы и языки;

— КОДИРОВКА — в отличие от старых стандартов, где каждый символ занимал фиксированное количество байт, Unicode поддерживает несколько схем кодирования, таких как UTF-8, UTF-16 и UTF-32, что позволяет эффективно хранить и передавать данные.

Примеры использования Unicode:
- веб-сайты, работающие с многоязычным контентом;
- программное обеспечение, которое должно работать с разными языками;
- мобильные приложения, поддерживающие эмодзи и специальные символы.

Таким образом, Unicode является важным инструментом для обеспечения совместимости и удобства работы с текстовыми данными в современном мире.