PDA

Просмотр полной версии : Работа с массивами



Андрей007
14.12.2015, 14:50
Не смог быстро найти на форуме имеющиеся статьи по данному вопросу, поэтому пишу.
Подскажите, как можно сравнить значения массивов, не прибегая к помощи, написанным с помощью циклов ФБ?
Надеюсь вопрос понятен.

Вольд
14.12.2015, 15:03
Не смог быстро найти на форуме имеющиеся статьи по данному вопросу, поэтому пишу.
Подскажите, как можно сравнить значения массивов, не прибегая к помощи, написанным с помощью циклов ФБ?
Надеюсь вопрос понятен.

Кто ясно мыслит, тот ясно излагает и наоборот ? У тебя, по моему, наоборот.

Валенок
14.12.2015, 16:04
if sysmemcmp(adr(массив1),adr(массив2),sizeof(массив1 )) <> 0 then ... //не равны

Андрей007
14.12.2015, 16:07
Я больше всего на этом форуме не понимаю подобное трепло, вроде Вольда.
Если есть, что написать по вопросу пиши, а нет иди трепись с подобными себе "наоборотами".

Я же написал, что не используя циклы.
Я знаю как при их помощи это сделать, не недавно натолкнулся на интересные примеры с использованием POINTER TO ARRAY,
но не очень понял логику их работы, вот и решил послушать кто, что может подсказать.

Андрей007
14.12.2015, 16:08
if sysmemcmp(adr(массив1),adr(массив2),sizeof(массив1 )) <> 0 then ... //не равны
А это какая библеотека?
Или это встроенная функция?

Андрей007
14.12.2015, 16:17
Данная функция сравнивает их размеры а не данные.
Я имел ввиду не равенство данных внутри массива.

petera
14.12.2015, 16:47
Данная функция сравнивает их размеры а не данные.
Я имел ввиду не равенство данных внутри массива.
Именно проверяет равенство данных внутри массивов
21319
Для сравнения длины массивов достаточно было бы просто сравнить их длину sizeof(массив1 ) и sizeof(массив2 )

Андрей007
14.12.2015, 16:59
Благодарю за ответ.
Всё работает. Спасибо.

Yegor
03.01.2016, 16:30
массив заполненный не с начала и не до концаЯ долго пытался распарсить эту формулировку. Имеется в виду массив с ненулевой нижней границей? Но тогда что значит «не до конца»? Массивы всегда заполнены целиком по определению.

Может, требуется определить A и B из arr: ARRAY[A..B] OF T? Но в языках 61131-3, во-первых, нет интроспекции; а во-вторых, A и B уже известны в любом контексте на этапе компиляции. Если проблема в том, что приходится указывать A и B несколько раз, сделайте их VAR CONSTANT.

lara197a
03.01.2016, 18:59
Обнуляем некую переменную и переменную номер в структуре.
Циклически проверяем наличие в х,y,z нуля.
Если есть, увеличиваем некую переменную на один.
примерно так:

n:=0;
cn:=0;
FOR cN:= 0 TO 999 DO (*начинаем поиск*)
IF ARX[cN].Х=0 AND
ARX[cN].Y AND
ARX[cN].Z=0 THEN (*Если нашли,то*)
n:=N+1;
END_IF
cn:=cN+1;
END_FOR

Yegor
03.01.2016, 19:39
Советую по возможности заранее считать данные при поступлении или удалении их из массива. Можно сэкономить уйму процессорного времени, т.к. не придётся проходить весь массив.

goldenlife
01.05.2025, 12:40
Дбрг-Дня. По массивам. Допустим есть массив из REAL-переменных и есть массив из WORD-переменных. Нужно сравнить каждую переменную массива с "нулём" (или другим значением, больше/меньше/равно) и установить контрольный бит в TRUE.
У меня набор параметров из 10 real и 9 word, а их, !каждого!, нужно проверить и перечислять каждый параметр ... ну слишком большая строчка в ST получается =)))
Я запутался как это сделать, - подскажите! Спасибо!

МихаилГл
01.05.2025, 12:46
For i:= 1 to 10 do
If Aaa[i]....
Next i

Как то так, вернее в конце end-for, не помню

melky
01.05.2025, 13:04
Контрольный бит один для всех, или у каждой переменной ? если общий, то выйти можно и раньше.

