C/C++ Ready | Программирование
14.5K subscribers
1.32K photos
83 videos
626 links
Авторский канал по разработке на C и C++.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!

Автор: @energy_it

РКН: https://clck.ru/3QREHc

Реклама на бирже: https://telega.in/c/cpp_ready
Download Telegram
👩‍💻 Сжимаем и восстанавливаем строки с помощью RLE (Run-Length Encoding)

Сегодня реализуем алгоритм сжатия строк с помощью RLE (Run-Length Encoding), а также восстановление строки из сжатого представления.

В этой задаче:

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

При распаковке парсим число и столько раз добавляем следующий символ.

Проверяем корректность: сжимаем → распаковываем → сравниваем строки.


Такой приём особенно полезен для логов, графики и повторяющихся данных, где он экономит место.

📣 C++ Ready | #задача
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍43
Быстро тестируем код через assert.

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

Подключим нужную библиотеку:
#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


🔥 Таким образом ты можешь быстро проверять поведение функций — без сторонних библиотек и с минимальным кодом.

📣 C++ Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17👍53
☕️ Сильная статья — понятный вход в ray tracing через базовую геометрию, лучи и построение изображения.

В этой статье:

• Как формируется изображение через плоскость проекции, камеру и направление лучей
• Почему пиксели можно представить как результат пересечения лучей со сценой
• Базовая логика, с которой начинается построение собственного трассировщика лучей

🔊 Продолжай читать на habr!


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍6🔥4
Почему std::async иногда не делает код асинхронным?

На первый взгляд кажется, что задача просто запускается в фоне, а выполнение сразу идет дальше. Но у 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. Иначе “запустил в фоне” легко превращается в “случайно дождался здесь же”.

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥75
📂 Напоминалка для работы с Big O Notation!

Например, O(1) — выполняется за постоянное время, а O(n) растёт линейно от размера входных данных.

На картинке — основные виды сложности, которые чаще всего встречаются в алгоритмах и структурах данных.

Сохрани, чтобы не забыть!

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
20👍9🔥6
constexpr-парсинг enum в C++: без простыни из if-else

Строки из конфига, 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-значений намного спокойнее.

🔥 Один mapping лучше десятка if-else веток.

📣 C++ Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
14👍6🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
☕️ Fruntend — подборка лучших ресурсов для изучения языков!

Это сайт, где собраны ресурсы для изучения разных языков программирования, включая отдельные подборки по C++ и C#. Позволяет быстро найти платформы, курсы и учебные материалы. По C++ и C#: курсы, видео, полноценные учебные порталы, туториалы и гайды. Можно выбрать подходящий ресурс и начать обучение без долгого поиска.

📌 Оставляю ссылочку: fruntend.com

📣 C++ Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
13🔥9👍8
👩‍💻 Разберём unique_ptr — умный указатель для безопасного и автоматического управления ресурсами!

С ним можно легко создавать объекты на куче, работать с сырыми указателями без передачи владения, освобождать или менять ресурс, обмениваться им за константное время, а также получать доступ к данным через * и ->

📣 C++ Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21🤝134👍4
This media is not supported in your browser
VIEW IN TELEGRAM
😎 Fluent Cpp — сайт, который поможет писать код на C++ понятным, лаконичным и профессиональным!

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

📌 Оставляю ссылочку: fluentcpp.com

📣 C++ Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍5🔥2
Убираем все пробелы из строки!

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

Сначала подключим необходимые библиотеки из стандартной поставки:
#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


🔥 Таким образом ты можешь быстро очищать строки от пробелов — без циклов, копий и лишнего кода.

📣 C++ Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍63
📂 Напоминалка по архитектуре систем!

Например, Load Balancing распределяет нагрузку между серверами, а Caching помогает ускорить ответы за счёт хранения данных в памяти.

На картинке — 12 основных концепций, которые должен понимать каждый разработчик.

Сохрани, чтобы не потерять!

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1610👍9
Почему захват [this] в асинхронном коде опасен?

Многие воспринимают [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.

📣 C++ Ready | #совет
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
👍 Free Programming Books — библиотека ресурсов по программированию на различных языках!

Проект постоянно обновляется сообществом и уже включает тысячи книг, курсов и обучающих ресурсов на разных языках, включая русский . Всё удобно разбито по категориям, отдельные разделы посвящены C++, C#, поэтому можно быстро найти нужную тему и начать изучение. Отлично подходит как база для самообучения.

Оставляю ссылочку: GitHub 📱


📣 C++ Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
👍159🔥9
📂 Напоминалка по системам хранения данных!

Например, CPU cache и RAM дают минимальную задержку и используются для быстрых вычислений, а cloud storage и базы данных — для долговременного хранения и масштабирования.

На картинке — основные типы storage, которые используются в современных системах: от памяти процессора до облачных решений.

Сохрани, чтобы не потерять!

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍168🤝8👎1
Почему emplace_back() не всегда лучше push_back()?

Есть популярное заблуждение, что emplace_back() всегда быстрее. Но это не так.

push_back() добавляет в контейнер уже готовый объект.
emplace_back() конструирует объект прямо на месте из переданных аргументов.

Например:
v.emplace_back("world");


здесь строка создается сразу внутри vector, и это действительно удобно.

Но если объект у тебя уже есть:
std::string s = "hello";
v.push_back(s);


то замена на
v.emplace_back(s);


обычно не дает никакого особого выигрыша. По смыслу это почти то же самое.

emplace_back() полезен, когда ты передаешь аргументы конструктора.
push_back() — когда у тебя уже есть готовое значение.

🔥 emplace_back() — не универсально лучший вариант. Используй его там, где нужен именно in-place construction.

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
18👍7🔥3
This media is not supported in your browser
VIEW IN TELEGRAM
✍️ CyberForum — крупнейшее сообщество разработчиков с разделами по C++ и C#!

Форум, где можно обсуждать задачи, получать помощь и разбирать кейсы из разработки. Есть активные разделы по C++ и C#: обсуждение синтаксиса, разбор ошибок, советы по обучению и практическая помощь. Форум можно использовать как источник знаний, особенно когда требуется разобраться в конкретной задаче или посмотреть, как её решают другие разработчик.

📌 Оставляю ссылочку: cyberforum.ru

📣 C++ Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
20👍9🔥8