Skocz do zawartości

Witamy w Nieoficjalnym polskim support'cie AMX Mod X

Witamy w Nieoficjalnym polskim support'cie AMX Mod X, jak w większości społeczności internetowych musisz się zarejestrować aby móc odpowiadać lub zakładać nowe tematy, ale nie bój się to jest prosty proces w którym wymagamy minimalnych informacji.
  • Rozpoczynaj nowe tematy i odpowiedaj na inne
  • Zapisz się do tematów i for, aby otrzymywać automatyczne uaktualnienia
  • Dodawaj wydarzenia do kalendarza społecznościowego
  • Stwórz swój własny profil i zdobywaj nowych znajomych
  • Zdobywaj nowe doświadczenia

Dołączona grafika Dołączona grafika

Guest Message by DevFuse
 

Zdjęcie

Operatory w PAWNieWersja rozszerzona


  • Nie możesz napisać tematu
  • Zaloguj się, aby dodać odpowiedź
7 odpowiedzi w tym temacie

#1 GwynBleidD

    Godlike

  • Przyjaciel

Reputacja: 1 869
Godlike

  • Postów:3 066
  • Steam:steam
  • Lokalizacja:Przemyśl
Offline

Napisano 16.04.2015 16:33

*
Popularny

Już kilka artykułów o tym istnieje, jednak żadnen nie opisuje tego dokładniej. Istnieje również ładny artykuł na wikibooks, będący częścią książki o języku C (C/Operatory - Wikibooks, biblioteka wolnych podręczników) jednak opisuje on niektóre kwestie dość zawile i jest o języku C, a w PAWNie jest kilka drobnych różnic (m.in w rzutowaniu itp)
 
Wstęp
 
Ogólnie operatory możemy podzielić na 3 kategorie: dwuargumentowe, jednoargumentowe i jeszcze jeden, samotny w swojej grupie operator wyrażenia warunkowego ( ? : ) który posiada 3 argumenty.
 
Operatory dwuargumentowe przyjmują 2 argumenty, rozdzielone właśnie tym operatorem. Argumenty nazywamy odpowiednio lewym i prawym.
 
Operatory jednoargumentowe przyjmują tylko jeden argument, który powinien być określony z lewej lub z prawej strony operatora (w zależności od operatora i jego użycia).
 
Operator przypisania
 
Operator przypisania, czyli operator = służy do umieszczenia wartości znajdującej się z prawej strony w zmiennej po lewej stronie. Po prawej może znajdować się dowolne wyrażenie, po lewej musi znajdować się zmienna.
 
a = 10  // przypisze wartość 10 do zmiennej a
Umieszczenie czegokolwiek innego po jego lewej stronie poskutkuje pięknym błędem kompilacji.
 
10 = a // zwróci błąd, nie możemy przecież nic przypisać do 10, nie jest zmienną!
10 = 12 // również zwróci błąd
10 = 10 // to też jest błąd, nie ważne że 10 jest równe 10, to nie jest operator porównania
Co ciekawe, operator przypisania ZWRACA wartość. Wartością tą jest wartość prawego wyrażenia, dzięki temu możemy takiego operatora użyć kilkukrotnie w 1 instrukcji:
 
a=b=c=12 // zmiennej c przypisze wartość 12, następnie zrobi to samo dla wartości b oraz a
 
Dzięki temu możemy użyć takiego operatora w warunku if:
 
if ( x = funkcja(y) )
Wiele osób pewnie pomyśli, że powyższy kod porówna x z wartością zwróconą przez funkcję. Otóż nie zrobi tego! Przypisze on do zmiennej x wartość zwróconą przez funkcję, a następnie tą samą wartość zwróci. Tak więc jeśli funkcja zwróci true, kod wewnątrz if się wykona, jeśli zwróci false, kod się nie wykona. Nie jest ważne co do tej pory siedziało w zmiennej x, na dodatek zostanie to zastąpione nową wartością!
 
Bystre oko zauważy, że kompilator AMXX zwróci nam warning przy kompilacji tej linii. Aby kompilator uciszyć, wystarczy objąć warunek dodatkowymi nawiasami:
 