goldenlife
01.05.2025, 21:03
Контрольный бит один для всех, или у каждой переменной ? если общий, то выйти можно и раньше.

VAR
i: INT :=0;
start: BOOL;
stop: BOOL;
rParam_: ARRAY [1..6] OF REAL := 2.2, 3.2, 2.5, 3.4, 6.7, 0.21;
END_VAR
-------------------------------
IF (start = TRUE) THEN
FOR i:=1 TO 6 DO
IF (rParam_[i] = 0.00) THEN
stop := TRUE;
ELSE
stop := FALSE;
END_IF
END_FOR
END_IF

Я шото накинул, но ... не пойму, нужно ли i сбрасывать перед последним END_IF? В таком случае (как сейчас) у меня мой stop всегда FALSE, и неважно какое значение rParam_, хоть нули, хоть троечку...
а симулятор показывает, что после одного "прохода", i-шка становится равная 7, и в следующий забег со start она всё равно равна 7... знач там нужно видимо её обнулять...
и мне бы так, чтоб проверка проводилась каждый цикл выполнения POU, а не с бита start.

kondor3000
01.05.2025, 21:21
Я шото накинул, но ... не пойму, нужно ли i сбрасывать перед последним END_IF? В таком случае (как сейчас) у меня мой stop всегда FALSE, и неважно какое значение rParam_, хоть нули, хоть троечку...
а симулятор показывает, что после одного "прохода", i-шка становится равная 7, и в следующий забег со start она всё равно равна 7... знач там нужно видимо её обнулять...
и мне бы так, чтоб проверка проводилась каждый цикл выполнения POU, а не с бита start.


RETURN ; допишите и будет выход из цикла, после определения 0 83605 на скрине i =3, так как 3 переменная в массиве равна 0
i сбрасывать не надо, она сама проходит каждый цикл от 1 до 6, если нет переменной с нулём, i =7

goldenlife
01.05.2025, 21:39
RETURN ; допишите и будет выход из цикла, после определения 0 83605 на скрине i =3, так как 3 переменная в массиве равна 0
i сбрасывать не надо, она сама проходит каждый цикл от 1 до 6

Шагаем дальше...

Если сделать так:

IF (start=TRUE) THEN
int1:= int1 + 1;

END_IF
FOR i:=1 TO 6 DO
IF (rParam_[i] = 0.00) THEN
stop := TRUE;
RETURN;
ELSE
stop := FALSE;
END_IF
END_FOR

IF (start=TRUE) THEN
int2:= int2 + 1;
END_IF

