❓ Как получить размер файла в байтах?
В C++17 была добавлена библиотека filesystem, которая упрощает работу с файловой системой
❗️Стоит учитывать, что если файл был открыт не только вами, то размер может быть изменён извне
В C++17 была добавлена библиотека filesystem, которая упрощает работу с файловой системой
#include <filesystem>
int main()
{
std::uintmax_t size = std::filesystem::file_size("file.txt");
}
❗️Стоит учитывать, что если файл был открыт не только вами, то размер может быть изменён извне
🔥7
🍔 Отладочные макросы
Отладочные макросы в C++ используются для упрощения процесса отладки и диагностики программного кода
Основные отладочные макросы включают assert, static_assert и пользовательские макросы
🍓 assert
Макрос assert определён в заголовочном файле <cassert> и используется для проверки логических выражений во время выполнения программы. Если выражение вернёт false, assert завершает выполнение программы и выводит сообщение об ошибке
🍒 static_assert
static_assert введён в C++11 и позволяет проверять условия на этапе компиляции. Это особенно полезно для проверки условий, которые должны выполняться всегда, независимо от состояния программы во время выполнения
❗️Начиная с C++11 и C23 static_assert является ключевым словом
🫐 Пользовательские отладочные макросы
Вы также можете определять собственные макросы для отладки, которые помогут вам выводить дополнительную информацию или выполнять специфические проверки
Отладочные макросы в C++ используются для упрощения процесса отладки и диагностики программного кода
Основные отладочные макросы включают assert, static_assert и пользовательские макросы
🍓 assert
Макрос assert определён в заголовочном файле <cassert> и используется для проверки логических выражений во время выполнения программы. Если выражение вернёт false, assert завершает выполнение программы и выводит сообщение об ошибке
#include <cassert>
void test(int x) {
assert(x > 0 && "x must be positive");
// остальной код функции
}
int main() {
test(5); // проходит проверку
test(-3); // приводит к ошибке во время выполнения
return 0;
}
🍒 static_assert
static_assert введён в C++11 и позволяет проверять условия на этапе компиляции. Это особенно полезно для проверки условий, которые должны выполняться всегда, независимо от состояния программы во время выполнения
#include <type_traits>
template <typename T>
void check() {
static_assert(std::is_integral<T>::value, "T must be an integral type");
}
int main() {
check<int>(); // проходит проверку
check<float>(); // ошибка компиляции: T must be an integral type
return 0;
}
❗️Начиная с C++11 и C23 static_assert является ключевым словом
🫐 Пользовательские отладочные макросы
Вы также можете определять собственные макросы для отладки, которые помогут вам выводить дополнительную информацию или выполнять специфические проверки
#include <iostream>
#define DEBUG
#ifdef DEBUG
#define DEBUG_PRINT(x) std::cout << x << std::endl
#else
#define DEBUG_PRINT(x)
#endif
int main() {
int value = 42;
DEBUG_PRINT("Value: " << value);
return 0;
}
👍5🔥1
🍯 Задача с собеседования
Входные данные:
- Дан массив состоящий из int'ов
- Повторяющихся элементов в списке нет
Задача:
- Нужно преобразовать этот массив в строку, сворачивая соседние по числовому ряду числа в диапазоны
Примеры:
[1,4,5,2,3,9,8,11,0] => "0-5,8-9,11"
[1,4,3,2] => "1-4"
[1,4] => "1,4"
Входные данные:
- Дан массив состоящий из int'ов
- Повторяющихся элементов в списке нет
Задача:
- Нужно преобразовать этот массив в строку, сворачивая соседние по числовому ряду числа в диапазоны
Примеры:
[1,4,5,2,3,9,8,11,0] => "0-5,8-9,11"
[1,4,3,2] => "1-4"
[1,4] => "1,4"
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
std::string convertToRanges(std::vector<int>& nums) {
if (nums.empty()) {
return "";
}
// Сортируем вектор
std::sort(nums.begin(), nums.end());
std::vector<std::string> ranges;
int start = nums[0];
int prev = start;
for (size_t i = 1; i < nums.size(); ++i) {
if (nums[i] != prev + 1) {
// Если последовательность прервалась, добавляем диапазон
if (start == prev) {
ranges.push_back(std::to_string(start));
}
else {
ranges.push_back(std::to_string(start) + "-" + std::to_string(prev));
}
start = nums[i];
}
prev = nums[i];
}
// Добавляем последний диапазон
if (start == prev) {
ranges.push_back(std::to_string(start));
}
else {
ranges.push_back(std::to_string(start) + "-" + std::to_string(prev));
}
// Объединяем диапазоны в одну строку
std::ostringstream result;
for (size_t i = 0; i < ranges.size(); ++i) {
if (i > 0) {
result << ",";
}
result << ranges[i];
}
return result.str();
}
int main() {
std::vector<int> nums1 = { 1, 4, 5, 2, 3, 9, 8, 11, 0 };
std::cout << convertToRanges(nums1) << std::endl; // Ожидаемый вывод: "0-5,8-9,11"
std::vector<int> nums2 = { 1, 4, 3, 2 };
std::cout << convertToRanges(nums2) << std::endl; // Ожидаемый вывод: "1-4"
std::vector<int> nums3 = { 1, 4 };
std::cout << convertToRanges(nums3) << std::endl; // Ожидаемый вывод: "1,4"
return 0;
}
👍2
Почему использование std::endl может быть менее эффективным, чем \n в некоторых случаях?
Всё дело в буферизации вывода
- std::endl не только добавляет символ новой строки (\n) в поток, но и явно сбрасывает (flushes) буфер вывода. Это означает, что данные из буфера немедленно отправляются в устройство вывода (например, на экран или в файл).
- \n, напротив, просто добавляет символ новой строки в поток без принудительного сброса буфера. Буферизация остаётся управляемой самой стандартной библиотекой, и данные выводятся только тогда, когда буфер заполняется или программа явно вызывает std::flush.
В результате выполния кода будет заметно, что время вывода с \n будет меньше.
- std::endl не только добавляет символ новой строки (\n) в поток, но и явно сбрасывает (flushes) буфер вывода. Это означает, что данные из буфера немедленно отправляются в устройство вывода (например, на экран или в файл).
- \n, напротив, просто добавляет символ новой строки в поток без принудительного сброса буфера. Буферизация остаётся управляемой самой стандартной библиотекой, и данные выводятся только тогда, когда буфер заполняется или программа явно вызывает std::flush.
#include <iostream>
#include <chrono>
int main() {
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 10000; ++i) {
std::cout << "Hello, World!" << std::endl; // Принудительный сброс после каждой строки
}
auto middle = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 10000; ++i) {
std::cout << "Hello, World!\n"; // Буферизация, меньше операций I/O
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Time with std::endl: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(middle - start).count()
<< " ms\n";
std::cout << "Time with \\n: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end - middle).count()
<< " ms\n";
return 0;
}
В результате выполния кода будет заметно, что время вывода с \n будет меньше.
👍4
📚 Загадочная библиотека setjmp.h — неочевидный инструмент для управления потоком выполнения
Библиотека setjmp.h предоставляет два необычных макроса:
• setjmp — сохраняет текущее состояние программы (регистры, стек) в буфер jmp_buf
• longjmp — «откатывает» выполнение к сохранённому состоянию, как прыжок во времени
⚠️ Осторожно!
• Не заменяет исключения — нет вызова деструкторов (как в C++)
• Опасность утечек — если между setjmp и longjmp выделялась память, она не освободится
• Портит стек — может сломать логику функций
🛠 Где может пригодиться?
• Обработка критических ошибок (а-ля «аварийный выход»)
• Код для встраиваемых систем, где нужно быстро восстановить состояние
• Нестандартные хаки (но лучше так не делать 😈)
Библиотека C/C++ разработчика
Библиотека setjmp.h предоставляет два необычных макроса:
• setjmp — сохраняет текущее состояние программы (регистры, стек) в буфер jmp_buf
• longjmp — «откатывает» выполнение к сохранённому состоянию, как прыжок во времени
#include <stdio.h>
#include <setjmp.h>
jmp_buf jump_buffer;
void risky_function() {
printf("Готовимся к прыжку...\n");
longjmp(jump_buffer, 42); // Прыжок обратно в setjmp!
}
int main() {
int ret = setjmp(jump_buffer);
if (ret == 0) {
printf("Первая инициализация...\n");
risky_function();
} else {
printf("Вернулись с кодом: %d\n", ret); // Выведет 42!
}
return 0;
}
⚠️ Осторожно!
• Не заменяет исключения — нет вызова деструкторов (как в C++)
• Опасность утечек — если между setjmp и longjmp выделялась память, она не освободится
• Портит стек — может сломать логику функций
🛠 Где может пригодиться?
• Обработка критических ошибок (а-ля «аварийный выход»)
• Код для встраиваемых систем, где нужно быстро восстановить состояние
• Нестандартные хаки (но лучше так не делать 😈)
Библиотека C/C++ разработчика
🥱3👍2
Forwarded from Библиотека задач по C++ | тесты, код, задания
Какое утверждение о модулях C++20 является верным?
Anonymous Quiz
20%
Модули полностью заменяют заголовочные файлы и #include
57%
Модули компилируются быстрее заголовочных файлов и не подвержены проблемам One Definition Rule
5%
Модули могут экспортировать только классы, но не функции
13%
Модули автоматически решают все проблемы циклических зависимостей
4%
Модули работают только с компилятором GCC