К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как разделить строку на символы в 1С

Как разделить строку на символы в 1С: перебор через Сред и СтрДлина, функция СтрРазделить, работа с кириллицей и спецсимволами. Примеры кода и типичные ошибки.

Задача разбить строку на отдельные символы возникает в 1С чаще, чем кажется: посимвольная проверка введённых данных, поиск недопустимых знаков в номенклатуре, разбор штрихкода, проверка ИНН или подготовка строки к посимвольному сравнению. Встроенный язык 1С не имеет функции, которая одной командой возвращает массив символов, поэтому разработчику нужно знать несколько рабочих приёмов.

Основной инструмент — связка функций СтрДлина() и Сред(): первая возвращает длину строки, вторая извлекает подстроку по позиции. Дополнительно в платформе 8.3.6 и новее доступна функция СтрРазделить(), которая умеет раскладывать строку в массив, а в новых версиях — работать и посимвольно. Каждый способ имеет свои ограничения, и выбор зависит от версии платформы и задачи.

Ниже разобраны практические варианты с готовым кодом, особенности работы с кириллицей и переносами строк, типичные ошибки и способы проверить результат. Все примеры можно вставить в модуль общего назначения или внешнюю обработку и выполнить без доработки конфигурации.

Классический способ: цикл со Сред() и СтрДлина()

Метод работает на любой версии платформы 1С:Предприятие 8 и потому считается базовым. Идея проста: узнаём длину строки, затем в цикле извлекаем по одному символу и складываем их в массив. Нумерация символов в 1С начинается с единицы, а не с нуля — это важно для тех, кто пришёл из других языков.

Функция РазделитьСтрокуНаСимволы(ИсходнаяСтрока) Экспорт

МассивСимволов = Новый Массив;

ДлинаСтроки = СтрДлина(ИсходнаяСтрока);

Для Позиция = 1 По ДлинаСтроки Цикл

ТекущийСимвол = Сред(ИсходнаяСтрока, Позиция, 1);

МассивСимволов.Добавить(ТекущийСимвол);

КонецЦикла;

Возврат МассивСимволов;

КонецФункции

Вызов выглядит так: Результат = РазделитьСтрокуНаСимволы("Привет"); — в массиве окажется шесть элементов: «П», «р», «и», «в», «е», «т». Функция Сред() принимает три параметра: исходную строку, начальную позицию и количество символов. Если третий параметр опустить, будет возвращена строка от указанной позиции до конца, поэтому для посимвольного разбора единицу указывать обязательно.

Если третий параметр не нужен, аналогичную роль выполняют функции Лев() и Прав(), но для перебора по позиции удобнее именно Сред() — она не требует вычислять смещение от краёв строки.

Порядок действий
  1. 1
    Создайте пустой массив для результата
  2. 2
    Получите длину строки через СтрДлина()
  3. 3
    Организуйте цикл от 1 до длины строки
  4. 4
    Внутри цикла извлекайте символ через Сред(Строка, Позиция, 1)
  5. 5
    Добавляйте символ в массив и верните его из функции

Разбор строки через СтрРазделить()

Начиная с платформы 8.3.6 доступна функция СтрРазделить(), которая разбивает строку по разделителю и возвращает массив подстрок. Если передать в качестве разделителя пустую строку, в новых версиях платформы строка раскладывается именно на символы — это самый короткий путь к результату.

МассивСимволов = СтрРазделить("Привет", "");

// Результат: массив из 6 элементов, по одному символу в каждом

Однако поведение с пустым разделителем зависит от версии платформы и режима совместимости конфигурации. Перед использованием приёма в рабочем коде проверьте результат на тестовой строке: в части версий пустой разделитель трактуется иначе, и вместо массива символов можно получить массив из одного элемента — исходной строки целиком.

Если версия платформы неизвестна или конфигурация должна работать на разных релизах, надёжнее использовать цикл со Сред() — он предсказуем везде. СтрРазделить() удобна, когда строку нужно разбить по конкретному разделителю: запятой, точке с запятой, переводу строки.

