При обработке текстовых данных, парсинге строк или валидации пользовательского ввода разработчики часто сталкиваются с задачей: как быстро и надежно определить, является ли конкретный символ цифрой (диапазон от "0" до "9") или буквой (диапазон от "А" до "Я"). В отличие от некоторых других языков программирования, во встроенном языке 1С нет встроенного оператора работы с множествами вида in ['0'..'9']. Однако эту задачу можно эффективно решить несколькими способами. Разберем по шагам доступные варианты реализации, их плюсы, минусы и подводные камни.
Рассмотрим самый простой, лаконичный и быстрый способ. В платформе 1С строки можно сравнивать стандартными операторами сравнения (>= и <=). Символы сравниваются в соответствии с их лексикографическим порядком (по кодовой таблице).
Посмотрим на пример проверки одиночного символа на принадлежность к цифрам:
Если Символ >= "0" И Символ <= "9" Тогда
// Символ является цифрой
КонецЕсли;
Аналогично можно проверить принадлежность к русскому алфавиту, но здесь важно учитывать регистр символов:
СимволВРег = ВРег(Символ);
Если (СимволВРег >= "А" И СимволВРег <= "Я") Или СимволВРег = "Ё" Тогда
// Символ является русской буквой
КонецЕсли;
Важный нюанс: обратите внимание на букву «Ё». В кодировке Unicode заглавная буква «Ё» (код 1025) и строчная «ё» (код 1105) расположены вне непрерывного диапазона русских букв «А»–«я» (коды с 1040 по 1103). Если просто написать условие Символ >= "А" И Символ <= "Я", буква «Ё» не попадет в этот диапазон. Ее всегда следует проверять отдельно.
Проанализируем еще один популярный способ — проверку вхождения символа в заранее подготовленную строку со всеми допустимыми символами. Для этого во встроенном языке используется функция СтрНайти (или устаревший аналог Найти).
Посмотрим, как выглядит такой код:
Если СтрНайти("0123456789", Символ) > 0 Тогда
// Символ найден среди цифр
КонецЕсли;
Для проверки букв кириллицы строка-эталон составляется аналогично:
СимволыАлфавита = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
Если СтрНайти(СимволыАлфавита, ВРег(Символ)) > 0 Тогда
// Символ является русской буквой
КонецЕсли;
Особенность метода: этот подход отлично подходит, если проверяется именно одиночный символ (длиной ровно 1). Если же передать строку из нескольких символов, например "12", функция СтрНайти("0123456789", "12") также вернет положительный результат, так как подстрока найдена целиком. Всегда контролируйте длину проверяемого фрагмента.
Разберем низкоуровневый вариант с использованием функции КодСимвола. Этот метод исключает влияние настроек региональной сортировки строк и работает напрямую с кодами Unicode.
Рассмотрим пример условия, охватывающего цифры, латиницу и кириллицу:
КодС = КодСимвола(Стр, Индекс);
ЭтоЦифра = (КодС >= 48 И КодС <= 57);
ЭтоЛатиница = (КодС >= 65 И КодС <= 90) Или (КодС >= 97 И КодС <= 122);
ЭтоКириллица = (КодС >= 1040 И КодС <= 1103) Или КодС = 1025 Или КодС = 1105;
Если ЭтоЦифра Или ЭтоЛатиница Или ЭтоКириллица Тогда
// Символ входит в допустимый диапазон
КонецЕсли;
Этот способ работает очень быстро при обработке больших массивов текста посимвольно в цикле, однако код получается менее читаемым по сравнению с обычным сравнением строк.
Выясним, как решается задача с помощью регулярных выражений. Здесь подход зависит от версии платформы 1С:Предприятие:
СтрПодобнаПоРегулярномуВыражению:
// Проверка на цифру
ЭтоЦифра = СтрПодобнаПоРегулярномуВыражению(Символ, "^[0-9]$");
// Проверка на русскую букву любого регистра с учетом буквы Ё
ЭтоБуква = СтрПодобнаПоРегулярномуВыражению(Символ, "^[а-яёА-ЯЁ]$");
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина;
RegExp.Pattern = "^[0-9]$";
Если RegExp.Test(Символ) Тогда
// Символ является цифрой
КонецЕсли;
COMОбъект работает исключительно в среде Windows. На серверах и клиентах под управлением Linux, в веб-клиенте и на macOS создание COM-объекта завершится аварийной ошибкой. Кроме того, постоянное создание COM-объектов в цикле критически снижает скорость работы алгоритма.
Если необходимо проверить большой массив текста на принадлежность произвольному набору символов, можно смоделировать структуру данных «Множество» с помощью объекта Соответствие. Поиск по ключу в Соответствие выполняется за константное время $O(1)$.
Посмотрим на практическую реализацию:
МножествоСимволов = Новый Соответствие;
Для Индекс = 0 По 9 Цикл
МножествоСимволов.Вставить(Формат(Индекс, "ЧГ="), Истина);
КонецЦикла;
// Быстрая проверка принадлежности:
Если МножествоСимволов[Символ] <> Неопределено Тогда
// Символ принадлежит заданному множеству
КонецЕсли;
Если ваша конфигурация разработана на основе БСП (1С:ERP, УТ, КА, БП, ЗУП и др.), не требуется писать собственные проверки для цифр. В общем модуле СтроковыеФункцииКлиентСервер уже реализована готовая функция:
Если СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке(Символ) Тогда
// Символ или строка состоит только из цифр
КонецЕсли;
Рассмотрим частые ошибки при проверке символов:
ПОДОБНО с шаблонами вида [0-9] поддерживается исключительно в языке запросов к базе данных. Во встроенном языке модулей оператора ПОДОБНО нет. Выполнять запрос к СУБД ради проверки одного символа крайне неэффективно.Число(Символ) внутри блока Попытка... Исключение возвращает ложные срабатывания. Например, для пробелов Число(" ") или пустой строки функция не вызывает исключение, а успешно возвращает 0, что приводит к логическим ошибкам.