if (( x = funkcja(y) ))
Nie zmieni to działania warunku, ale poinformuje kompilator, że WIEMY co robimy i nie pomyliliśmy się używając = zamiast == w tym miejscu.
 
Operatory arytmetyczne
 
Operatory arytmetyczne wykonują proste działania arytmetyczne i zwracają ich wynik. Wszystkie operatory arytmetyczne są dwuargumentowe i zaliczamy do nich +, -, *, / oraz %. Wykonują one po kolei: dodawanie, odejmowanie, mnożenie, dzielenie (zwrócenie wyniku z dzielenia), dzielenie (zwrócenie reszty z dzielenia). Przykłady:
 
 
10 + 20 // 30
20 - 2 // 18
14 * 3 // 42
12 / 2 // 6
13 / 2 // również 6 !
13.0 / 2 // 6.5
13 % 2 // 1
 
Dodatkowemu wyjaśnieniu podlegają operatory dzielenia. Pierwszy z nich dokona dzielenia całkowitego (tj zaokrągli wynik z dzielenia do jedności w dół) jeśli po jego obu stronach znajdą się liczby typu całkowitego. Dokona jednak dokładnego dzielenia, gdy choć z jednej strony znajdzie się liczba zmiennoprzecinkowa. Drugi z operatorów dokona zawsze dzielenia całkowitego i zwróci jego resztę.
 
Operatory znaku liczby
 
Są to operatory - i + dla których podany został tylko 1 argument, po prawej stronie. Skutkiem jest zachowanie (dla +) lub zmiana na przeciwny (dla -) znak liczby. Wyobrazić sobie można to tak, jakby po lewej stronie wirtualnie stało zawsze 0 ;)
 
Operatory te można rozróżnić tylko, gdy po lewej stronie nie znajduje się nic, znajduje się inny operator lub znajduje się nawias.
 
Operatory bitowe
 
Istnieje 7 operatorów bitowych, jeden jednoargumentowy i sześć dwuargumentoych.
 
Operatorem jednoargumentowym jest ~ czyli negacja bitowa. Przyjmuje on argument po swojej PRAWEJ stronie:
 
~14 // dobrze
14~ // żle, argument musi być po prawej!
 
Operator zwraca negację bitową podanego argumentu.
 
Operatorami dwuargumentowymi są operatory &, |, ^, <<, >> oraz >>>. Trzy pierwsze z nich dla podanych argumentów zwracają odpowiednio ich koniunkcję bitową (iloczyn bitowy), ich alternatywę bitową (suma bitowa) oraz ich alternatywę rozłączną (bitową różnicę symetryczną, XOR).
 
Pozostałe trzy dokonują przesunięcia bitowego. Argument po lewej stronie jest liczbą przesuwaną, a argument po prawej oznacza o ile bitów argument po lewej zostanie przesunięty. << dokonuje przesunięcia w lewo, >> w prawo arytmetycznie, a >>> w prawo logicznie.
 
Więcej o operatorach bitowych tutaj: Operacje bitowe
 
Operatory skróconego przypisania
 
Operator skróconego przypisania jest niczym innym, jak połączeniem operatora arytmetycznego lub bitowego z operatorem przypisania. Dla operatora •:
 
a •= 10
jest równoznaczne:
 
a = a • 10
Oczywiście operator • w języku pawn nie istnieje, należy go zastąpić dowolnym operatorem arytmetycznym lub bitowym.
 
Inaczej mówiąc: operator ten wykona działanie na argumencie lewym i prawym tak jakby to miało miejsce przy zwykłym operatorze arytmetycznym lub bitowym, jednak wynik tego działania zapisze również w lewym argumencie.
 
Oznacza to, że tak jak dla operatora przypisania, zwraca on wartość przypisywaną oraz wymaga by po jego lewej stronie znajdowała się zmienna.
 
Inkrementacja i dekrementacja
 
