В практике разработки на платформе 1С:Предприятие часто возникает задача валидации данных, введенных пользователем. Одной из самых распространенных задач является проверка того, является ли строка числом. Казалось бы, задача тривиальна, но она имеет множество нюансов: от обработки разделителей дробной части до производительности кода при массовой обработке данных. В этой статье мы рассмотрим подробнее несколько подходов к решению этой задачи, проанализируем их плюсы и минусы, и выберем наиболее подходящий вариант для различных ситуаций.
Самый очевидный и «нативный» способ — это попытка прямого преобразования строки в число с помощью встроенной функции Число(). Если строка не соответствует формату числа, платформа вызовет исключение, которое мы можем перехватить.
Давайте разберем по шагам, как это реализовать:
Функция ЭтоЧисло(Знач ИсходнаяСтрока)
Попытка
Результат = Число(ИсходнаяСтрока);
Возврат Истина;
Исключение
Возврат Ложь;
КонецПопытки;
КонецФункции
Преимущества: этот метод учитывает региональные настройки (например, понимает и точку, и запятую в качестве разделителя в зависимости от локали) и умеет обрабатывать научную нотацию (например, «1e2»).
Недостатки: использование исключений для реализации логики программы считается «плохим тоном» в программировании, так как генерация исключения — ресурсозатратная операция. Если вам нужно проверить 100 000 строк, из которых половина не являются числами, код будет работать крайне медленно.
Если нам нужно строгое соответствие условию «только цифры и точка» (без учета пробелов, минусов и запятых), рассмотрим алгоритм ручного перебора. Этот метод надежен и работает на любой версии платформы.
Проанализируем ситуацию, когда нам нужно не просто найти недопустимые символы, но и убедиться, что точка в числе всего одна:
Функция ПроверитьСтрокуНаЧисло(ПроверяемаяСтрока)
Результат = Истина;
Если ПустаяСтрока(ПроверяемаяСтрока) Тогда
Возврат Ложь;
КонецЕсли;
КоличествоТочек = 0;
Для Поз = 1 По СтрДлина(ПроверяемаяСтрока) Цикл
ТекСимвол = Сред(ПроверяемаяСтрока, Поз, 1);
Если СтрНайти("0123456789", ТекСимвол) > 0 Тогда
// Это цифра, продолжаем проверку
ИначеЕсли ТекСимвол = "." Тогда
КоличествоТочек = КоличествоТочек + 1;
// Точка не может быть первой, последней или встречаться дважды
Если КоличествоТочек > 1 Или Поз = 1 Или Поз = СтрДлина(ПроверяемаяСтрока) Тогда
Результат = Ложь;
Прервать;
КонецЕсли;
Иначе
// Любой другой символ делает строку не числом
Результат = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Начиная с версии платформы 8.3.23, в 1С появилась встроенная поддержка регулярных выражений. Это самый изящный и быстрый способ проверки. Выясним, как составить правильный шаблон.
Для проверки числа, состоящего из цифр и необязательной точки, подойдет следующий код:
Функция ЭтоЧислоРегулярка(ПроверяемаяСтрока)
// Шаблон: начало строки, цифры, возможная группа (точка и цифры), конец строки
Шаблон = "^\d+(\.\d+)?$";
Возврат СтрПодобнаПоРегулярномуВыражению(ПроверяемаяСтрока, Шаблон);
КонецФункции
Важный нюанс: символ \d в регулярных выражениях 1С может соответствовать не только арабским цифрам, но и цифровым символам других языков. Если нужна максимальная строгость, используйте диапазон [0-9].
Интересный и быстрый способ — «вычесть» из строки все допустимые символы. Если после удаления всех цифр и точки строка осталась пустой, значит, она состояла только из них. Посмотрим на пример такой реализации:
Функция ПроверкаЧерезРазделение(ИсходнаяСтрока)
// Удаляем из строки все цифры и точку
МассивЧастей = СтрРазделить(ИсходнаяСтрока, "0123456789.", Ложь);
// Если массив пустой, значит лишних символов нет
Если МассивЧастей.Количество() > 0 Тогда
Возврат Ложь;
КонецЕсли;
// Дополнительно проверим количество точек, чтобы не пропустить "1.2.3"
Возврат СтрЧислоВхождений(ИсходнаяСтрока, ".") <= 1;
КонецФункции
Этот метод работает быстрее, чем посимвольный перебор в цикле Для, так как основные операции выполняются платформенными функциями, написанными на C++.
Этот способ часто встречается в типовых конфигурациях (БСП). Мы создаем объект ОписаниеТипов для числа и пытаемся «привести» значение строки к этому типу. Проанализируем этот подход:
Функция ЭтоЧислоЧерезОписаниеТипов(Значение)
ОписаниеЧисла = Новый ОписаниеТипов("Число");
ПриведенноеЗначение = ОписаниеЧисла.ПривестиЗначение(Значение);
// Если результат не 0, то это точно число.
// Если 0 - нужно проверить, не была ли сама строка нулем.
Если ПриведенноеЗначение <> 0 Тогда
Возврат Истина;
Иначе
Возврат СокрЛП(Значение) = "0";
КонецЕсли;
КонецФункции
Подводя итог нашему исследованию, сформулируем рекомендации по выбору метода:
СтрРазделить или оптимизированный посимвольный перебор.Попытка...Исключение с функцией Число() будет самым простым и надежным решением, так как она учитывает системные настройки разделителей.Важный момент: всегда помните о функции СокрЛП(). Пользователи часто случайно добавляют невидимые пробелы в начале или конце строки, что может привести к ложноотрицательному результату при строгой проверке символов.