При разработке алгоритмов сортировки, парсинга или валидации строк разработчики часто сталкиваются с неочевидным поведением операторов сравнения во встроенном языке 1С. Рассмотрим классический парадокс: если проверить числовые коды символов точки и звёздочки, то код точки оказывается больше кода звёздочки, однако прямое сравнение строковых значений возвращает противоположный результат.
Посмотрим на пример кода, демонстрирующий эту ситуацию:
КодТочки = КодСимвола("."); // Возвращает 46
КодЗвездочки = КодСимвола("*"); // Возвращает 42
РезультатКодов = (КодТочки < КодЗвездочки); // 46 < 42 -> Ложь
РезультатСтрок = ("." < "*"); // Результат -> Истина
Разберем детально, почему так происходит, как платформа 1С обрабатывает текстовые данные и как реализовать строгое упорядочивание символов по кодам Unicode.
Проанализируем механику работы каждого оператора, чтобы понять разницу:
КодСимвола() возвращает целочисленный порядковый номер символа в таблице кодировки Unicode (UTF-16). Для символа точки "." этот код равен 46, а для знака умножения / звёздочки "*" — 42. Сравнение обычных чисел подчиняется строгим математическим правилам: 46 < 42 возвращает значение Ложь.<, >, =, <=, >= выполняют не побайтовое и не числовое сопоставление символов, а лингвистическое сравнение (Collation). При строковом сравнении платформа сопоставляет символам весовые коэффициенты в соответствии с правилами Unicode Collation Algorithm (UCA) и системными языковыми стандартами.В правилах лингвистической сортировки знаки препинания, типографические и специальные символы имеют особый приоритет. В таблицах весов точка упорядочивается раньше звёздочки, поэтому логическое выражение "." < "*" закономерно вычисляется как Истина.
Аналогичная ситуация возникает и с буквами алфавита. Например, выражение "а" < "Я" возвращает Истина, хотя в таблице кодировки заглавные буквы имеют меньший числовой код, чем строчные. Другой яркий пример — буква "ё": в таблице Unicode она расположена отдельно от основного диапазона русского алфавита, но при языковом сравнении корректно встает рядом с буквой "е".
Разберем, как контекст выполнения влияет на работу со строками:
СтрСравнить() и объект СравнениеЗначений также выполняют лингвистическое сопоставление, но без учета регистра.УПОРЯДОЧИТЬ ПО и условия фильтрации ГДЕ выполняются силами базы данных. Здесь действуют правила Collation конкретной СУБД (например, Russian_100_CI_AS для MS SQL Server или внутренний Collation файла базы 1CD), где регистр букв по умолчанию игнорируется.Важно помнить, что во встроенном языке платформы 1С нет штатного модификатора для операторов сравнения, аналогичного порядковому (Ordinal) режиму в других языках программирования.
Если бизнес-логика алгоритма требует строгого лексикографического порядка (в точном соответствии с таблицей Unicode), напишем универсальную функцию для посимвольного сравнения кодов:
Функция СтрокаМеньшеПоКодам(Знач Строка1, Знач Строка2)
Длина1 = СтрДлина(Строка1);
Длина2 = СтрДлина(Строка2);
МинДлина = Мин(Длина1, Длина2);
Для Индекс = 1 По МинДлина Цикл
Код1 = КодСимвола(Сред(Строка1, Индекс, 1));
Код2 = КодСимвола(Сред(Строка2, Индекс, 1));
Если Код1 <> Код2 Тогда
Возврат Код1 < Код2;
КонецЕсли;
КонецЦикла;
// Если общая часть совпала, меньшей считается более короткая строка
Возврат Длина1 < Длина2;
КонецФункции
Посмотрим на результат работы этой функции применительно к нашей задаче:
Результат = СтрокаМеньшеПоКодам(".", "*");
// Функция вернет Ложь, так как КодСимвола(".") = 46, а КодСимвола("*") = 42
Рассмотрим альтернативный способ, который подходит для сопоставления строк без явных циклов по каждому символу. Для этого переведем строки в двоичные данные с фиксированной кодировкой UTF-16LE, а затем получим шестнадцатеричную строку:
Функция ПолучитьHexСтроки(Знач ВходнаяСтрока)
Двоичные = ПолучитьДвоичныеДанныеИзСтроки(ВходнаяСтрока, "UTF-16LE", Ложь);
Возврат ВРег(ПолучитьHexСтрокуИзДвоичныхДанных(Двоичные));
КонецФункции
Шестнадцатеричное представление байтов состоит исключительно из цифр 0-9 и латинских букв A-F. Для таких нормализованных строк одинаковой разрядности стандартное сравнение строк полностью совпадает с фактическим порядком байтов в памяти компьютера.