Pawn. Операторы

Операторы — это команды языка программирования, которые выполняют последовательность инструкций.

Операторы присваивания

Все операторы присваивания идентичны с операторами присваивания языка C.

x = a; // присвоит переменной x значение переменной a
x = a + b; // присвоит переменной x сумму значений переменных a и b
x = a - b; // присвоит переменной x разность значений переменных a и b
x = a * b; // присвоит переменной x произведение значений переменных a и b
x = a / b; // присвоит переменной x деление значений переменных a на b
x = a % b; // присвоит переменной x остаток от деления значения переменной a на b

Все эти операторы имеют сокращённый синтаксис(этот синтаксис транслируется на уровне компиляции и на скорость выполнения кода никак не влияет), выглядит он следующим образом:

x += a; // присвоит переменной x сумму значений переменных x и a, идентично x = x + a
x -= a; // присвоит переменной x разность значений переменных x и a, идентично x = x - a

и так далее.
Существуют ещё побитовые операторы, о которых рассказано в одной из следующих статей.

Операторы инкремента/декремента

Оператор инкремента(++) увеличивает его операнд(переменную, к которой он применён) на единицу, а оператор декремента(−−) уменьшает его операнд(переменную, к которой он применён) на единицу.
Эти операторы могут быть применены двумя способами:
1. Префиксный
2. Постфиксный
В случае префиксного способа, комбинация инкремента и операнда будет возвращать значение до увеличения или уменьшения. В случае постфиксного способа, всё будет в точности наоборот.
Пример:

x++; // (можно и так: ++x;)увеличим значение переменной x на 1, идентично x = x + 1
x--; // (можно и так: --x;)уменьшим значение переменной x на 1, идентично x = x - 1
x = y++; // присвоит переменной x значение переменной y, затем увеличит значение переменной y на 1.
x = --y; // уменьшит значение переменной y на 1, затем присвоит переменной x значение переменной y(уже уменьшенное).

Оператор выражения

В языке Pawn операторы выражения сходны с языком C:
&& — И
|| — ИЛИ
! — НЕ

Оператор if/else:

if — при дословном переводе означает ‘если’
else — иначе
Для сравнения используются следующие знаки:
> — больше
< — меньше
>= — больше либо равно
<= — меньше либо равно
== — равно
!= — не равно

Пример:

new x = 5, y = 8;
if (x > 5) // дословно: если x больше 5, то
{
	print("x > 5");
}
else // иначе, то есть если x меньше либо равен 5, то
{
	print("x <= 5");
}
// результатом выполнения будет: x <= 5

Теперь сделаем условие по сложнее, с использованием операторов выражения:

new x = 5, y = 8, z = 5;
if ( (x >= 5) && !(z == y) ) // дословно: если x больше 5 и z не равен y, то
// это условие можно записать и так: if (x >= 5 && z != y)
{
	print("x >= 5");
}
else
{
	print("x <= 5");
}
new x = 5, y = 8, z = 5;
if (x >= 5 && z == y) // дословно: если x больше 5 и z равен y, то
{
	print("x >= 5");
}
else if (y >= 8) // иначе, если y больше либо равен 8
{
	print("y <= 8");
}

Примечание:

Операторы if/else имеют сокращённый синтаксис, который абсолютно идентичен языку C.
Выглядит он следующим образом:

new x, y = 5;
x = (y > 5) ? 2 : 6;
// в результате x будет равен 6.

Можно использовать например и так:

new x = 2, y = 5;
printf("%d", (y > 5 || x == 2) ? x : y);
// в результате выведет 2.

Оператор switch/case

switch/case используется для создания более удобных конструкций и быстрого выполнения условия(в некоторых случаях).

new x = random(10); // переменной x присваиваем случайное значение от 0 до 9
switch (x)
{
	case 0: print("x равно 0");
	case 1, 2: print("x равно 1 или 2");
	case 3..5: print("x в диапазоне от 3 до 5");
	case 4..8, 196: print("x в диапазоне от 4 до 8 или 196");
	default: // любое значение, не вошедшее в верхние, в данном случае это 9
	{
		printf("x равен %d", x);
	}
}
new x[1];
x[0] = 'z';
switch (x[0])
{
	case 'a': print("в x[0] символ a");
	case 'a','z': print("в x[0] символ a или z");
	case 'a'..'z': print("x[0] символы в диапазоне от a до z");
	case 'a'..'z','A'..'Z','@':
	{
		print("x[0] символы в диапазоне от a до z или от A до Z или символ @");
	}
}

