Controlando Estruturas

From SA-MP Wiki

Jump to: navigation, search


Contents

Condicionais

if

Uma instrução if verifica se algo é verdadeiro ou falso, e executa uma determinada ação.

new a = 5;
if (a == 5)
{
	 print("a é igual 5");
}

O código dentro dos parênteses após o "if" é chamado de condição, há uma série de operadores diferentes que podem ser utilizados.

Veja outro exemplo:

if (SomeFunction() != 5) //operador de "diferença"
{
	print("SomeFunction() é diferente de 5");
}

Ele irá testar o valor de retorno da função SomeFunction(), exemplo:

stock SomeFunction() {
     return 1;
}
if(SomeFunction() == 1)
{
        print("A função SomeFunction() retorna '1'");
}

Você também pode checar muitas coisas ao mesmo tempo(porém é mais lento que se chegar cada coisa em uma condicional):

new
	a = 5,
	b = 3;
if (a == 5 && b != 3)
{
	print("Não sera Imprimido!");
}
else // ou else serve como "caso contrário", ele é chamada caso a condição retorne false/0.
{    // no caso ela retornou false, pelo fato de checar se b é diferente de 3, o que não é verdade.
       print("Sera Imprimido, pois a condição retornou false/0, pois a == 5 && b == 3");

Esse exemplo acima verifica e 'a' é igual a 5 e 'b' não é igual a 3, no entanto b é 3, de modo a verificação falhar/retornar false.

new
	a = 5,
	b = 3;
if (a == 5 || b != 3)
{
	print("Sera imprimido!");
}

No exemplo acima, utilizamos o operador OR (||), ou seja, caso qualquer condição da condicional for verdadeira/true, ele irá retornar true para a condicional como um todo.

Operadores

A seguir, apresentaremos os símbolos que podem ser usados ​​em comparações e suas explicações. Alguns já foram utilizados no exemplos acima.

Operador Significado Uso
== A condição da Esquerda é igual a da Direito if (Esquerda == Direito)
!= A condição da Esquerda é diferente ao da Direita if (Esquerda != Direita)
> A condição da Esquerda é maior que a da Direita if (Left > Right)
>= A condição da Esquerda é maior ou Igual a a da Direita if (Left >= Right)
< A Condição da Esquerda é menor que a da Direita if (Left < Right)
<= A Condição da Esquerda é menor ou igual que a da Direita if (Left <= Right)
Operador Significado Uso
&& And if (Esquerda && Direita)
|| Or if (Esquerda || Direita)
 ! Not if (!Variavel)
Nor if (!(Esquerda || Direita))
Nand if (!(Esquerda && Direita))
Exclusive Or (xor, eor) - Apenas um ou outro é verdade, tanto faz if (!(Esquerda && Direita) && (Esquerda || Direita))
Not exclusive Or (nxor, neor) - ambos ou nenhum são verdadeiras if ((Esquerda && Direita) || !(Esquerda || Direita))

Parênteses

O outro aspecto principal das condições está entre parênteses, nestes controles as coisas são feitas em ordem:

new
	a = 3,
	b = 3,
	c = 1;
if (a == 5 && b == 3 || c == 1)
{
	print("Isto sera imprimido?");
}

Há duas maneiras de olhar para a afirmação acima:

if ((a == 5 && b == 3) || c == 1)

E:

if (a == 5 && (b == 3 || c == 1))

O primeiro exemplo verifica se 'a' é 5 e 'b' é 3, Caso seja falso ( em alguns ou ambos não são os seus respectivos valores) ele irá verificar se 'c' é 1. (a == 5 && b == 3) é uma condição false, então vamos substituir para melhorar o intendimento:

if (FALSE || c == 1)

Sabemos que false não pode ser verdadeiro(uma vez que não é verdadeiro pela definição), no entanto, 'c' é verdadeiro, pois 'c == 1', o que faz que a condicional como um todo seja verdadeira.

O segundo exemplo verifica se 'a' é 5, Caso for, verifica se 'b' é 3 ou 'c' é 1. (b == 3 || c == 1) é verdadeiro, as duas condições são verdadeiras, no entanto para a condição no geral seja verdadeiro, somente necessitamos que no minino um valor seja verdadeiro:

if (a == 5 && TRUE)

(a == 5) é false, porque 'a' é 3, então temos:

if (FALSE && TRUE)

Obviamente falso é falso, assim a condição não pode ser verdade, então a verificação irá falhar.

else

Else basicamente é chamado caso a condição falhar/ser falsa

new
	a = 5;
if (a == 3) // False
{
	print("Não sera imprimido");
}
else
{
	print("Isto sera Imprimido");
}

else if

Um else if será chamado somente caso a primeira condição seja falsa

new
	a = 5;
if (a == 1)
{
	print("Será chamado se 'a' for 1");
}
else if (a == 5)
{
	print("Será chamado se 'a' for 5");
}
else
{
	print("Sera chamado se 'a' for igual a outros números");
}

Você pode agrupar vários else if's:

new
	a = 4;
if (a == 1)
{
	// False
}
else if (a == 2)
{
	// False
}
else if (a == 3)
{
	// False
}
else if (a == 4)
{
	// True
}
else
{
	// False
}

Em um else if, caso a primeira condição seja verdadeira, as outras não serão chamadas:

new
	a = 5;
if (a == 5)
{
	// Sera chamado
	a = 4;
}
else if (a == 4)
{
	// nao sera chamado
}

Para contornar isto, você pode simplesmente utilizar if em vez de else if.

Ternário (?)

? e : agem basicamente como um if dentro de uma declaração

new
	a,
	b = 3;
if (b == 3)
{
	a = 5;
}
else
{
	a = 7;
}

Esse é um exemplo simples para atribuir uma variável com base em outra variável, no entanto, pode ser feito:

new
	a,
	b = 3;
a = (b == 3) ? (5) : (7);

A parte antes do '?' é o condicional, ela tem exatamente a mesma função de uma condicional normal. A parte entre o '?' e ':' é o valor a devolver se a condição for verdadeira, a outra parte é o valor a devolver se a condição é falsa. Você pode empilhá-los com varias comparações também:

new
	a,
	b = 3;
if (b == 1)
{
	a = 2;
}
else if (b == 2)
{
	a = 3;
}
else if (b == 3)
{
	a = 4;
}
else
{
	a = 5;
}

Pode ser feito:

new
	a,
	b = 3;
a = (b == 1) ? (2) : ((b == 2) ? (3) : ((b == 3) ? (4) : (5)));

Isto é semelhante a fazer:

new
	a,
	b = 3;
if (b == 1)
{
	a = 2;
}
else
{
	if (b == 2)
	{
		a = 3;
	}
	else
	{
		if (b == 3)
		{
			a = 4;
		}
		else
		{
			a = 5;
		}
	}
}

Mas eles são equivalentes (neste exemplo, pelo menos).

Loops

while ()

"while" loops do something while the condition specified is true. A condition is exactly the same format as the condition in an if statement, it is just checked repeatedly and the code done if it is true every time it is checked:

new
	a = 9;
while (a < 10)
{
	// Code in the loop
	a++;
}
// Code after the loop

That code will check if a is less than 10, if it is the code inside the braces (a++;) will be executed, thus incrementing a. When the closing brace is reached code execution jumps back to the check and does it again, this time the check will fail as a is 10 and execution will jump to after the loop. If a started out as 8 the code would be run twice etc.

for ()

A for loop is essentially a while loop compressed, a for statement has three sections, initialization, condition and finalization. As a for loop the while example above would be written:

for (new a = 9; a < 10; a++)
{
	// Code in the loop
}
// Code after the loop

Thats a simple code to loop through all players:

for(new i,a = GetMaxPlayers();i < a;i++)
{
        if(IsPlayerConnected(i))
        {
                 //do something
        }
}

Any of the conditions can be omitted simply by putting no code in them:

new
	a = 9;
for ( ; a < 10; )
{
	// Code in the loop
	a++;
}
// Code after the loop

This example makes it a little easier to show how a for loop matches up to a while loop. There are two very slight differences between the two for loops given. The first is that the second example declares a outside the for loop, this means it can be used outside the for loop, in the first example a's scope (the section of code for which a variable exists) is only inside the loop. The second difference is that the a++ in the second example is actually done slightly before the a++ in the first example, 99% of the time this doesn't make any difference, the only time it matters is when you're using continue (see below), continue will call the a++ in the first example but will skip it in the second example.

do-while

A do-while loop is a while loop where the condition comes after the code inside the loop instead of before. This means that the code inside will always be executed at least once because it is done before the check is done:

new
	a = 10;
do
{
	// Code inside the loop
	a++;
}
while (a < 10); // Note the semi-colon
// Code after the loop

If that was a standard while loop a would not be incremented as the (a < 10) check is false, but here it's incremented before the check. If a started as 9 the loop would also only be done once, 8 - twice etc.

if-goto

This is essentially what the loops above compile to, the use of goto is generally discouraged however it's interesting to see exactly what a loop is doing:

new
	a = 9;
 
loop_start:
if (a < 10)
{
	// Code in the loop
	a++;
	goto loop_start;
}
// Code after the loop

OBOE

OBOE stands for Off By One Error. This is a very common mistake where a loop runs for one too many or two few times. E.g:

new
	a = 0,
	b[10];
while (a <= sizeof (b))
{
	b[a] = 0;
}

This very simple example demonstrates one of the most common OBOEs, at first glance people may think this will loop through all the contents of b and set them to 0, however this loop will actually run 11 times and try access b[10], which doesn't exist (it would be the 11th slot in b starting from 0), thus can cause all sorts of problems. This is known as an Out Of Bounds (OOB) error.

You have to be especially careful of OBOEs when using do-while loops as they ALWAYS run at least once.

switch

switch

A switch statement is basically a structured if/else if/else system (similar to how for is a structured while). The easiest way to explain it is with an example:

new
	a = 5;
switch (a)
{
	case 1:
	{
		// Won't be called
	}
	case 2:
	{
		// Won't be called
	}
	case 5:
	{
		// Will be called
	}
	default:
	{
		// Won't be called
	}
}

This is functionally equivalent to:

new
	a = 5;
if (a == 1)
{
	// Won't be called
}
else if (a == 2)
{
	// Won't be called
}
else if (a == 5)
{
	// Will called
}
else
{
	// Won't be called
}

However it is slightly clearer to see what is going on.

An important thing to note here is the different ways in which ifs and switches are processed:

switch (SomeFunction())
{
	case 1: {}
	case 2: {}
	case 3: {}
}

That will call SomeFunction() ONCE and compare it's result 3 times.

if (SomeFunction() == 1) {}
else if (SomeFunction() == 2) {}
else if (SomeFunction() == 3) {}

That will call SomeFunction() three times, which is very inefficient, a switch is more like doing:

new
	result = SomeFunction();
if (result == 1) {}
else if (result == 2) {}
else if (result == 3) {}

For those of you who know C the PAWN switch is slightly different, the individual conditions are NOT fall-through and are bound by braces so there's no need for break statements.

case

case statements (the "case X:" parts of the switch statement) can have other options besides a single number. You can compare a value to a list of numbers (replacing fall-through in C) or even a range of values:

case 1, 2, 3, 4:

This case will trigger if the symbol being tested is 1, 2, 3, or 4, it's the same as doing:

if (bla == 1 || bla == 2 || bla == 3 || bla == 4)

but far more concise. Numbers in lists do not have to be consecutive, in fact if they are it's better to do:

case 1 .. 4:

This case will do exactly the same as above but by checking a range instead of a list, it is the same as doing:

if (bla >= 1 && bla <= 4)
new
	a = 4;
switch (a)
{
	case 1 .. 3:
	{
	}
	case 5, 8, 11:
	{
	}
	case 4:
	{
	}
	default:
	{
	}
}

default

This is the equivalent to else in if statements, it does something if all the other case statements failed.

Single line statements

goto

goto is essentially a jump, it goes to a label without question (i.e. there's no condition to need to be true). You can see an example above in the if-goto loop.

goto my_label;
 
// This section will be jumped over
 
my_label: // Labels end in a colon and are on their own line
 
// This section will be processed as normal

The use of gotos is widely discouraged due to their effect on program flow.

break

break breaks out of a loop, ending it prematurely:

for (new a = 0; a < 10; a++)
{
	if (a == 5) break;
}

This loop will go 6 times but code after the break will only be executed 5 times.

continue

continue basically skips a loop iteration

for (new a = 0; a < 3; a++)
{
	if (a == 1) continue;
	printf("a = %d", a);
}

That will give the output of:

a = 0 a = 2

The continue basically jumps to the closing brace of the loop, as hinted at above you have to be careful when using continue with some loops:

new
	a = 0;
while (a < 3)
{
	if (a == 1) continue;
	printf("a = %d", a);
	a++;
}

This looks very similar to the other example however this time the continue will skip the a++; line, so the loop will get stuck in an infinite loop as a will always be 1.

return

return stops a function and goes back to the point in code which called the function in the first place:

main()
{
	print("1");
	MyFunction(1);
	print("3");
}
 
MyFunction(num)
{
	if (num == 1)
	{
		return;
	}
	print("2");
}

That code will give an output of:

1 3

Because the print("2"); line will never be reached.

You can also use return to return a value:

main()
{
	print("1");
	if (MyFunction(1) == 27)
	{
		print("3");
	}
}
 
MyFunction(num)
{
	if (num == 1)
	{
		return 27;
	}
	print("2");
	return 0;
}

That code will give the same output as above, however note that an additional return has been added to the end of the function. The end of a function has a return implied at it, however this return has no value, you cannot return a value and not return a value from the same function so we must explicitly return a value.

The symbol you return can be a number, a variable or even another function (in which case the other function will be called, it will return a value (it MUST return a value if you use it as a return value) and that value will be returned from the first function.

You can also store return values for later use:

main()
{
	print("1");
	new
		ret = MyFunction(1);
	if (ret == 27)
	{
		print("3");
	}
}
 
MyFunction(num)
{
	if (num == 1)
	{
		return 27;
	}
	print("2");
	return 0;
}

See also: Keywords

Personal tools
Navigation
Toolbox