В практике разработчика 1С часто возникает задача валидации данных, вводимых пользователем (поможет готовый конструктор валидации данных и автопроверок ввода) или получаемых из внешних систем. Одной из самых распространенных задач является проверка того, можно ли преобразовать строковое значение в число. На первый взгляд задача кажется простой, но она таит в себе множество нюансов: от разделителей дробной части до невидимых символов пробелов. В этой статье мы подробно разберем все способы решения этой задачи — от элементарных циклов до продвинутых методов с использованием регулярных выражений и системных функций.
Проанализируем самый надежный и универсальный метод. Платформа 1С имеет встроенную функцию Число(), которая пытается преобразовать строку в числовой тип. Если строка содержит недопустимые символы, система генерирует ошибку. Мы можем использовать это поведение в своих целях.
Рассмотрим пример кода:
Функция ЭтоЧисло(ЗначениеСтрока)
Попытка
Результат = Число(СокрЛП(ЗначениеСтрока));
Возврат Истина;
Исключение
Возврат Ложь;
КонецПопытки;
КонецФункции
Этот метод хорош тем, что он автоматически учитывает региональные настройки системы. Например, если в настройках ОС разделителем дробной части является запятая, то Число("10,5") отработает успешно. Важный момент: перед проверкой всегда используйте функцию СокрЛП(), чтобы убрать лишние пробелы по краям строки.
Разберем ситуацию, с которой часто сталкиваются начинающие разработчики. Попробуем проверить каждый символ строки вручную. В исходном сообщении была допущена классическая ошибка: цикл продолжал работу до последнего символа, и результат проверки зависел только от того, чем заканчивается строка.
Давайте проанализируем правильный алгоритм с использованием прерывания цикла:
СтрокаДляПроверки = "123.45";
Длина = СтрДлина(СтрокаДляПроверки);
ЭтоЧисло = Истина;
Для Поз = 1 По Длина Цикл
ТекСимвол = Сред(СтрокаДляПроверки, Поз, 1);
Если СтрНайти("0123456789.", ТекСимвол) = 0 Тогда
ЭтоЧисло = Ложь;
Прервать; // Критически важно остановить цикл сразу
КонецЕсли;
КонецЦикла;
Если ЭтоЧисло Тогда
Сообщить("Строка является числом");
Иначе
Сообщить("Строка содержит недопустимые символы");
КонецЕсли;
Обратите внимание на команду Прервать. Как только мы встретили хотя бы один «неправильный» символ, дальнейшая проверка не имеет смысла. Однако у этого метода есть недостаток: он посчитает строку "1.2.3" числом, хотя в ней две точки. Для корректной работы нужно добавлять счетчик разделителей.
Посмотрим на более лаконичный, «продвинутый» способ, предложенный участниками обсуждения. Идея заключается в том, чтобы удалить из строки все цифры и разделители. Если после удаления останется пустая строка — значит, в исходном тексте были только цифры.
// Простая проверка на целое положительное число
Строка = "12345";
ЭтоЧисло = (СтрСоединить(СтрРазделить(Строка, "0123456789"), "") = "");
Чтобы адаптировать этот метод для дробных и отрицательных чисел, нам нужно добавить точку, запятую и минус в фильтр, но при этом предусмотреть проверку их количества и расположения. Этот метод элегантен, но менее надежен, чем Попытка.
Если мы работаем на современных версиях платформы (начиная с 8.3.24), нам доступен встроенный объект РегулярноеВыражение. Для более старых версий можно использовать COM-объект VBScript.RegExp. Это самый гибкий метод, позволяющий задать точный шаблон числа.
Рассмотрим, как реализовать проверку через регулярное выражение:
// Пример для новых версий платформы
Шаблон = "^-?[0-9]+([.,][0-9]+)?$";
РегЭксп = Новый РегулярноеВыражение(Шаблон);
Если РегЭксп.Совпадает(СтрокаДляПроверки) Тогда
Сообщить("Это корректное число");
КонецЕсли;
Разберем шаблон ^-?[0-9]+([.,][0-9]+)?$ подробнее:
^ и $ — начало и конец строки.-? — возможный минус в начале.[0-9]+ — одна или более цифр.([.,][0-9]+)? — необязательная дробная часть, начинающаяся с точки или запятой.Проанализируем проблемы, которые могут возникнуть при использовании любого из методов:
Число() его понимает, а самописные циклы — нет. Перед проверкой рекомендуется заменить символ с кодом 160 на пустую строку: СтрЗаменить(Строка, Символ(160), "").Попытка с функцией Число() вернет Истина, в то время как простые проверки на цифры выдадут ошибку из-за буквы "e".Попытки наиболее безопасно, так как она опирается на текущие настройки сеанса.ОбщегоНазначения.ЭтоЧисло(Значение). Она уже содержит в себе все необходимые проверки и обработки исключений, что крайне важно.Мы рассмотрели несколько подходов к проверке строк. Для большинства повседневных задач оптимальным выбором будет Способ 1 (Попытка — Исключение) из-за его надежности и поддержки системных настроек. Если же вам требуется специфическая валидация (например, строго 2 знака после запятой или запрет экспоненциальной записи), воспользуйтесь регулярными выражениями.
Всегда помните о предварительной очистке строки от пробелов и невидимых символов.