Сегодня реализуем алгоритм сжатия строк с помощью RLE (Run-Length Encoding), а также восстановление строки из сжатого представления.
В этой задаче:
• Считаем длину последовательностей одинаковых символов и сразу добавляем в результат
• При распаковке парсим число и столько раз добавляем следующий символ.
• Проверяем корректность: сжимаем → распаковываем → сравниваем строки.
Такой приём особенно полезен для логов, графики и повторяющихся данных, где он экономит место.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍4❤3
Быстро тестируем код через assert.
Сейчас научимся добавлять простые проверки прямо в код, чтобы убедиться, что функции работают правильно. Это особенно удобно на этапе отладки и для мини-тестов без фреймворков.
Подключим нужную библиотеку:
Предположим, у нас есть функция, которая должна возвращать квадрат числа. Реализуем её так:
Теперь напишем несколько простых тестов с помощью assert, чтобы проверить, что функция работает правильно на базовых примерах:
Если проверка не пройдёт — программа остановится и покажет, где ошибка.
Вот как может выглядеть ошибка, если ожидание не совпадает с результатом:
🔥 Таким образом ты можешь быстро проверять поведение функций — без сторонних библиотек и с минимальным кодом.
📣 C++ Ready | #практика
Сейчас научимся добавлять простые проверки прямо в код, чтобы убедиться, что функции работают правильно. Это особенно удобно на этапе отладки и для мини-тестов без фреймворков.
Подключим нужную библиотеку:
#include <cassert>
#include <iostream>
Предположим, у нас есть функция, которая должна возвращать квадрат числа. Реализуем её так:
int square(int x) {
return x * x;
}Теперь напишем несколько простых тестов с помощью assert, чтобы проверить, что функция работает правильно на базовых примерах:
int main() {
assert(square(2) == 4);
assert(square(-3) == 9);
assert(square(0) == 0);
std::cout << "Все тесты пройдены!\n";
return 0;
}Если проверка не пройдёт — программа остановится и покажет, где ошибка.
Вот как может выглядеть ошибка, если ожидание не совпадает с результатом:
Assertion failed: square(2) == 5, file main.cpp, line 10
🔥 Таким образом ты можешь быстро проверять поведение функций — без сторонних библиотек и с минимальным кодом.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17👍5❤3
В этой статье:
• Как формируется изображение через плоскость проекции, камеру и направление лучей• Почему пиксели можно представить как результат пересечения лучей со сценой• Базовая логика, с которой начинается построение собственного трассировщика лучей🔊 Продолжай читать на habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍6🔥4
Почему std::async иногда не делает код асинхронным?
На первый взгляд кажется, что задача просто запускается в фоне, а выполнение сразу идет дальше. Но у
Если этот
В итоге код выглядит как fire-and-forget, но на деле поток может заблокироваться уже на этой строке. То есть вместо фоновой работы ты случайно получаешь скрытую синхронизацию.
Из-за этого баг особенно неприятный: внешне все выглядит асинхронно, а по факту приложение тормозит в месте, где ты вообще не ждешь блокировки.
Если результат нужен позже,
А если тебе реально нужен отдельный поток жизни задачи, лучше использовать более явные инструменты, а не полагаться на такой неочевидный сценарий.
🔥 Не потеряй
📣 C++ Ready | #совет
На первый взгляд кажется, что задача просто запускается в фоне, а выполнение сразу идет дальше. Но у
std::async есть важная деталь: он возвращает std::future.Если этот
future не сохранить, он будет уничтожен в конце выражения. А для задачи, запущенной с std::launch::async, это может означать ожидание завершения прямо в деструкторе.В итоге код выглядит как fire-and-forget, но на деле поток может заблокироваться уже на этой строке. То есть вместо фоновой работы ты случайно получаешь скрытую синхронизацию.
Из-за этого баг особенно неприятный: внешне все выглядит асинхронно, а по факту приложение тормозит в месте, где ты вообще не ждешь блокировки.
Если результат нужен позже,
future надо сохранить и явно решить, когда именно его ждать.auto fut = std::async(std::launch::async, [] {
reindex();
});
std::cout << "after async\n";А если тебе реально нужен отдельный поток жизни задачи, лучше использовать более явные инструменты, а не полагаться на такой неочевидный сценарий.
future от std::async. Иначе “запустил в фоне” легко превращается в “случайно дождался здесь же”.Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥7❤5
constexpr-парсинг enum в C++: без простыни из if-else
Строки из конфига, CLI и env-переменных почти всегда нужно переводить в enum. И очень быстро код зарастает однотипными ветками
Намного удобнее держать все соответствия в одной таблице. Тогда из неё можно сделать и парсинг строки в enum, и обратное преобразование enum в строку.
Сначала объявим сам enum:
Теперь добавим таблицу соответствий. Все значения лежат в одном месте, и это сразу упрощает поддержку.
После этого можно написать
Если строка неизвестна, вернём пустой результат. Это безопаснее, чем молча подставлять какое-то значение по умолчанию.
Из той же таблицы легко сделать обратное преобразование. Это удобно, когда нужно писать enum в логах, сообщениях об ошибках или конфиге.
Если значение не найдено, вернём запасной вариант.
Использование получается простым и читаемым:
Один mapping в одном месте убирает дублирование, сокращает код и делает добавление новых enum-значений намного спокойнее.
🔥 Один mapping лучше десятка
📣 C++ Ready | #практика
Строки из конфига, CLI и env-переменных почти всегда нужно переводить в enum. И очень быстро код зарастает однотипными ветками
if (s == "...").Намного удобнее держать все соответствия в одной таблице. Тогда из неё можно сделать и парсинг строки в enum, и обратное преобразование enum в строку.
Сначала объявим сам enum:
enum class log_level {
trace,
debug,
info,
error
};Теперь добавим таблицу соответствий. Все значения лежат в одном месте, и это сразу упрощает поддержку.
using namespace std::literals;
constexpr std::array mappings{
std::pair{"trace"sv, log_level::trace},
std::pair{"debug"sv, log_level::debug},
std::pair{"info"sv, log_level::info},
std::pair{"error"sv, log_level::error},
};
После этого можно написать
constexpr-парсер. Он просто проходит по таблице и ищет совпадение.constexpr std::optional<log_level>
parse_log_level(std::string_view s) {
for (auto [name, value] : mappings) {
if (name == s)
return value;
}
Если строка неизвестна, вернём пустой результат. Это безопаснее, чем молча подставлять какое-то значение по умолчанию.
return std::nullopt;
}
Из той же таблицы легко сделать обратное преобразование. Это удобно, когда нужно писать enum в логах, сообщениях об ошибках или конфиге.
constexpr std::string_view
to_string(log_level lvl) {
for (auto [name, value] : mappings) {
if (value == lvl)
return name;
}
Если значение не найдено, вернём запасной вариант.
return "unknown";
}
Использование получается простым и читаемым:
auto lvl = parse_log_level("debug")
.value_or(log_level::info);
std::cout << to_string(lvl) << '\n';Один mapping в одном месте убирает дублирование, сокращает код и делает добавление новых enum-значений намного спокойнее.
if-else веток.Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍6🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
Это сайт, где собраны ресурсы для изучения разных языков программирования, включая отдельные подборки по C++ и C#. Позволяет быстро найти платформы, курсы и учебные материалы. По C++ и C#: курсы, видео, полноценные учебные порталы, туториалы и гайды. Можно выбрать подходящий ресурс и начать обучение без долгого поиска.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13🔥9👍8
С ним можно легко создавать объекты на куче, работать с сырыми указателями без передачи владения, освобождать или менять ресурс, обмениваться им за константное время, а также получать доступ к данным через * и ->Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21🤝13❤4👍4
This media is not supported in your browser
VIEW IN TELEGRAM
Здесь вы найдёте глубокие статьи, практические советы и техники, помогающие лучше использовать возможности языка, улучшать читаемость кода и развивать архитектурное мышление.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍5🔥2
Убираем все пробелы из строки!
Сейчас научимся быстро удалять все пробельные символы (
Сначала подключим необходимые библиотеки из стандартной поставки:
Допустим, у нас есть строка с лишними пробелами и табуляцией:
Теперь удалим все пробельные символы с помощью одного вызова:
Результат при запуске программы:
🔥 Таким образом ты можешь быстро очищать строки от пробелов — без циклов, копий и лишнего кода.
📣 C++ Ready | #практика
Сейчас научимся быстро удалять все пробельные символы (
пробел, таб, перевод строки) из строки. Это пригодится при парсинге ввода, чтении конфигов или очистке текстовых данных.Сначала подключим необходимые библиотеки из стандартной поставки:
#include <string>
#include <algorithm> // std::erase_if (C++20)
#include <cctype> // std::isspace
Допустим, у нас есть строка с лишними пробелами и табуляцией:
std::string raw = " Hello\tWorld \n ";
Теперь удалим все пробельные символы с помощью одного вызова:
std::erase_if(raw, [](unsigned char c) {
return std::isspace(c);
});
std::cout << raw << '\n';Результат при запуске программы:
HelloWorld
🔥 Таким образом ты можешь быстро очищать строки от пробелов — без циклов, копий и лишнего кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍6❤3
Почему захват [this] в асинхронном коде опасен?
Многие воспринимают
Если задача выполнится уже после уничтожения
Проблема в том, что код выглядит абсолютно нормально. Пока объект жив, все работает. Но как только lifetime объекта и lifetime задачи расходятся, появляется use-after-free.
Например, опасный сценарий выглядит так:
Еще хуже, когда внутри лямбды идет доступ к полям объекта:
Если объект должен пережить асинхронный вызов, его временем жизни нужно управлять явно. Обычно для этого используют
Такой код сначала проверяет, жив ли объект вообще, и только потом вызывает метод.
Иногда используют и более прямой вариант с
🔥 Захват
📣 C++ Ready | #совет
Многие воспринимают
[this] как безопасный способ вызвать метод объекта позже. Но на самом деле лямбда сохраняет только указатель this. Она не продлевает время жизни объекта.Если задача выполнится уже после уничтожения
Session, лямбда попробует обратиться к несуществующему объекту. В лучшем случае это закончится падением, в худшем — редким и трудноуловимым UB.Проблема в том, что код выглядит абсолютно нормально. Пока объект жив, все работает. Но как только lifetime объекта и lifetime задачи расходятся, появляется use-after-free.
Например, опасный сценарий выглядит так:
void run(ThreadPool& pool) {
Session s;
s.start(pool);
} // s уже уничтожен, а задача может выполниться позжеЕще хуже, когда внутри лямбды идет доступ к полям объекта:
class Session {
std::string buffer;
public:
void start(ThreadPool& pool) {
pool.post([this] {
std::cout << buffer << "\n"; // доступ к уже мертвому объекту
});
}
};Если объект должен пережить асинхронный вызов, его временем жизни нужно управлять явно. Обычно для этого используют
shared_ptr и weak_ptr.class Session : public std::enable_shared_from_this<Session> {
public:
void start(ThreadPool& pool) {
auto weak = weak_from_this();
pool.post([weak] {
if (auto self = weak.lock()) {
self->flush();
}
});
}
void flush();
};Такой код сначала проверяет, жив ли объект вообще, и только потом вызывает метод.
Иногда используют и более прямой вариант с
shared_from_this(), когда задаче нужно гарантированно удерживать объект живым до конца выполнения:void start(ThreadPool& pool) {
auto self = shared_from_this();
pool.post([self] {
self->flush();
});
}[this] не делает асинхронный код безопасным. Если время жизни объекта не контролируется, это прямой путь к use-after-free.Please open Telegram to view this post
VIEW IN TELEGRAM
❤14🔥7🤝5👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Проект постоянно обновляется сообществом и уже включает тысячи книг, курсов и обучающих ресурсов на разных языках, включая русский . Всё удобно разбито по категориям, отдельные разделы посвящены C++, C#, поэтому можно быстро найти нужную тему и начать изучение. Отлично подходит как база для самообучения.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤9🔥9