Особенности кириллицы, пробелов и спецсимволов

В 1С строки хранятся в Unicode, поэтому СтрДлина() и Сред() корректно работают с кириллицей, латиницей, цифрами и большинством знаков без каких-либо перекодировок. Русская буква занимает одну позицию, как и латинская — смещений и «двойных байтов», знакомых по низкоуровневым языкам, здесь нет.

Тонкости начинаются со служебных символов. Символы переноса строки (Символы.ПС, Символы.ВК), табуляции и неразрывные пробелы тоже являются символами строки и попадут в массив. Если строка пришла из многострочного текстового поля или файла, в результате могут оказаться «невидимые» элементы, которые ломают дальнейшую логику сравнения.

Перед разбором часто имеет смысл очистить строку: СокрЛП() уберёт краевые пробелы и служебные символы по краям, а СтрЗаменить() поможет удалить или заменить переносы строк внутри. Проверить, что именно попало в массив, можно через КодСимвола() — функция вернёт числовой код, по которому легко отличить обычный пробел от неразрывного.

Контрольные точки

Как проверить результат

Количество элементов массива
Норма

Равно СтрДлина() исходной строки

Тревожный признак

Меньше или больше — возможны пропуски или лишние служебные символы

Содержимое элементов
Норма

Каждый элемент — ровно один видимый символ

Тревожный признак

Пустые строки или нечитаемые знаки — в исходной строке переносы или неразрывные пробелы

Кириллица
Норма

Русские буквы извлекаются целиком, без замены знаками вопроса

Тревожный признак

Символы искажены — проблема с кодировкой источника данных, а не с разбором

Посимвольный анализ: проверка и фильтрация

На практике разделить строку на символы чаще всего нужно не ради самого массива, а для проверки каждого знака: допустим ли он, является ли цифрой, входит ли в заданный алфавит. В этом случае массив можно не строить вовсе — достаточно анализировать символ прямо в цикле.

Функция ТолькоЦифры(ИсходнаяСтрока) Экспорт

Допустимые = "0123456789";

Для Позиция = 1 По СтрДлина(ИсходнаяСтрока) Цикл

ТекущийСимвол = Сред(ИсходнаяСтрока, Позиция, 1);

Если СтрНайти(Допустимые, ТекущийСимвол) = 0 Тогда

Возврат Ложь;

КонецЕсли;

КонецЦикла;

Возврат Истина;

КонецФункции

Такой подход экономит память на длинных строках и позволяет прервать проверку при первом недопустимом символе. Для сбора «очищенной» строки вместо массива удобно накапливать результат конкатенацией: Результат = Результат + ТекущийСимвол; — добавляя только прошедшие проверку знаки.

Учтите, что СтрНайти() в 1С нечувствительна к регистру при сравнении букв — если регистр важен (например, при разборе паролей или кодов), сравнивайте символы напрямую через оператор равенства или используйте КодСимвола().

Типичные ошибки
01
Начало цикла с нуля вместо единицы — первый символ теряется, а Сред(Строка, 0, 1) даёт неожиданный результат
02
Использование СтрДлина() на строке с незаполненным значением Неопределено — возникает ошибка; сначала приведите значение к строке
03
Накопление результата через конкатенацию в цикле на очень длинных строках — заметное падение производительности
04
Игнорирование переносов строк и неразрывных пробелов — в массиве появляются невидимые элементы, ломающие сравнение

Производительность на длинных строках

Для строк разумной длины — до нескольких тысяч символов — разница между способами незаметна, и выбирать стоит по удобству чтения кода. Проблемы начинаются на строках в десятки и сотни тысяч символов: посимвольная конкатенация в цикле становится узким местом, потому что при каждом сложении строк создаётся новый объект.

Если нужно собрать из символов новую строку, эффективнее складывать символы в массив, а затем объединить их одной операцией СтрСоединить(МассивСимволов, ""). Это заметно быстрее, чем тысячи операций Результат = Результат + Символ.