Выходит так, что если сделать в таком ключе, и проверка не происходит, т.е. STOP = FALSE, то и int2 плюсует нормально, а как только проверка rParam_ завершилась и нашлись нули где-то в массиве, то int2 останавливается и не считает как положено, и всё это изза ReTurn-а , который стоит в середине и отправляет обратно в начало... а если Return поставить в сааамый конец, то никакой реакции на нули в массиве =( кхе.

kondor3000
01.05.2025, 22:07
А можно так


IF start THEN
FOR i:=1 TO 6 DO
IF (rParam_[i] = 0) THEN
stop := TRUE;
int2:= int2 + 1; stop:= FALSE; start:= FALSE;
RETURN;
ELSE
stop := FALSE;
END_IF
END_FOR
END_IF

goldenlife
01.05.2025, 22:09
stop := stop OR (FALSE или TRUE);
Наверное так начнет получаться

в какое место его вкрячивать?

int = int +1 - это я для наглядности сделал, т.к. проверку массива хочу поставить в середине кода, а то что "ДО" или "ПОСЛЕ" проверки должно работать, т.е. эти плюсования в int.

goldenlife
01.05.2025, 22:10
А можно так


IF start THEN
FOR i:=1 TO 6 DO
IF (rParam_[i] = 0) THEN
stop := TRUE;
int2:= int2 + 1; stop:= FALSE; start:= FALSE;
RETURN;
ELSE
stop := FALSE;
END_IF
END_FOR
END_IF


избавляемся от START-а , эту проверку в середину кода хочу вложить...

МихаилГл
02.05.2025, 02:32
Я делаю интересней. Правда я так вид аварии определяю, и основной стоп...


stop:=false
for i:=1 to 6 do
alarm[i]:= false
if alfa[i]=0 then
alarm[i]:=true
stop:=true
end_if
end_for
... Тут далее этот stop обрабатываем, иначе он может потеряться, т.к. всегда вначале обнуляется.


Ретурн не делаю...
В массиве алармов видно, на какой переменной нулевые значения, при чем на всех, а не на первой, если применять ретурн.
А стоп один общий, если хотя бы один ноль есть...

melky
02.05.2025, 11:12
Ретурн служит для проверки на ИЛИ. Какой смысл ползать дальше по массиву, если выход один и проверяем ИЛИ?
если надо И, то там должно пройти по всем элементам цикла.
Хотя и при И в определенных случаях можно выйти раньше.

МихаилГл
02.05.2025, 11:39
Просто мне надо видеть все аварии, а не первую из списка.

kondor3000
02.05.2025, 11:53
Тогда уж так, и все аварии и Стоп


stop:=FALSE;
FOR i:=1 TO 6 DO
alarm[i]:= rParam_[i] =0 ;
stop := stop OR alarm[i];
END_FOR

МихаилГл
02.05.2025, 11:56
Можно и так

goldenlife
02.05.2025, 21:41
https://owen.ru/forum/showthread.php?t=22902&p=463322&viewfull=1#post463322
Ну так всё же? как тут быть?
Есть код, его достаточно, и где-то в середине (пришлось так сделать), что идёт проверка на ненулевые значения "настроек" и если нулевое попадается, то включается БИТ и он сенсорной панели говорит, что "высвети окно с настройками" и пусть оператор задаст ненулевые параметры, т.к. с нулевыми "система" не поедет... Так вот пока оператор не задаст всё правильно, то бит и останется включенным, ну а всё остальное (код) пусть работает - зачем его тормозить-то?
Выходит, что лучшим способом будет "запихнуть эту проверку" в функциональный блок и, по ходу цикла, входить и проверять на "ненулевые" значения и зажигать бит (или не зажигать)... но а в таком случае получится выйти из этого ФБ и продолжить выполнять POU - тут я еще не пробовал... а может уже кто-то попробовал так?

kondor3000
02.05.2025, 21:48
https://owen.ru/forum/showthread.php?t=22902&p=463322&viewfull=1#post463322
Ну так всё же? как тут быть?
Есть код, его достаточно, и где-то в середине (пришлось так сделать), что идёт проверка на ненулевые значения "настроек" и если нулевое попадается, то включается БИТ и он сенсорной панели говорит, что "высвети окно с настройками" и пусть оператор задаст ненулевые параметры, т.к. с нулевыми "система" не поедет... Так вот пока оператор не задаст всё правильно, то бит и останется включенным, ну а всё остальное (код) пусть работает - зачем его тормозить-то?
Выходит, что лучшим способом будет "запихнуть эту проверку" в функциональный блок и, по ходу цикла, входить и проверять на "ненулевые" значения и зажигать бит (или не зажигать)... но а в таком случае получится выйти из этого ФБ и продолжить выполнять POU - тут я еще не пробовал... а может уже кто-то попробовал так?

Без RETURN; вы можете взять любой последний код (сегодня 2 варианта уже дали) и использовать в середине программы. 83608
Программа не остановится, хоть в ФБ, хоть где вставьте. Переменная stop будет активна и массив бит (аварий) покажет где нули есть.
С разными переменными можно проверить все массивы на 0, после исправления массивов, переменные (типа stop и массивы аварий) сбросятся сами.

goldenlife
02.05.2025, 22:17
Тогда уж так, и все аварии и Стоп


stop:=FALSE;
FOR i:=1 TO 6 DO
alarm[i]:= rParam_[i] =0 ;
stop := stop OR alarm[i];
END_FOR


Извините, но встал в ступор =))) меня чуть синтаксис вводит в заблуждение этих двух строчек (я только вступаю в ST) и нужно много читать/пробовать, а тут прям очень-новенькое:

alarm[i]:= rParam_[i] =0; => если рассуждать,- то в массив alarm[i] (который булевый) запишется что??? не понимаю=( ведь в rParam_[i] находятся значения REAL...
stop := stop OR alarm[i]; => в бит stop будет записываться он же, или нули из массива alarm[i], если они там находятся, т.е. он будет всегда FALSE пока в массиве alarm[i] будут нули, а если в массиве будет ненулевое значение, то он станет TRUE ... так?

обновление:
alarm[i]:= rParam_[i] =0; = это проверка! если rParam_[i] =0 не выполняется, то возвращает TRUE, а если выполняется то возвращает FALSE, т.е. в alarm[i] будет возвращаться результат проверки.
.
Откланялся =)
пошел дальше изучать... где нибудь бы литературу правильную взять/найти по ST =)) а лучше что-то типо видеоуроков.

kondor3000
02.05.2025, 22:38
Извините, но встал в ступор =))) меня чуть синтаксис вводит в заблуждение этих двух строчек (я только вступаю в ST) и нужно много читать/пробовать, а тут прям очень-новенькое:
alarm[i]:= rParam_[i] =0; = это проверка! если rParam_[i] =0 не выполняется, то возвращает TRUE, а если выполняется то возвращает FALSE, т.е. в alarm[i] будет возвращаться результат проверки.
.
Откланялся =)
пошел дальше изучать... где нибудь бы литературу правильную взять/найти по ST =)) а лучше что-то типо видеоуроков.

Выше скрин с работой, проверка в 2 массивах.
ST изучают только основы, далее применение на примерах.

1exan
03.05.2025, 07:16
Извините, но встал в ступор =)))...
Откланялся =)
пошел дальше изучать... где-нибудь бы литературу правильную взять/найти по ST =)) а лучше что-то типо видеоуроков.

Технологию и алгоритмы программирования можете изучать практически на любом языке (например на си).
Конкретно для ST достаточно изучить его операторы и синтаксис - в справке на тот-же кодесис достаточно много описаний, даже с небольшими примерами.
Вот завалялась ещё брошюрка

МихаилГл
03.05.2025, 08:24
https://owen.ru/product/codesys_v3/documentation
https://owen.ru/uploads/373/cds23_manual_v2.8.pdf

В руководстве по версии 3.5 описание языка более наглядно представлено.

Валенок
05.05.2025, 12:28
...есть массив из REAL-переменных и есть массив из WORD-переменных. Нужно сравнить каждую переменную массива с "нулём" (или другим значением) и установить контрольный бит в TRUE. ...У меня набор параметров из 10 real и 9 word...

var
x,check_x: array[1..10] of real := 10("нулём" или другим значением); //юзается x[] и w[]
w,check_w: array[1..9] of word := 9("нулём" или другим значением);
контрольный бит: boolean;
end_var
--------
контрольный бит := sysmemcmp(adr(x),adr(check_x),sizeof(x)) = 0 and sysmemcmp(adr(w),adr(check_w),sizeof(w)) = 0;

goldenlife
06.05.2025, 20:44
var
x,check_x: array[1..10] of real := 10; ("нулём" или другим значением); //юзается x[] и w[]
w,check_w: array[1..9] of word := 9; ("нулём" или другим значением);
control : bool;
end_var
--------
control := sysmemcmp(adr(x),adr(check_x),sizeof(x)) = 0 and sysmemcmp(adr(w),adr(check_w),sizeof(w)) = 0;

Даже если соблюсти весь синтаксис, то Codesys 2.3 пишет что:
1. Ошибка 4001 - Идентификатор SYSMEMCMP не определён.
2. Ошибка 4250 - Требуется "ST" - выражение или окончание POU.

kondor3000
07.05.2025, 00:19
Даже если соблюсти весь синтаксис, то Codesys 2.3 пишет что:
1. Ошибка 4001 - Идентификатор SYSMEMCMP не определён.
2. Ошибка 4250 - Требуется "ST" - выражение или окончание POU.

Надо добавить биб-ку SisLibMem.lib и работать будет только в живом ПЛК, в эмуляции не работает,
в работе измените любую переменную массива на 0.

var
x, check_x: array[1..10] of real := 10(15.3); (* массив основной и копия, 10 переменных массива равны 15,3 *)
w, check_w: array[1..9] of word := 9(45); (* массив основной и копия, 9 переменных массива равны 45 *)
control : bool;
end_var
--------
control :=NOT (SysMemCmp(ADR(x),ADR(check_x),SIZEOF(x))=0 AND SysMemCmp(ADR(w),ADR(check_w),SIZEOF(w))=0) ;