Są to operatory ++ oraz --, są operatorami jednoargumentowymi i występują w 2ch odmianach: post i pre. Postinkrementacja i postdekrementacja następują, gdy argument zostanie podany z lewej strony. Preinkrementacja i predekrementacja gdy zostanie podany z prawej strony. Przykłady:
 
 
i++ // postinkrementacja
++i // preinkrementacja
--i // predekrementacja
i-- // postdekrementacja
 
Operatory te zwiększają (inkrementacja) lub zmniejszają (dekrementacja) wartość liczby o 1. Jako, że zapisują one wynik w zmiennej podanej jako argument, przyjmują za argument WYŁĄCZNIE zmienne. Nie mogą być to liczby ani inne wyrażenia. Post od pre różni się zwracaną wartością. Postinkrementacja zwraca wartość przed wykonaniem działania, preinkrementacja wartość po wykonaniu działania. Preinkrementacja jest bezpośrednim odpowiednikiem zapisu:
 
i += 1
Postinkrementację można zapisać inaczej tylko jako funkcję:
 
postinkrementacja(&i) {
    new j = i;
    i += 1
    return j;
}
 
Operatory logiczne
 
Zanim o samych operatorach, trochę o samych stanach logicznych. W języku pawn istnieją 2 stany logiczne: prawda i fałsz, które są swoimi wzajemnymi przeciwieństwami. Fałszem jest wszystko o wartości zero, prawdą wszystko o wartości różnej od zera! To oznacza, że prawdą jest nie tylko 1, ale też 2, 10, 2000 a nawet liczby ujemne czyli -300 lub -1!
W związku z tym, że wartości dla prawdy jest de facto nieskończenie wiele (właściwie to skończenie, ale i tak mnóstwo), przyjęło się że każdy operator logiczny będzie zwracał 1 jako prawdę logiczną. Zważmy jednak na to, że nadal może on przyjąć dowolną wartość i jeśli jest ona różna od zera, potraktuje ją jako prawdę !!!
 
Operatorami logicznymi są: !, ==, !=, <, >, <=, >=, && oraz ||.
 
Pierwszy z nich, czyli ! jest operatorem jednoargumentowym i przyjmuje argument, tak jak operator negacji bitowej, po swojej prawej stronie. Zwraca on logiczne przeciwieństwo danego wyrażenia. Czyli jeśli jako argument dostanie prawdę, zwróci fałsz, jeśli fałsz to zwróci prawdę.
 
Reszta z nich przyjmuje 2 argumenty i możemy je podzielić na 2 kategorie: operatory porównania i operatory and i or.
 
Operatory porównania po prostu porównują 2 wartości ze sobą i zwracają prawdę lub fałsz jeśli ich wewnętrzny warunek został spełniony.
== sprawdzi czy wartości są równe
!= sprawdzi czy wartości są różne
> sprawdzi czy wartość po lewej jest większa od wartości po prawej
< sprawdzi czy wartość po lewej jest mniejsza od wartości po prawej
>= sprawdzi czy wartość po lewej jest większa lub równa wartości po prawej
<= sprawdzi czy wartość po lewej jest mniejsza lub równa wartości po prawej
 
Operator && jest to operator AND, sprawdza on czy zarówno po lewej jak i po prawej znajduje się prawda logiczna. Jest dość specyficznym operatorem, ponieważ najpierw sprawdzi (i jednocześnie wykona odpowiednie działania) czy po prawej jest prawda, a dopiero później po lewej. Jeśli po prawej znajdzie się fałsz, wszystko po jego lewej stronie NIE ZOSTANIE wykonane!
 
Oznacza to, że:
 
if (is_user_connected(id) && has_user_jetpack(id))
kod wewnątrz funkcji has_user_jetpack NIE ZOSTANIE NIGDY wykonany, jeśli gracz nie jest połączony do serwera!
 
Operator || jest operatorem OR, sprawdza on czy po lewej lub po prawej znajduje się prawda logiczna. On również zachowuje się specyficznie, gdyż nie wykona nigdy kodu po jego prawej jeśli po lewej znajduje się prawda.
 
Oznacza to, że:
 
