Программа показывает последовательность цифр по одной, быстро стирает экран и просит ввести всё в том же порядке, превращая обычный запуск в маленький тренажёр внимания.
В этой задаче узнаешь:
• Как генерировать случайную последовательность и хранить её в std::vector;
• Как паузы через std::chrono и sleep_for создают “напряжение” и делают игру честной;
• Как быстро проверить результат, сравнивая ответы по позициям.
Пара простых циклов — и у тебя готова игра, которую легко прокачать уровнями: после победы увеличивать длину и собирать свой личный рекорд.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥24❤5👍4😁1🤝1
Media is too big
VIEW IN TELEGRAM
CppDeveloperRoadmap — репозиторий, в котором собраны книги, идеи для пэт-проектов и полезные ресурсы для изучения. Все материалы разбиты на уровни junior, middle и senior.
📣 C++ Ready | #репозиторий
Оставляю ссылочку: Github📱
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12❤5👍3
std::span + subspan(): “нарезай” буфер на части без копий и лишних new!
Это особенно удобно для протоколов и парсинга, где есть заголовок, тело и хвост.
Часто делают так: копируют куски в новые контейнеры.
Проблема в том, что это лишние аллокации и копирование: на каждом разрезе создаётся новый буфер, а в горячем коде парсинга это быстро становится дорогим.
Вместо копий — просто виды на исходный буфер:
Использование выглядит так же просто:
Важно помнить:
🔥
📣 C++ Ready | #практика
Это особенно удобно для протоколов и парсинга, где есть заголовок, тело и хвост.
Часто делают так: копируют куски в новые контейнеры.
std::vector<uint8_t> header(const std::vector<uint8_t>& buf, size_t n) {
return {buf.begin(), buf.begin() + n};
}
std::vector<uint8_t> payload(const std::vector<uint8_t>& buf, size_t n) {
return {buf.begin() + n, buf.end()};
}Проблема в том, что это лишние аллокации и копирование: на каждом разрезе создаётся новый буфер, а в горячем коде парсинга это быстро становится дорогим.
std::span не владеет памятью, зато позволяет сделать “вид” на нужный участок, и subspan() как раз возвращает такой срез.Вместо копий — просто виды на исходный буфер:
struct PacketView {
std::span<const std::uint8_t> hdr;
std::span<const std::uint8_t> body;
};
PacketView split(std::span<const std::uint8_t> buf, std::size_t n) {
return {
buf.subspan(0, n),
buf.subspan(n)
};
}Использование выглядит так же просто:
int main() {
std::vector<std::uint8_t> buf = {1,2,3,4,5,6,7,8};
auto p = split(buf, 3);
// p.hdr -> {1,2,3}
// p.body -> {4,5,6,7,8}
}Важно помнить:
span живёт только пока живут исходные данные, поэтому нельзя возвращать span на временный объект или локальный буфер, который скоро уничтожится.subspan() — это “срез без копии”: идеально для парсинга и разборки буферов, когда нужно быстро выделять части и не плодить новые вектора.Please open Telegram to view this post
VIEW IN TELEGRAM
❤15🔥8👍5
В этой статье:
• Понять, зачем в сервере столько уровней шаблонов вообще• Увидеть, как через типы собирается конфигурация API сервера• Разобраться, как шаблоны уменьшают бойлерплейт без рантайма лишнего🔊 Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7❤3👍3😁1
Почему {} иногда спасает от скрытых багов с конверсиями?
Самая коварная ошибка — когда число “влезло” в другой тип, но тихо обрезалось. С круглыми скобками или
В C++ есть безопасная привычка: использовать uniform initialization с фигурными скобками. Она запрещает narrowing-конверсии — то есть те, где можно потерять данные.
Например, вот это должно насторожить:
То же самое с дробными числами:
С
🔥 Итог: если инициализируешь числа (особенно при приведениях типов), чаще используй
📣 C++ Ready | #совет
Самая коварная ошибка — когда число “влезло” в другой тип, но тихо обрезалось. С круглыми скобками или
= такие конверсии легко проходят незаметно и потом превращаются в странные баги.В C++ есть безопасная привычка: использовать uniform initialization с фигурными скобками. Она запрещает narrowing-конверсии — то есть те, где можно потерять данные.
Например, вот это должно насторожить:
int a = 300;
std::uint8_t b{a};
std::uint8_t обычно хранит 0..255, а 300 не влезает. С {} компилятор обязан ругнуться, вместо того чтобы молча обрезать значение.То же самое с дробными числами:
double pi = 3.14;
int x{pi};
С
{} ты не сможешь “случайно” потерять дробную часть — компилятор остановит сборку.{} — это дешёвый способ ловить “тихие” обрезания на этапе компиляции.Please open Telegram to view this post
VIEW IN TELEGRAM
👍20❤6🔥6
This media is not supported in your browser
VIEW IN TELEGRAM
Технический блог Джеффа Прешинга, где он объясняет сложные темы “на пальцах”: атомики и memory ordering, lock-free подходы, тонкости работы компилятора/CPU и практические паттерны для производительного кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤16🔥6👍4
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19🤝7❤5👍2
На картинке — большая наглядная таблица, которая помогает быстро оценивать “сколько это будет работать” и “сколько это съест памяти”.
Здесь в одном месте собраны Big O для основных структур данных и их операций, а также для популярных алгоритмов сортировки, с акцентом на best/average/worst случаи и сравнение time vs space.
Сохрани, чтобы на лету выбирать подходящую структуру/алгоритм и прикидывать узкие места.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19❤6👍5
std::scoped_lock: берём два mutex без риска дедлока.
Когда нужно залочить несколько мьютексов, эта мелочь экономит часы отладки “редких зависаний”.
Часто пишут так и не замечают проблему:
На первый взгляд всё ок, но если два потока одновременно зайдут в
Правильный вариант в C++17 —
Смысл в том, что
🔥
📣 C++ Ready | #практика
Когда нужно залочить несколько мьютексов, эта мелочь экономит часы отладки “редких зависаний”.
Часто пишут так и не замечают проблему:
std::mutex m1, m2;
void a() {
std::lock_guard<std::mutex> l1(m1);
std::lock_guard<std::mutex> l2(m2);
// работа с общими данными
}
void b() {
std::lock_guard<std::mutex> l2(m2);
std::lock_guard<std::mutex> l1(m1);
// работа с общими данными
}
На первый взгляд всё ок, но если два потока одновременно зайдут в
a() и b(), один может держать m1 и ждать m2, а второй держать m2 и ждать m1. Это классический дедлок, который может проявляться “раз в неделю” и очень дорого стоит.Правильный вариант в C++17 —
std::scoped_lock, который лочит сразу несколько мьютексов одним объектом:std::mutex m1, m2;
void a() {
std::scoped_lock lock(m1, m2);
// работа с общими данными
}
void b() {
std::scoped_lock lock(m1, m2);
// тот же порядок, тот же механизм
}
Смысл в том, что
std::scoped_lock использует безопасный механизм захвата нескольких мьютексов, поэтому тебе не нужно вручную следить за порядком lock-ов и ловить редкие зависания на проде.std::scoped_lock — простая привычка, которая убирает целый класс дедлоков, когда ресурсов больше одного, а потоков больше одного.Please open Telegram to view this post
VIEW IN TELEGRAM
❤15🔥9👍5
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥64❤9👍7
Например,
GET используется для получения данных, POST — для создания новых записей, а DELETE — для удаления.На картинке — 9 самых популярных методов HTTP-запросов, которые стоит держать под рукой каждому разработчику.
Сохрани, чтобы не забыть!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21❤10🔥9🤝2
Небольшая консольная утилита оценивает пароль по понятным признакам: длина, разные типы символов и частые ошибки вроде пробелов.
В этой задаче узнаешь:
• Как за один проход по строке определить типы символов (islower/isdigit/ispunct);
• Как превратить простые правила в понятную оценку;
• Как сделать вывод полезным: подсказать конкретные шаги усиления пароля.
Это не “банковская” безопасность, а удобный чек-лист, который сразу показывает, что улучшить.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥32❤6👍4🤝3