Собираем простой dispatcher команд на C++!
Иногда программа принимает строковую команду и должна вызвать нужное действие. Самый быстрый путь часто начинается с цепочки if.
Например, так легко получить длинный блок условий:
Когда команд становится больше, такой код сложнее расширять и тестировать. Удобнее явно завести таблицу команд.
Опишем тип обработчика:
Теперь можно собрать словарь:
Вызов становится коротким и одинаковым для всех команд:
Если команда не найдена, можно отдельно обработать ошибку:
Такой dispatcher удобно использовать в CLI-утилитах, тестовых меню, админских командах и маленьких инструментах. Новая команда добавляется одной строкой в таблицу, а не ещё одной веткой в середине логики.
📣 C++ Ready | #практика
Иногда программа принимает строковую команду и должна вызвать нужное действие. Самый быстрый путь часто начинается с цепочки if.
Например, так легко получить длинный блок условий:
if (cmd == "build") build();
else if (cmd == "clean") clean();
else if (cmd == "status") status();
Когда команд становится больше, такой код сложнее расширять и тестировать. Удобнее явно завести таблицу команд.
Опишем тип обработчика:
using Handler = void (*)();
Теперь можно собрать словарь:
std::unordered_map commands{
{"build", build},
{"clean", clean},
{"status", status}
};Вызов становится коротким и одинаковым для всех команд:
auto it = commands.find(cmd);
if (it != commands.end()) {
it->second();
}
Если команда не найдена, можно отдельно обработать ошибку:
if (it == commands.end()) {
std::cout << "unknown command\n";
return;
}Такой dispatcher удобно использовать в CLI-утилитах, тестовых меню, админских командах и маленьких инструментах. Новая команда добавляется одной строкой в таблицу, а не ещё одной веткой в середине логики.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍4🔥3
Разбираем std::filesystem 7 функций для работы с файлами!
std::filesystem помогает работать с путями, директориями и файлами без ручной склейки строк и платформенных ifdef.
В этой шпоре: exists, is_regular_file, create_directories, directory_iterator, recursive_directory_iterator, copy_file и remove_all.
📣 C++ Ready | #шпора
std::filesystem помогает работать с путями, директориями и файлами без ручной склейки строк и платформенных ifdef.
В этой шпоре: exists, is_regular_file, create_directories, directory_iterator, recursive_directory_iterator, copy_file и remove_all.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍6❤5
Парсим простой CSV без сторонних библиотек на C++!
Иногда нужно разобрать строку CSV из лога, экспорта или конфигурации. Если формат простой, можно обойтись стандартной библиотекой и аккуратно пройти строку посимвольно.
Возьмём строку:
Главная сложность это запятая внутри кавычек. Её нельзя считать разделителем.
Заведём буфер и флаг:
Теперь проходим символы:
После цикла не забываем добавить последнюю ячейку:
Проверим результат:
Ожидаемый вывод:
При парсинге текста важно учитывать контекст. Одна и та же запятая может быть разделителем или обычным символом внутри значения.
📣 C++ Ready | #практика
Иногда нужно разобрать строку CSV из лога, экспорта или конфигурации. Если формат простой, можно обойтись стандартной библиотекой и аккуратно пройти строку посимвольно.
Возьмём строку:
std::string line = "id,\"hello, cpp\",active";
Главная сложность это запятая внутри кавычек. Её нельзя считать разделителем.
Заведём буфер и флаг:
std::string cell;
bool quoted = false;
Теперь проходим символы:
for (char ch : line) {
if (ch == '"') {
quoted = !quoted;
continue;
}
if (ch == ',' && !quoted) {
cells.push_back(cell);
cell.clear();
continue;
}
cell += ch;
}После цикла не забываем добавить последнюю ячейку:
cells.push_back(cell);
Проверим результат:
for (const auto& value : cells) {
std::cout << '[' << value << "]\n";
}Ожидаемый вывод:
[id]
[hello, cpp]
[active]
При парсинге текста важно учитывать контекст. Одна и та же запятая может быть разделителем или обычным символом внутри значения.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍4🔥2
Собираем простой парсер CLI-аргументов на C++!
Нужно разобрать аргументы командной строки. Сделаем маленький парсер для флагов и параметров вида --key=value.
В этой задаче:
Такой парсер удобен для утилит, тестовых запусков и маленьких dev-инструментов.
📣 C++ Ready | #задача
Нужно разобрать аргументы командной строки. Сделаем маленький парсер для флагов и параметров вида --key=value.
В этой задаче:
• идём по argv
• отделяем флаги от значений
• сохраняем параметры в map
• проверяем наличие нужных опций
Такой парсер удобен для утилит, тестовых запусков и маленьких dev-инструментов.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4🔥3
This media is not supported in your browser
VIEW IN TELEGRAM
В репозитории собраны решения и упражнения из специализации «Основы разработки на современном C++» от МФТИ и Яндекса. Материал разбит по уровням сложности — от «Белого пояса» с базовыми конструкциями языка до более продвинутых заданий из «Жёлтого», «Красного» и «Коричневого поясов».
Оставляю ссылочку: GitHub
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤7🔥5👎3
Почему reserve() не добавляет элементы в vector?
reserve() часто используют перед заполнением vector:
После этого у vector действительно появляется место под 10 элементов, но размер остаётся нулевым:
Важно не путать size и capacity.
Такой код ошибочный:
Индексатор работает только с уже существующими элементами. reserve() выделяет память, но не создаёт объекты внутри vector.
Если нужно добавить значения, используй push_back():
А если нужны именно 10 готовых элементов, нужен resize():
reserve() полезен, когда ты заранее знаешь примерное количество будущих элементов:
Так vector реже перевыделяет память при росте.
📣 C++ Ready | #совет
reserve() часто используют перед заполнением vector:
std::vector<int> nums;
nums.reserve(10);
После этого у vector действительно появляется место под 10 элементов, но размер остаётся нулевым:
std::cout << nums.size() << '\n'; // 0
std::cout << nums.capacity() << '\n'; // 10
Важно не путать size и capacity.
Такой код ошибочный:
std::vector<int> nums;
nums.reserve(10);
nums[0] = 42; // undefined behavior
Индексатор работает только с уже существующими элементами. reserve() выделяет память, но не создаёт объекты внутри vector.
Если нужно добавить значения, используй push_back():
nums.push_back(42);
nums.push_back(100);
А если нужны именно 10 готовых элементов, нужен resize():
std::vector<int> nums;
nums.resize(10);
nums[0] = 42;
reserve() полезен, когда ты заранее знаешь примерное количество будущих элементов:
std::vector<std::string> logs;
logs.reserve(1000);
for (auto line : input) {
logs.push_back(line);
}
Так vector реже перевыделяет память при росте.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍4🔥2
Интересная статья про constexpr Game of Life на C++!
Автор разбирает необычный эксперимент, где логика игры считается ещё на этапе компиляции. Внутри есть consteval, constexpr, двумерный Canvas, генерация поколений и попытка достать результат без обычного запуска программы.
В статье автор показывает:
• как Game of Life можно представить как набор compile-time вычислений
• зачем нужен consteval и чем он строже обычного constexpr
• как искать результат работы программы в артефактах сборки
📣 C++ Ready | #статья
Автор разбирает необычный эксперимент, где логика игры считается ещё на этапе компиляции. Внутри есть consteval, constexpr, двумерный Canvas, генерация поколений и попытка достать результат без обычного запуска программы.
В статье автор показывает:
• как Game of Life можно представить как набор compile-time вычислений
• зачем нужен consteval и чем он строже обычного constexpr
• как искать результат работы программы в артефактах сборки
Продолжай читать на Habr
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7🔥4👍2