if (has_user_jetpack(gracz1) || has_user_jetpack(gracz2))
sprawdzenie dla drugiego gracza czy posiada jetpack NIGDY SIĘ NIE WYKONA jeśli pierwszy gracz jetpack posiada.
 
Operator wyrażenia warunkowego
 
Operator ten przyjmuje 3 argumenty, pierwszy z nich wstawiamy przed znakiem zapytania, drugi pomiędzy znakiem zapytania, a dwukropkiem, a trzeci z nich za dwukropkiem.
 
Działanie operatora jest dość proste, jeśli 1 argument jest prawdą, zwróci on 2 argument, jeśli fałszem, zwróci 3 argument. Przykład:
 
 
is_user_connected(id)?"gracz jest na serwerze":"gracza nie ma na serwerze"
 
Nawiasy
 
Prócz tych wszystkich operatorów występują również nawiasy. Pierwszy z nich, czyli nawias okrągły () może służyć do 2ch rzeczy: może grupować (jak w matematyce) odpowiednie wyrażenia, zmieniając ich kolejność wykonywania oraz może być składnikiem definicji lub wywołania funkcji.
 
Drugi z nich, nawias kwadratowy [] służy do definiowania tablicy lub do wywoływania konkretnego elementu tej tablicy.
 
Priorytety i kolejność obliczeń
 
Każdy z operatorów posiada pewien priorytet, który determinuje kolejność w jakiej operatory zostaną wywołane jeśli znajdują się w 1 instrukcji. Dodatkowo każdy z operatorów posiada kierunek łączności, który determinuje w jakiej kolejności zostaną wykonane działania dla operatorów o tym samym priorytecie.
 
Priorytety od najwyższego do najniższego:
  • Nawiasy
  • wybór elementu tablicy, wywołanie funkcji, postinkrementacja, postdekrementacja 
  • !, ~, + i - (jako znak liczby), preinkrementacja, predekrementacja
  • *, /, %
  • + i - (jako operatory arytmetyczne)
  • <<, >>, >>>
  • <, <=, >, >=
  • == !=
  • &
  • ^
  • |
  • &&
  • ||
  • ?: (operator wyrażenia warunkowego)
  • wszystkie operatory przypisania
Większość operatorów posiada łączność lewostronną. Wyjątkiem są operatory priorytetów 3, 14 i 15 które posiadają łączność prawostronną.
  • +
  • -
  • 13

NIE pomagam na PW. Nie trudź się, na zlecenia nie odpiszę... Od pomagania jest forum.
NIE zaglądam w tematy wysłane na PW. Jeśli są na forum to prędzej czy później je przeczytam. Jeśli mam co w nich odpisać, to odpiszę.
 
1988650.png?theme=dark


#2 Rivit

    Godlike

  • Support Team

Reputacja: 1 319
Godlike

  • Postów:4 380
Offline

Napisano 16.04.2015 16:49


Bystre oko zauważy, że kompilator AMXX zwróci nam warning przy kompilacji tej linii. Aby kompilator uciszyć, wystarczy objąć warunek dodatkowymi nawiasami:

 

Brakło Ci nawiasu zamykającego jednego ;)

 

 

+

i-- // preinkrementacja

postdekrementacja
chyba że o czymś nie wiem :X

 

 

Ogólnie operatory możemy podzielić na 3 kategorie: dwuargumentowe, jednoargumentowe i jeszcze jeden, samotny w swojej grupie operator wyrażenia warunkowego (? :) który posiada 3 argumenty.

Ta buźka zmienia sens życia :c

 

 

 

Poradnik na 6 :D


GwynBleidD (17.04.2015 08:42):
Poprawione.

  • +
  • -
  • 0

#3 Skull.

    Wszechpomocny

  • Użytkownik

Reputacja: 70
Pomocny

  • Postów:314
  • Steam:steam
  • Imię:Tajemnica
  • Lokalizacja:Woj. Wielkopolskie
Offline

Napisano 16.04.2015 17:27