Это очень удобно, код становится более наглядным, сравните сами:

new x = random(10);
if (x == 1)
	print("Ура, один");
else if (x == 2 || x == 3)
	print("Ура, два или три");
else if (x >= 4 && x <= 9)
	print("Ура, от четырех до девяти включительно");
else
	print ("Ура, нуль");

Верхний код можно заменить так:

new x = random(10);
switch (x)
{
	case 1: print("Ура, один");
	case 2,3: print("Ура, два или три");
	case 4..9: print("Ура, от четырех до девяти включительно");
	default: print("Ура, нуль");
}

Важно!
Стоить отметить, что в официальной документации к языку написано: ‘In pawn, switch is a structured “if”‘, а это значит, что конструкция switch — это набор структурированных if’ов, отсюда следует, что switch не может работать быстрее if. Однако, тесты показали следующее:

Следующая конструкция:

switch (var)
{
        case 40, 80, 150, 160, 230, 420: return 1;
}

быстрее, чем

if ( var == 40 || var == 80 || var == 150 || var == 160 || var == 230 || var == 420 ) return 1;

Следующая конструкция:

switch(var)
{
        case 40..80,150..160,230..420: return 1;
}

медленнее чем

if ( var >= 40 && var <= 80 || var >= 150 && var <= 160 || var >= 230 && var <= 420 ) return 1;

Следующая конструкция:

switch (var)
{
        case 40: return 1;
}

одинакова как и

if ( var == 40 ) return 1;

Следующая конструкция:

switch (var)
{
        case 40..50: return 1;
}

быстрее чем

if ( var >= 40 && var <= 50 ) return 1;

Как видим — switch/case медленнее(значительно) if только на больших промежутках значений.

Оператор while и do/while:

Операторы while и do/while — это циклические операторы.
Различия между while и do/while лишь в том, что do/while гарантированно выполнится один раз.

new x = random(10);
while (x != random(10)) // пока x не равен random(10) повторяй
{
	print("x != random(10)");
}
new x;
do // делай
{
	print("x != random(10)");
}
while (x != random(10)); // пока x не равен random(10)

Условия могут быть такие же как и в if

Оператор for

Оператор for имеет следующий вид:
for (действия, которые выполнятся 1 раз ; условие при котором выполняется цикл (выполняется после каждой итерации) ; какие действия будут произведены после завершения итерации)
Рассмотрим несколько примеров:

new x;
for (x = 0; x < 5; x++)// выполнится 5 раз(от 0 до 4),
// после каждой итерации к x прибавляет 1
{
	printf("x = %d", x);
}
for (new x = 5; x <= 8; x += 2)// выполнится 2 раза(5 потом 7)
// после каждой итерации к x прибавляет 2
{
	printf("x = %d",x);
}

Если не задавать условие выполнения, то цикл будет бесконечным

for (new x = 5; ; x += 2)
{
	printf("x = %d", x);
}

Циклы можно прервать оператором break; или пропустить итерацию, с помощью continue;

for (new x = 0; x < 10; x++)
{
	if (x == 5) continue;
	if (x == 8) break;
	printf("%d", x);
	// результат: 0,1,2,3,4,6,7
}

Важное замечание:
Все условия, циклы могут быть двойные, тройные и т.д.
Пример:

new x = 45, y = 1;
if (x == 45)
{
	if (y == 1)
	{
		if (x - 1 == 45 - 1)
		{
			print("Ура");//выведется в консоль
		}
	}
}
for (new i = 0; i < 10; i++)
{
	for (new j = 0; j < 5; j++)
	{
		printf("[%d][%d]", i, j);
	}
}
  • Кирилл

    Всё очень понятно и хорошо написано. Спасибо.

  • Максим

    new x;
    for(x=0;x<5;x++)// выполнится 5 раз(от 0 до 4),
    // после каждой интерации к x прибавляет 2
    {
    printf("x = %d",x);
    }

    Ziggi, к х 1 прибавляется..

    • ZiGGi

      Исправил, спасибо.

  • Mel

    new x=random(10); // переменной x присваиваем рандомное значение от 0 до 4
    switch(x)
    {
    case 0: print("x равно 0");
    case 1,2: print("x равно 1 или 2");
    case 3..5: print("x в диапазоне от 3 до 5");
    case 4..8,196: print("x в диапазоне от 4 до 8 или 196");
    default: // любое значение, не вошедшее в верхние, в данном случае это 9
    {
    printf("x равен %d",x);
    }
    }

    Почему тут значение от 0 до 4 когда указано 10?

    • Опечатка. Спасибо, исправил.

  • Chez

    case же if else based
    проведи тесты проверим

    • Добавил информацию(давненько писал её на forum.sa-mp.com) по switch/case, без чисел, но они не особо важны;)

  • Опиши условный оператор ?

    Оператор в PAWN, работает сразу с тремя операндами. Синтаксис условного оператора:

    Bugaga = (x < y) ? xD1 : xD2;

    Выражение присвоит переменной Bugaga большее значение (если x меньше — присвоит значение xD1, если x больше- присвоит значение xD2)

    • Спасибо, забыл добавить.

      • Не за что сейчас ещё кое что = )

        Операторы Присваивания

        Присваивание: x=y // означает присвоить переменной x значение переменной y

        Сложение: x += y // означает x = x + y, присвоить переменной x результат сложения x+y

        Вычитание: x -= y // означает x = x — y, присвоить переменной x результат вычитания x-y

        Умножение: x *= y // означает x = x * y , присвоить переменной x результат умножения x*y

        Деление: x /= y // означает x = x / y, присвоить переменной x результат деления x/y

        Вычисление остатка от деления: x %= y // означает x = x % y

        =) Отличный сайт и уроки, рад что есть люди которые делятся накопленным опытом, а не утоп показывают всем насколько они круты )

        • Часть я рассказал в в статье «Подробнее о переменных и массивах», но забыл рассказать обо всех, спасибо.

          • Можно ещё подробнее описать операторы перехода (break, continue, return, goto) :)

          • ну про break, continue есть, return описан в статье про функции, а goto не нужен, но сделаю

  • Инкримент (++)

    Оператор инкримент используется следующим образом: var++ или ++var

    Этот оператор увеличивает его операнд и возвращает значение. Если используемый постфикс, с оператором после операнда (например x ++), то возвращает значение перед увеличением. Если используемый префикс с оператором перед операндом (например, ++ x), то возвращает значение после увеличения.Префиксный оператор вычисляется до присваивания, постфиксный — после.

    Пример:


    y = y++; // присваивает значение перед увеличением
    x = ++x; // присваивает значение после увеличения

    Декремент (—)

    Оператор декремента используется следующим образом: var— или —var

    Этот оператор уменьшает его операнд и возвращает значение. Если используемый постфикс (например x—) то возвращает значение перед уменьшением. Если используемый префикс (например, —x), то возвращает значение после уменьшения.Префиксный оператор вычисляется до присваивания, постфиксный — после.

    Пример:

    y = y--; // присваивает значение перед вычитанием
    x = --x; // присваивает значение после вычитания

    • Точно:D

      • = ) Потом ещё много чего опишу

        • Можешь не писать описание, просто напиши о какой языковой конструкции нет информации:)

  • Павел

    помогите плиз не могу исправить ошибку, вот компиляция:
    C:\Users\ShockWave\Desktop\samp03x_svr_R2_win32\gamemodes\RealLife-RP.pwn(116) : error 036: empty statement
    Pawn compiler 3.2.3664 Copyright (c) 1997-2006, ITB CompuPhase

    1 Error.

    а вот сам код:
    stock dval(cmd[], &i)
    {
    new val[256];
    while((cmd[i] != ‘ ‘) && (i < strlen(cmd)));
    {
    format(val, 256, "%s%c", val, cmd[1]);
    i= i + 1;
    }
    return val;
    }

    • После while лишняя ;
      Эта функция — бред, вместо cmd[1] скорее всего нужно использовать cmd[i]. Да и лишнего много, вот моя замена:

      stock dval(cmd[], &start_pos)
      {
      	new end_pos = start_pos;
       
      	while (cmd[end_pos] != ' ' && cmd[end_pos] != '\0') {
      		end_pos++;
      	}
       
      	new val[256];
      	strmid(val, cmd, start_pos, end_pos);
       
      	start_pos = end_pos;
       
      	return val;
      }
Перейти к верхней панели