Описание языка С++ в AgavaSCADA/AgavaPLC
Данное описание содержит базовое руководство по созданию программ на языке С++ и их использовании в среде разработки AgavaPLC.
Скрипты создаются в операциях «Скрипт С++».
1 Основы синтаксиса
Все программы на языке С++ состоят из отдельных действий. Каждое действие заканчивается точкой с запятой:
int x; x = 1; int y = x + 2;
Для повышения удобства работы с кодом можно оставлять в нем комментарии, которые не используются при работе программы и предназначены для улучшения читаемости кода. Перед комментариями ставится «//»:
bool x = true; // bool x = false; // вторая строка не будет выполняться в программе
2 Переменные
Переменные – объекты, хранящиеся в памяти, над которыми и производятся действия в программе.
Для начала работы с переменной необходимо инициализировать ее, указав тип и имя, а затем, при необходимости, присвоить ей значение:
bool a = true; int b = 1; double c = 1.1; string d = “строка”; int f; // переменная инициализирована, значение не присвоено f = 1; // присвоение значения
Ключевое слово auto при инициализации переменной может использоваться вместо типа переменной, для автоматического присвоения типа переменной исходя из инициализируемого значения.
auto a = true; auto b = 1;
2.1 Строки
Строка – массив байтов или 16-битных слов. Обычно строки используются для хранения текста, но также могут хранить любые двоичные данные. Текст, хранящийся в строке, заключается в двойные кавычки.
При работе со строками доступны следующие функции:
Функция | Действие |
---|---|
length() | Возвращает длину строки |
resize(uint) | Устанавливает длину строки |
isEmpty() | Возвращает истину, если строка пуста, т. е. длина равна нулю |
substr(uint start = 0, int count = -1) | Возвращает строку с содержимым, начинающимся с start, и количеством байтов, заданным параметром count. Аргументы по умолчанию вернут всю строку как новую строку |
insert(uint pos, const string &in other) | Вставляет другую строку string на позиции pos в исходной строке |
erase(uint pos, int count = -1) | Удаляет количество символов count из строки, начиная с позиции pos |
findFirst(const string &in str, uint start = 0) | Находит первое вхождение значения str в строке, начиная с символа под номером start. Если вхождения не найдено, будет возвращено отрицательное значение |
findLast(const string &in str, int start = -1) | Находит последнее вхождение значения str в строке |
Пример работы с функциями для строк:
string str = “ABCDEF”; // инициализирована строка str int a = str.length(); // a равно 6 int b = str.findFirst(“CD”, 0); // b равно 2 string str1 = str.erase(1, 3); // str1 равно “AEF”
2.2 Массивы
Массив — свокупный тип данных, который позволяет получить доступ ко всем переменным одного и того же типа данных через использование одного идентификатора. Используется в том случае, если вам необходимо сгруппировать несколько элементов одного типа:
array <int> a = {2, 5, 10, 15, 20}; // инициализирован массив a с пятью элементами int x = a [0]; // x становится равен элементу массива а под номером 0 (2) int y = a [4]; // y становится равен элементу массива а под номером 4 (20) arr [3] = 11; // элемент массива а под номером 3 становится равен 11 int z = arr [3]; // z становится равен элементу массива а под номером 3 (11)
Важно помнить, что нумерация членов массива начинается с 0.
При работе с массивами доступны следующие функции:
Функция | Действие |
---|---|
length() | Возвращает длину массива |
resize(uint) | Устанавливает новую длину массива |
reverse() | Меняет порядок элементов в массиве на обратный |
insertAt(uint index, const T& in value) | Вставляет новый элемент в массив по указанному индексу |
insertLast(const T& in) | Добавляет элемент в конец массива |
removeAt(uint index) | Удаляет элемент по указанному индексу |
removeLast() | Удаляет последний элемент массива |
removeRange(uint start, uint count) | Удаляет количество элементов count, начиная с элемента номер start |
sortAsc () | Сортирует элементы в массиве в порядке возрастания |
sortDesc () | Сортирует элементы в массиве в порядке убывания |
find (const T &in) | Возвращает индекс первого элемента, который имеет то же значение, что и желаемое. Если совпадений не найдено, возвращает отрицательное значение |
Пример работы с функциями для массивов:
int main() { array<int> arr = {1,2,3}; // 1,2,3 arr.insertLast(0); // 1,2,3,0 arr.insertAt(2,4); // 1,2,4,3,0 arr.removeAt(1); // 1,4,3,0 arr.sortAsc(); // 0,1,3,4 int sum = 0; for( uint n = 0; n < arr.length(); n++ ) sum += arr[n]; return sum; }
2.3 Перечисления
Перечисление — это тип данных, где любое значение определяется как символьная константа. Оно позволяет представить семейства целочисленных констант (например, коды ошибок) в текстовом виде вместо числового. Использование перечислений помогает улучшить читаемость кода, поскольку не нужно искать в руководстве, что означает числовое значение.
Значения перечислений объявляются путем их объявления в операторе перечисления. Если для константы перечисления не указано конкретное значение, она будет принимать значение предыдущей константы плюс 1. Первая константа получит значение 0, если не указано иное.
enum Errors { NoError, // = 0 ReadError = 2, // = 2 WriteError, // = 3 } // теперь к константам перечисления можно обращаться через текстовое значение, например // int a = NoError;
2.4 Типы переменных
Доступны логические, целочисленные, строковые переменные и переменные с плавающей запятой.
Логические переменные
Тип | Мин. значение | Макс. значение |
---|---|---|
bool | false (0) | true (1) |
Целочисленные переменные
Тип | Мин. значение | Макс. значение |
---|---|---|
int8 | - 128 | 127 |
int16 | - 32 768 | 32 767 |
int | - 2 147 483 648 | 2 147 483 647 |
int64 | - 9 223 372 036 854 775 808 | 9 223 372 036 854 775 807 |
uint8 | 0 | 255 |
uint16 | 0 | 65 535 |
uint | 0 | 4 294 967 295 |
uint64 | 0 | 18 446 744 073 709 551 615 |
Переменные с плавающей запятой
Тип | Диапазон значений | Наименьшее значение |
---|---|---|
float | ± 3.402823466 e+38 | 1.175494351 e-38 |
double | ± 1.79769313486231 e+308 | 2.22507385850720 e-308 |
3 Операторы
Доступны операторы сравнения, логические, побитовые, арифметические, приращений и индексации.
3.1 Операторы сравнения
Оператор | Символ | Пример | Операция |
---|---|---|---|
Равно | == | x == y | true, если x равно y |
Не равно | != | x != y | true, если x не равно y |
Меньше | < | x < y | true, если x меньше y |
Больше | > | x > y | true, если x больше y |
Меньше или равно | <= | x <= y | true, если x меньше или равно y |
Больше или равно | >= | x >= y | true, если x больше или равно y |
3.2 Логические операторы
Оператор | Символ | Пример | Операция |
---|---|---|---|
Логическое НЕ | ! | !x | true, если x – false и false, если x – true |
Логическое И | && | x && y | true, если x и y – true, в противном случае – false |
Логическое ИЛИ | || | x || y | true, если x или y – true, в противном случае – false |
Логическое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR) | ^ | x ^ y | true, если x или y – true (но не одновременно), в противном случае – false |
3.3 Побитовые операторы
Оператор | Символ | Пример | Операция |
---|---|---|---|
Побитовое И | & | x & y | Каждый бит в x И каждый соответствующий ему бит в y |
Побитовое ИЛИ | | | x | y | Каждый бит в x ИЛИ каждый соответствующий ему бит в y |
Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR) | ^ | x ^ y | Каждый бит в x XOR с каждым соответствующим ему битом в y |
Побитовый сдвиг влево | << | x << y | Все биты в x смещаются влево на y бит |
Побитовый сдвиг вправо | >> | x >> y | Все биты в x смещаются вправо на y бит |
3.4 Арифметические операторы
Оператор | Символ | Пример | Операция |
---|---|---|---|
Сложение | + | x + y | Складываем x и y |
Вычитание | - | x – y | Вычитаем y из x |
Умножение | * | x * y | Умножаем x на y |
Деление | / | x / y | Делим x на y |
Присваивание | = | x = y | Присваиваем значение y переменной x |
Сложение с присваиванием | += | x += y | Добавляем y к x |
Вычитание с присваиванием | -= | x -= y | Вычитаем y из x |
Умножение с присваиванием | *= | x *= y | Умножаем x на y |
Деление с присваиванием | /= | x /= y | Делим x на y |
3.5 Операторы приращений
Операция инкремента увеличивает значение на 1, декремента – уменьшает на 1.
Оператор | Символ | Пример | Операция |
---|---|---|---|
Преинкремент | ++ | ++х | Инкремент х, затем вычисление х |
Предекремент | -- | --х | Декремент х, затем вычисление х |
Постинкремент | ++ | х++ | Вычисление х, затем инкремент х |
Постдекремент | -- | х-- | Вычисление х, затем декремент х |
3.6 Оператор индексации
Используется для доступа к элементу.
Оператор | Символ | Пример | Операция |
---|---|---|---|
Индексация | [ ] | arr [0] | Обращение к нулевому элементу массива arr |
4 Блоки выражений и область видимости переменных
Блоки выражений используются в условиях, циклах и функциях. При использовании вложенных блоков, блок, который содержит внутри себя другой блок, называется внешним блоком, а тот, который содержится внутри этого блока — внутренним / вложенным блок. Каждый блок заключается в фигурные скобки.
Внешние блоки не имеют доступа к переменным внутренних блоков.
{ int a; float b; { float a = 1.0; // Отменить объявление внешней переменной // но только в пределах внутреннего блока b = a; // переменные из внешних блоков все еще доступны int c; } // a снова становится целочисленной переменной, b теперь равна 1.0, c здесь недоступна }
5 Условия
5.1 Операторы if/else
Позволяют выбрать выполнение нужных действий, в зависимости от выбранного условия, указанного в скобках:
if (x == 1) { // эти действия выполнятся, если х равно 1 } else { // эти действия выполнятся, если х не равно 1 }
5.2 Условное выражение (тернарный оператор)
Более короткая запись оператора выбора if/else:
x = 1 ? y = true : y = false; // если х равно 1, тогда y равен true, иначе y равен false
5.3 Оператор switch
Является альтернативой if/else для тех случаев, когда необходимо сделать множественный выбор:
switch(x) { case 0: // эти действия выполнятся, если х равно 0 break; // каждый case всегда должен заканчивать оператором break case 1: // эти действия выполнятся, если х равно 1 break; case 2: // эти действия выполнятся, если х равно 2 break; default: // Эти действия выполнятся, если x не равен ни одному из предыдущих значений case }
6 Циклы
6.1 Цикл while
Цикл выполняется, пока условие в скобках истинно:
x = 0; while (x < 5) { // это действие будет выполняться, пока х меньше 5 x++; // при каждом выполнении цикла увеличиваем х на 1 }
6.2 Цикл do while
Цикл похож на while, но, в отличии от него, цикл в любом случае выполнится хотя бы один раз (или больше, если при последующих проверках условие будет истинно):
x = 10; do { // это действие выполнится один раз, так как условие изначально ложно } while (x < 5);
6.3 Цикл for
Цикл for обычно используется как счетчик и хорошо подходит, когда известно необходимое количество итераций. В скобках через точку с запятой указывается переменная, условие, инкремент / декремент для переменной:
for ( int x = 0; x < 5; x ++ ) { // при каждом выполнении этих действий переменная х будет увеличивать на 1 // действия будут выполняться пока х меньше 5 }
7 Функции
Функция — это последовательность действия для выполнения определенного задания. Объявление функции похоже на объявление переменной: необходимо указать тип возвращаемого значения (либо void, если функция ничего не возвращает) и название функции. После этого ставятся двойные скобки, в которых находятся аргументы функции (либо пустые скобки, если аргументы отсутствуют). Действия, выполняемые функцией, заключаются в фигурные скобки.
Любой код в операции «Скрипт С++» должен находиться в функции. При использовании нескольких функций в скрипте будет выполняться только первая, остальные должны быть вызваны из нее:
void main () { int x = 1; function (); // вызов функции, программа переходит в void function() SetNodeValueAsInt(“/Конфигурация/Станция/Сигналы/Constant2”, x); } void function () { SetNodeValueAsInt(“/Конфигурация/Станция/Сигналы/Constant2”, 5); // теперь программа возвращается обратно в void main() }
После выполнения данного скрипта значение сигнала Constant1 станет равно 5, а Constant2 равно 1.
Если переменная была объявлена в функции, то она не будет доступна за ее пределами.
7.1 Функции с параметрами
Параметр функции — это переменная, которая используется в функции, и значение которой предоставляет вызывающий функцию объект.
Параметры указываются при объявлении функции в круглых скобках:
void summ (int x, int y) // в функцию передаются параметры х = 1 и y = 2 { int z = x + y; // z равно 3 }
7.2 Возврат значения
Для передачи значения из скрипта можно указать необходимое значение в действии return, указав тип функции такой же, как у возвращаемого значения:
bool R_Output (bool x, bool y) { bool z = false; z = x && y; return z; // z передается на выход скрипта }
8 Специализированные функции
Специализированные функции среды разработки, доступные для использования в скриптах, приведены в таблицах ниже.
8.1 Функции для работы с узлами
Определение функции | Описание |
---|---|
float GetNodeValueAsFloat(string strNodePath) | Получить значение узла в виде float по заданному пути |
void SetNodeValueAsFloat(string strNodePath, float fValue) | Установить значение узла в float по заданному пути |
int GetNodeValueAsInt(string strNodePath) | Получить значение узла в виде int по заданному пути |
void SetNodeValueAsInt(string strNodePath, int iValue) | Установить значение узла в int по заданному пути |
string GetNodeValueAsString(string strNodePath) | Получить значение узла в виде string по заданному пути |
void SetNodeValueAsString(string strNodePath, string strValue) | Установить значение узла в виде string по заданному пути |
bool GetNodeValueAsBool(string strNodePath) | Получить значение узла в виде bool по заданному пути |
void SetNodeValueAsBool(string strNodePath, bool bValue) | Установить значение узла в виде bool по заданному пути |
bool NodeValueIsError(string strNodePath) | Проверка значения узла на ошибку |
void StartNode(string strNodePath) | Запуск узла по заданному пути |
void StopNode(string strNodePath) | Остановка узла по заданному пути |
8.2 Функции для работы с окнами
Определение функции | Описание |
---|---|
void CloseWindow(string strNodePath, int iDisplay) | Закрыть окно по заданному пути на выбранном дисплее |
void ShowWindow(string strNodePath, int iDisplay) | Отобразить окно по заданному пути на выбранном дисплее. Координаты - абсолютные, установленные в свойствах окна. |
8.3 Функции для работы с временем
Определение функции | Описание |
---|---|
int GetCurrentTime() | Получение текущего времени в UNIX формате (количество секунд с 01 января 1970 года) |
int GetLocalTime() | Получение текущего времени в UNIX формате (количество секунд с 01 января 1970 года) с учетом часового пояса. |
int GetHours(int iTime) | Получение текущего часа из времени в формате UNIX |
int GetMinutes(int iTime) | Получение текущих минут из времени в формате UNIX |
int GetSeconds(int iTime) | Получение текущих секунд из времени в формате UNIX |
8.4 Функции для работы с событиями
int StoreMessage(int iMessageLevel, string strMessage)
Назначение | Генерация информационного события (типа "сообщение") |
Возвращаемое значение | 0 - успешно, иначе код ошибки |
Аргументы | int iMessageLevel - уровень сообщения (0-наивысший): 0=FATAL, 1=ERROR, 2=WARNING, 3=NOTICE, 4=INFO, 5=TRACE, 6=DEBUG |
string strMessage - текст сообщения | |
Примечания | функция доступна с версии 1.2.34 |
8.5 Функции для работы со строками
string EncodeMD5(string strText)
Назначение | Кодирование строки в MD5 хэш |
Возвращаемое значение | MD5 хэш параметра |
Аргументы | string strText - исходная строка |
Примечания | функция доступна с версии 1.2.34 |
8.6 Функции для работы с файлами
8.6.1 Класс file
Класс доступен начиная с версии 1.4.5 AgavaSCADA/AgavaPLC.
8.6.1.1 Методы
int open(const string& filename, const string& mode)
Назначение | Открытие файла |
Возвращаемое значение | Результат выполнения операции |
Аргументы | const string& filename - путь до файла |
const string& mode - режим открытия файла. |
int close()
Назначение | Закрытие файла |
Возвращаемое значение | Результат выполнения операции |
Аргументы | - |
int getSize() const
bool isEndOfFile() const
string readString(uint)
string readLine()
int64 readInt(uint)
uint64 readUInt(uint)
float readFloat()
double readDouble()
int writeString(const string &in)
int writeInt(int64, uint)
int writeUInt(uint64, uint)
int writeFloat(float)
int writeDouble(double)
int getPos() const
int setPos(int)
int movePos(int)
8.6.1.2 Поля
bool mostSignificantByteFirst
9 Пример использования скрипта для решения задачи
Приведенный ниже пример демонстрирует один из вариантов решения реальной практической задачи. Для реализации необходимого алгоритма работы задействованы узлы, взаимодействующие с входами / выходами контроллера или хранящие значения, и скрипт С++.
На вход скрипта подаются значения некоего сигнала (Signal) и уставки (Constant). В том случае, если сигнал больше уставки, замыкается релейный выход (out0). Соотношение между сигналом и уставкой переводится в проценты и записывается в переменную Percent. Если это соотношение становится меньше определенного значения, то соответствующее сообщение записывается в переменную Alert.
Текст скрипта:
bool main (float signal_val, float constant_val) // функция получает значения сигнала и уставки { float ratio; // переменная, в которой будет храниться соотношение сигнала и уставки ratio = signal_val / constant_val; // вычисление соотношения
percent_write(ratio); // вызов функции записи в узлы, с передачей в нее соотношения
if ( signal_val > constant_val) { return true; // если сигнал больше уставки, на выход скрипта приходит true } else { return false; // если сигнал не больше уставки, на выход скрипта приходит false } }
void percent_write (double ratio) // функция записи в узлы { string message = "Значение в пределах нормы"; // текстовое сообщение по умолчанию double percent = ratio * 100; // вычисляется процентное соотношение if ( percent < 50 ) { message = "Значение ниже нормы!"; // если процентное соотношение меньше 50 // то текст сообщения меняется } // запись текстового сообщения в нужный узел SetNodeValueAsString("/Конфигурация/Станция/Сигналы/Alert", message); // запись процентного соотношения в нужный узел SetNodeValueAsFloat("/Конфигурация/Станция/Сигналы/Percent", percent); }
10 Приоритет операций
В выражениях первым всегда вычисляется оператор с наивысшим приоритетом. Унарные операторы имеют более высокий приоритет, чем другие операторы. Постоператоры имеют более высокий приоритет, чем преоператоры.
В этой таблице показаны доступные унарные операторы, в порядке убывания приоритета.
Символ | Операция |
---|---|
::
|
Оператор разрешения области видимости |
[]
|
Оператор индексации |
++ --
|
Постинкремент и декремент |
.
|
Доступ |
++ --
|
Преинкремент и декремент |
!
|
Логическое НЕ |
+ -
|
Унарный положительный и отрицательный |
~
|
Побитовое дополнение |
@
|
Ссылка |
Эта таблица показывает приоритет бинарных и тернарных операторов в порядке убывания.
Символ | Операция |
---|---|
**
|
Экспонента |
* / %
|
Умножить, разделить, по модулю |
+ -
|
Сложить и вычесть |
<< >> >>>
|
Сдвиг влево, сдвиг вправо и арифметический сдвиг вправо |
&
|
Битовое И |
^
|
Битовый XOR |
|
|
Битовое ИЛИ |
<= < >= >
|
Сравнение |
== != is !is xor ^^
|
Равенство, идентичность и логическое исключающее ИЛИ |
and &&
|
Логическое И |
or ||
|
Логическое ИЛИ |
?:
|
Условие |
= += -= *= /= %= **= &=
|
Присваивание и составные присваивания |
11 Зарезервированные ключевые слова
Это ключевые слова, которые зарезервированы языком. Они не могут использоваться какими-либо идентификаторами, определенными скриптом.
and
abstract auto bool break case cast catch class const continue default do |
double
else enum explicit external false final float for from funcdef function get |
if
import in inout int interface int8 int16 int32 int64 is mixin namespace |
not
null or out override private property protected return set shared super switch |
this
true try typedef uint uint8 uint16 uint32 uint64 void while xor |