Właśnie o takie wyjaśnienie mi chodziło, dziękuje za chęci opisanie tak z zrozumieniem bardziej   ^D^
 
 

== sprawdzi czy wartości są równe
!= sprawdzi czy wartości są różne
> sprawdzi czy wartość po lewej jest większa od wartości po prawej
< sprawdzi czy wartość po lewej jest mniejsza od wartości po prawej
>= sprawdzi czy wartość po lewej jest większa lub równa wartości po prawej
<= sprawdzi czy wartość po lewej jest mniejsza lub równa wartości po prawej

 

 

Czyli jak zrobię if'a tak + użyje retrun:

if(get_user_team(index) != 1)
return PLUGIN_HANDLED;

fm_set_user_godmode(index, 1);return PLUGIN_HANDLED;

To wykona tylko na Team TT?

 

 

 

A jak zrobię if'a tak + użyje retrun:

if(get_user_team(index) != 1)
return PLUGIN_CONTINUE;

fm_set_user_godmode(index, 1);
return PLUGIN_CONTINUE;

To nie wykona na Team TT?

 

 

 

Ps. Gubię się też często w poprawnym postawieniu:

return PLUGIN_CONTINUE;
return PLUGIN_HANDLED;
retrun PLUGIN_HANDLED_MAIN;

