Валидация данных в C++: обзор библиотек и практические примеры
В современной разработке на C++ валидация данных — один из ключевых этапов обработки пользовательского ввода, сетевых запросов или файлов конфигурации. Без надёжной проверки приложение становится уязвимым к некорректным данным, что может привести к падениям, утечкам памяти или логическим ошибкам. В этой статье мы рассмотрим основные подходы и популярные библиотеки для валидации данных в C++.
Зачем нужна валидация?
Валидация решает три основные задачи:
- Безопасность — предотвращение ввода вредоносных данных (SQL-инъекции, переполнение буфера).
- Корректность — гарантия, что данные соответствуют ожидаемому формату (email, номер телефона, возраст).
- Стабильность — исключение сбоев при преобразовании типов (например, строка в число).
Библиотеки для валидации в C++
Рассмотрим несколько популярных решений, которые можно использовать в проектах на C++.
1. Boost.LexicalCast — простая проверка чисел
Библиотека Boost.LexicalCast позволяет безопасно преобразовывать строки в числа и наоборот. При ошибке выбрасывается исключение boost::bad_lexical_cast.
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
bool isValidNumber(const std::string& input) {
try {
int value = boost::lexical_cast<int>(input);
return (value >= 0 && value <= 100);
} catch (const boost::bad_lexical_cast&) {
return false;
}
}
int main() {
std::cout << isValidNumber("50") << std::endl; // 1
std::cout << isValidNumber("abc") << std::endl; // 0
return 0;
}
2. PicoJSON — валидация JSON-структур
Для проверки JSON-данных часто используют легковесную библиотеку PicoJSON. Она позволяет разобрать JSON и проверить наличие обязательных полей.
#include "picojson.h"
#include <iostream>
#include <string>
bool validateUserJSON(const std::string& jsonStr) {
picojson::value val;
std::string err = picojson::parse(val, jsonStr);
if (!err.empty()) return false;
picojson::object& obj = val.get<picojson::object>();
// Проверяем наличие поля "name" типа string
if (obj.count("name") == 0 || !obj["name"].is<std::string>()) return false;
// Проверяем поле "age" — должно быть числом и > 0
if (obj.count("age") == 0 || !obj["age"].is<double>()) return false;
double age = obj["age"].get<double>();
if (age <= 0 || age > 150) return false;
return true;
}
int main() {
std::string valid = R"({"name":"Alice","age":30})";
std::string invalid = R"({"name":"Bob","age":-5})";
std::cout << validateUserJSON(valid) << std::endl; // 1
std::cout << validateUserJSON(invalid) << std::endl; // 0
return 0;
}
3. Паттерн Validator (самописная реализация)
Если нужно гибкое правило валидации, можно реализовать собственный класс-валидатор. Пример для проверки email-адреса:
#include <regex>
#include <string>
#include <iostream>
class EmailValidator {
public:
bool validate(const std::string& email) const {
// Простейшее регулярное выражение для email
static const std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})");
return std::regex_match(email, pattern);
}
};
int main() {
EmailValidator ev;
std::cout << ev.validate("user@example.com") << std::endl; // 1
std::cout << ev.validate("invalid-email") << std::endl; // 0
return 0;
}
Сравнение подходов
Выбор инструмента зависит от задачи:
- Boost.LexicalCast — для быстрой проверки чисел и преобразования строк.
- PicoJSON — для валидации JSON-данных от API или конфигурационных файлов.
- Паттерн Validator — для