Также проверьте, действительно ли нужен полный посимвольный разбор. Часто задачу решают встроенные функции без цикла: СтрЧислоВхождений() для подсчёта вхождений, СтрЗаменить() для удаления нежелательных знаков, СтрНайти() для поиска позиции. Они выполняются на уровне платформы и работают быстрее интерпретируемого цикла.

Сравнение вариантов

Цикл со Сред() и СтрДлина()

Работает на любой версии платформы, предсказуем, позволяет анализировать символ на лету. Минус — больше кода

СтрРазделить с пустым разделителем

Одна строка кода, но поведение зависит от версии платформы и режима совместимости — требует проверки

СтрЗаменить / СтрНайти без цикла

Самый быстрый вариант, если задача сводится к поиску или удалению символов, а не к полному разбору

Проверка результата и отладка

Самый быстрый способ убедиться, что разбор сработал, — вывести результат через Сообщить() в цикле или посмотреть массив в отладчике. В отладчике конфигуратора массив раскрывается по элементам, и видно каждый символ, его индекс и фактическое содержимое, включая непечатаемые знаки.

Для контроля «невидимых» символов полезен приём с выводом кодов:

Для Каждого Элемент Из МассивСимволов Цикл

Сообщить("'" + Элемент + "' — код " + КодСимвола(Элемент));

КонецЦикла;

Коды позволяют точно идентифицировать символ: обычный пробел, неразрывный пробел, табуляция и перенос строки имеют разные коды, хотя визуально в сообщении могут выглядеть одинаково пусто. Это первое, что стоит проверить, если сравнение строк «на глаз одинаковых» возвращает Ложь.

Итог

Что важно запомнить

Базовый способ разделить строку на символы в 1С — цикл со СтрДлина() и Сред(Строка, Позиция, 1). СтрРазделить() с пустым разделителем короче, но зависит от версии платформы. Перед разбором очищайте строку от служебных символов, а для длинных строк избегайте посимвольной конкатенации — собирайте результат через массив и СтрСоединить().

Частые вопросы

Можно ли разделить строку на символы без цикла?

Да, в платформе 8.3.6 и новее — через СтрРазделить(Строка, ""), который в актуальных версиях раскладывает строку посимвольно. Однако поведение зависит от режима совместимости, поэтому для кода, работающего на разных релизах, надёжнее цикл со Сред().

Почему Сред(Строка, 0, 1) не возвращает первый символ?

В 1С нумерация символов строки начинается с единицы. Позиция 0 ведёт себя неочевидно и является частой причиной пропуска первого символа у разработчиков, привыкших к языкам с нумерацией от нуля.

Как разделить строку, если в ней есть переносы строк?

Переносы — обычные символы и попадут в массив. Если они не нужны, удалите их заранее: СтрЗаменить с Символы.ПС и Символы.ВК, либо обработайте строку через СокрЛП(), если служебные символы находятся только по краям.

Как проверить, состоит ли строка только из цифр?

Пройдите по символам циклом и для каждого проверьте вхождение в строку "0123456789" через СтрНайти(). Если хотя бы один символ не найден — строка содержит нецифровые знаки. Для ИНН и подобных кодов дополнительно проверяйте длину.

Что делать, если кириллица превращается в знаки вопроса?

Проблема не в разборе, а в кодировке источника: так бывает при чтении файлов в неверной кодировке. Укажите правильную кодировку в объекте ЧтениеТекста (например, КодировкаТекста.UTF8) — после корректного чтения Сред() и СтрДлина() отработают с русскими буквами штатно.

Что быстрее: цикл со Сред() или СтрРазделить()?

СтрРазделить() выполняется на уровне платформы и на длинных строках быстрее интерпретируемого цикла. На коротких строках разница незаметна, поэтому выбирайте по критерию совместимости с версией платформы и читаемости кода.