Czytałem trochę o retrunach lecz gdy w grę wchodzi ! lub != to już się gubię :(

Oraz czy ma to jakieś znaczenie że na końcu jest ten symbol:  ; ?


Użytkownik Mr.Skull edytował ten post 16.04.2015 17:28

  • +
  • -
  • 0

#4 Rivit

    Godlike

  • Support Team

Reputacja: 1 319
Godlike

  • Postów:4 380
Offline

Napisano 16.04.2015 17:42


Ps. Gubię się też często w poprawnym postawieniu:

return PLUGIN_CONTINUE;
return PLUGIN_HANDLED;
retrun PLUGIN_HANDLED_MAIN;

Czytałem trochę o retrunach lecz gdy w grę wchodzi ! lub != to już się gubię :(
#define PLUGIN_CONTINUE		0	/* Results returned by public functions */
#define PLUGIN_HANDLED		1	/* stop other plugins */
#define PLUGIN_HANDLED_MAIN	2	/* to use in client_command(), continue all plugins but stop the command */

Była masa o tym tematów, nawet sam pytałem.

if(get_user_team(index) != 1)
return PLUGIN_HANDLED;
if(get_user_team(index) != 1)
return PLUGIN_CONTINUE;
if(get_user_team(index) != 1)
return;

Wyjdzie z funkcji gdy team gracza jest różny od 1 (czyli TT)

 

 


Oraz czy ma to jakieś znaczenie że na końcu jest ten symbol: ; ?

W PAWN'ie nie jest wymagany średnik na końcu linii. Można użyć

#pragma semicolon 1

żeby wymusić na sobie dawanie średnika (dobry nawyk)


  • +
  • -
  • 0

#5 Skull.

    Wszechpomocny

  • Użytkownik

Reputacja: 70
Pomocny

  • Postów:314
  • Steam:steam
  • Imię:Tajemnica
  • Lokalizacja:Woj. Wielkopolskie
Offline

Napisano 16.04.2015 17:58

Mr.Skull, dnia 16 Kwie 2015 - 18:27, napisał:

Ps. Gubię się też często w poprawnym postawieniu:

return PLUGIN_CONTINUE;
return PLUGIN_HANDLED;
retrun PLUGIN_HANDLED_MAIN;

Czytałem trochę o retrunach lecz gdy w grę wchodzi ! lub != to już się gubię
#define PLUGIN_CONTINUE 0 /* Results returned by public functions */
#define PLUGIN_HANDLED 1 /* stop other plugins */
#define PLUGIN_HANDLED_MAIN 2 /* to use in client_command(), continue all plugins but stop the command */
Była masa o tym tematów, nawet sam pytałem.

To wiem, nawet kilkakrotne razy czytałem ten temat, lecz tak jak pisałem ze gubię się wtedy gdy trzeba dodać !

Czyli dwa przykłady:

1.

if(!get_user_flags(id) & ADMIN_LEVEL_H)

2.

if(get_user_team(index) != 1)

  • +
  • -
  • 0

#6 Rivit

    Godlike

  • Support Team

Reputacja: 1 319
Godlike

  • Postów:4 380
Offline

Napisano 16.04.2015 18:07

Patrz:

if(get_user_flags(id) & ADMIN_LEVEL_H) {/*MA FLAGE*/}
if(!(get_user_flags(id) & ADMIN_LEVEL_H)) {/*NIE MA FLAGE*/}
if(get_user_team(index) != 1) {/* NIE JEST W TT */}
if(!(get_user_team(index) == 1)) {/*NIE JEST W TT */}

Chyba Ci namieszałem :X


  • +
  • -
  • 1

#7 GwynBleidD

    Godlike

  • Autor tematu
  • Przyjaciel

Reputacja: 1 869
Godlike

  • Postów:3 066
  • Steam:steam
  • Lokalizacja:Przemyśl
Offline

Napisano 17.04.2015 07:55

Mr.Skull niepotrzebnie patrzysz na ten kod jako całość, rozbij sobie go na kawałki:

najpierw masz if, który coś sprawdzi. Jeśli sprawdzenie się powiedzie, wykona się return, jeśli się nie powiedzie return się nie wykona.
w warunku ifa masz warunek, jeśli cały jest zanegowany (znak ! na początku i objęta reszta nawiasem) to traktujesz tego ifa tak jakby if i else były zamienione miejscami.
dalej wewnątrz warunku masz jakieśtam rzeczy, korzystając z listy priorytetów operatorów doprowadź sobie warunek do formy w której wiesz dokładnie co i jak się w nim policzy.

Na przykładzie Twojego ifa z get user team:
if(get_user_team(index) != 1)
if nie jest zanegowany więc wykona się gdy wewnętrzny warunek jest spełniony. Następnie wykona się get_user_team(index), a wynik zostanie porównany z jedynką. Jeśli NIE jest równy jedynce (operator !=) to if się wykona, wykona się więc return zawarty w tym ifie i nic poza tym returnem w tej funkcji już się nie wykona.

Przykład 2:
if(!get_user_flags(id) & ADMIN_LEVEL_H)
If nie jest w całości zanegowany, zanegowane jest get_user_flags !! Popatrz na listę kolejności operatorów, jako pierwsze jest wywołanie funkcji, następnie operator ! a dopiero później operator &. W ten sposób:
1. wykona się get_user_flags
2. wynik get_user_flags zostanie zanegowany LOGICZNIE, co oznacza że jeśli gracz miał jakiekolwiek flagi, otrzymasz zero. Jeśli nie miał żadnych, otrzymasz jeden. Gracz zawsze ma flagi.
3. Zostanie obliczony iloczyn bitowy jedynki lub zera i ADMIN_LEVEL_H. Jedynka posiada zaświecony bit pierwszy, ADMIN_LEVEL_H ma któryś z dalszych, zero nie ma żadnego. Co oznacza że ten iloczyn bitowy ZAWSZE zwróci 0
4. if NIGDY się nie wykona.
  • +
  • -
  • 1

NIE pomagam na PW. Nie trudź się, na zlecenia nie odpiszę... Od pomagania jest forum.
NIE zaglądam w tematy wysłane na PW. Jeśli są na forum to prędzej czy później je przeczytam. Jeśli mam co w nich odpisać, to odpiszę.
 
1988650.png?theme=dark


#8 DarkGL

    Nie oddam ciasteczka !

  • Administrator

Reputacja: 6 553
Godlike

  • Postów:11 976
  • GG:
  • Steam:steam
  • Imię:Rafał
  • Lokalizacja:Warszawa
Offline

Napisano 17.04.2015 14:24

Dodatkowo http://pl.wikipedia..../Notacja_polska


  • +
  • -
  • 1




Użytkownicy przeglądający ten temat: 0

0 użytkowników, 0 gości, 0 anonimowych