Работа со списками

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

Функции обрабатывают списки через VAR_IN_OUT переменные (входы-выходы) – т.е. на вход функции подается исходный список, и на этот же вход возвращается результат его обработки. Такой подход позволяет обрабатывать списки путем прямых манипуляций с памятью ПЛК и является крайне эффективным, так как не требует копирования содержимого списков.

В рамках рассматриваемых примерах в качестве разделителя используется символ ‘&’ (ASCII-код – 16#26).

Примеры списков:

  • ‘&12&345’ – список с двумя записями (’12’ и ‘345’);

  • ‘’ – список без записей;

  • ‘&&&’ – список с тремя пустыми записями;

  • ‘&12&345&&ABC’ – список с четырьмя записями (’12’, ‘345’, пустая запись, ‘ABC’).

Номера записей отсчитываются с единицы (т.е. первая запись списка имеет номер 1).

LIST_ADD

Тип модуля: функция

Переменная

Тип

Описание

Входы

SEP

BYTE

ASCII-код символа-разделителя

INS

STRING

Добавляемая запись

Входы-выходы

LIST

STRING(LIST_LENGTH)

Список

Выходы

LIST_ADD

BOOL

Флаг завершения операции

Используемые модули

CHR_TO_STRING

Функция LIST_ADD добавляет в конец списка LIST с разделителем SEP запись INS. После выполнения операции выход функции принимает значение TRUE.

Пример

VAR (* Список с разделителем '&' (ASCII 16#26) *) List : STRING(OSCAT_BASIC.LIST_LENGTH) := '&12&345'; (* Разделитель *) Separator : BYTE := 16#26; (* '&' *) (* Добавляемая запись *) NewRecord : STRING := 'ABC'; (* Флаг завершения операции *) Done : BOOL; END_VAR (* Вызов функции LIST_ADD *) Done := OSCAT_BASIC.LIST_ADD( SEP := Separator, INS := NewRecord, LIST := List ); (* Результат: - List = '&12&345&ABC' - Done = TRUE Пояснение: - Исходный список: '&12&345' (записи '12' и '345') - Добавляем запись 'ABC' в конец - Новая запись отделяется разделителем '&' - Итоговый список: '&12&345&ABC' (записи '12', '345', 'ABC') *) END_PROGRAM

LIST_CLEAN

Тип модуля: функция

Переменная

Тип

Описание

Входы

SEP

BYTE

ASCII-код символа-разделителя

Входы-выходы

LIST

STRING(LIST_LENGTH)

Список

Выходы

LIST_CLEAN

BOOL

Флаг завершения операции

Функция LIST_CLEAN очищает список от пустых записей. После выполнения операции выход функции принимает значение TRUE.

Пример

VAR (* Список с пустыми записями *) List : STRING(OSCAT_BASIC.LIST_LENGTH) := '&12&345&&ABC'; (* Разделитель *) Separator : BYTE := 16#26; (* '&' *) (* Флаг завершения операции *) Done : BOOL; END_VAR (* Вызов функции LIST_CLEAN *) Done := OSCAT_BASIC.LIST_CLEAN( SEP := Separator, LIST := List ); (* Результат: - List = '&12&345&ABC' - Done = TRUE Пояснение: - Исходный список: '&12&345&&ABC' (4 записи: '12', '345', '', 'ABC') - Пустая запись между '&&' удаляется - Итоговый список: '&12&345&ABC' (3 записи: '12', '345', 'ABC') *) END_PROGRAM

LIST_GET

Тип модуля: функция

Переменная

Тип

Описание

Входы

SEP

BYTE

ASCII-код символа-разделителя

POS

INT

Номер читаемой записи

Входы-выходы

LIST

STRING(LIST_LENGTH)

Список

Выходы

LIST_GET

STRING(LIST_LENGTH)

Прочитанная запись

Функция LIST_GET возвращает из списка LIST с разделителем SEP запись с номером POS. Нумерация записей начинается с 1.

Пример

VAR (* Список с записями *) List : STRING(OSCAT_BASIC.LIST_LENGTH) := '&12&345&ABC&XYZ'; (* Разделитель *) Separator : BYTE := 16#26; (* '&' *) (* Номер читаемой записи *) RecordNumber : INT := 2; (* Прочитанная запись *) Record : STRING(OSCAT_BASIC.LIST_LENGTH); END_VAR (* Вызов функции LIST_GET *) Record := OSCAT_BASIC.LIST_GET( SEP := Separator, POS := RecordNumber, LIST := List ); (* Результат: Record = '345' Пояснение: - Список: '&12&345&ABC&XYZ' - Записи: 1='12', 2='345', 3='ABC', 4='XYZ' - POS = 2 → возвращается вторая запись '345' *) END_PROGRAM

LIST_INSERT

Тип модуля: функция

Переменная

Тип

Описание

Входы

SEP

BYTE

ASCII-код символа-разделителя

POS

INT

Позиция для вставки записи

INS

STRING

Добавляемая запись

Входы-выходы

LIST

STRING(LIST_LENGTH)

Список

Выходы

LIST_INSERT

BOOL

Флаг завершения операции

Используемые модули

CHR_TO_STRING

Функция LIST_INSERT добавляет в список LIST с разделителем SEP запись INS. Запись заменяет существующую запись номер POS, при этом существующая и все последующие записи смещаются. Если POS=0, то запись добавляется в начало списка (так же, как и при POS=1). Если значение POS превышает число существующих записей списка, то список дополняется пустыми записями.

После выполнения операции выход функции принимает значение TRUE.

Пример

VAR (* Список с записями *) List : STRING(OSCAT_BASIC.LIST_LENGTH) := '&12&345&ABC'; (* Разделитель *) Separator : BYTE := 16#26; (* '&' *) (* Позиция для вставки *) Position : INT := 2; (* Вставляемая запись *) NewRecord : STRING := 'NEW'; (* Флаг завершения операции *) Done : BOOL; END_VAR (* Вызов функции LIST_INSERT *) Done := OSCAT_BASIC.LIST_INSERT( SEP := Separator, POS := Position, INS := NewRecord, LIST := List ); (* Результат: - List = '&12&NEW&345&ABC' - Done = TRUE Пояснение: - Исходный список: '&12&345&ABC' (записи '12', '345', 'ABC') - Вставляем 'NEW' в позицию 2 - Запись '345' и последующие сдвигаются вправо - Итоговый список: '&12&NEW&345&ABC' *) END_PROGRAM

LIST_LEN

Тип модуля: функция

Переменная

Тип

Описание

Входы

SEP

BYTE

ASCII-код символа-разделителя

Входы-выходы

LIST

STRING(LIST_LENGTH)

Список

Выходы

LIST_LEN

INT

Число записей в списке

Функция LIST_LEN возвращает число записей в списке LIST с разделителем SEP.

Пример

VAR (* Список с записями *) List : STRING(OSCAT_BASIC.LIST_LENGTH) := '&12&345&ABC&XYZ'; (* Разделитель *) Separator : BYTE := 16#26; (* '&' *) (* Число записей в списке *) RecordCount : INT; END_VAR (* Вызов функции LIST_LEN *) RecordCount := OSCAT_BASIC.LIST_LEN( SEP := Separator, LIST := List ); (* Результат: RecordCount = 4 Пояснение: - Список: '&12&345&ABC&XYZ' - Записи: '12', '345', 'ABC', 'XYZ' - Всего 4 записи *) END_PROGRAM

LIST_NEXT

Тип модуля: ФБ

Переменная

Тип

Описание

Входы

SEP

BYTE

ASCII-код символа-разделителя

RST

BOOL

Сигнал перезапуска блока

Входы-выходы

LIST

STRING(LIST_LENGTH)

Список

Выходы

LEL

STRING(LIST_LENGTH)

Запись списка

NUL

BOOL

Флаг «прочитаны все записи»

Функциональный блок LIST_NEXT используется для чтения записей из списка LIST с разделителем SEP. При каждом последующем вызове блока на выход LEL транслируется следующая запись списка. Когда прочитаны все записи (или в списке их нет), выход NUL принимает значение TRUE. По переднему фронту на входе RST происходит перезапуск блока.

Пример

VAR     fbListNext:       OSCAT_BASIC.LIST_NEXT;     sList:            STRING(OSCAT_BASIC.LIST_LENGTH) := 's34&sAB&1122sTest';     asListElements:   ARRAY [1..10] OF STRING(OSCAT_BASIC.LIST_LENGTH);     iPos:             INT; END_VAR iPos := 0; fbListNext(LIST := sList, SEP := 16#26); WHILE NOT fbListNext.NUL AND iPos <= 10 DO     asListElements[iPos] :=    fbListNext.LEL;     fbListNext(list := sList);     iPos           := iPos + 1; END_WHILE END_PROGRAM

LIST_RETRIEVE

Тип модуля: функция

Переменная

Тип

Описание

Входы

SEP

BYTE

ASCII-код символа-разделителя

POS

INT

Номер вырезаемой записи

Входы-выходы

LIST

STRING(LIST_LENGTH)

Список

Выходы

LIST_RETRIEVE

STRING(LIST_LENGTH)

Вырезанная запись

Функция LIST_RETRIEVE вырезает из списка LIST с разделителем SEP запись с номером POS. Нумерация запись начинается с 1. Если элемент с данным номером отсутствует, то функция возвращает пустую строку. См. также функцию LIST_RETRIEVE_LAST, которая используется для вырезания последней записи списка.

Пример

VAR (* Список с записями *) List : STRING(OSCAT_BASIC.LIST_LENGTH) := '&12&345&ABC&XYZ'; (* Разделитель *) Separator : BYTE := 16#26; (* '&' *) (* Номер вырезаемой записи *) Position : INT := 2; (* Вырезанная запись *) RetrievedRecord : STRING(OSCAT_BASIC.LIST_LENGTH); END_VAR (* Вызов функции LIST_RETRIEVE *) RetrievedRecord := OSCAT_BASIC.LIST_RETRIEVE( SEP := Separator, POS := Position, LIST := List ); (* Результат: - RetrievedRecord = '345' - List = '&12&ABC&XYZ' Пояснение: - Исходный список: '&12&345&ABC&XYZ' (записи '12', '345', 'ABC', 'XYZ') - Вырезаем запись с номером 2 ('345') - Запись удаляется из списка - Итоговый список: '&12&ABC&XYZ' (записи '12', 'ABC', 'XYZ') *) END_PROGRAM

LIST_RETRIEVE_LAST

Тип модуля: функция

Переменная

Тип

Описание

Входы

SEP

BYTE

ASCII-код символа-разделителя

Входы-выходы

LIST

STRING(LIST_LENGTH)

Список

Выходы

LIST_RETRIEVE_LAST

STRING(LIST_LENGTH)

Вырезанная запись

Функция LIST_RETRIEVE_LASTвырезает из списка LIST с разделителем SEP последнюю запись. См. также функцию LIST_RETRIEVE, которая используется для вырезания заданной записи списка.

Пример

VAR (* Список с записями *) List : STRING(OSCAT_BASIC.LIST_LENGTH) := '&12&345&ABC&XYZ'; (* Разделитель *) Separator : BYTE := 16#26; (* '&' *) (* Вырезанная запись *) RetrievedRecord : STRING(OSCAT_BASIC.LIST_LENGTH); END_VAR (* Вызов функции LIST_RETRIEVE_LAST *) RetrievedRecord := OSCAT_BASIC.LIST_RETRIEVE_LAST( SEP := Separator, LIST := List ); (* Результат: - RetrievedRecord = 'XYZ' - List = '&12&345&ABC' *) END_PROGRAM