Přejít na obsah

#7 switch [*]

tut tutorial Pawn samp switch case default rozsah range

  • Pokud chcete odpovědět, přihlaste se
3 odpovědí

#1
vEnd

vEnd

    Python maniac

  • Globální moderátor
  • Příspěvků: 682

*
POPULÁRNÍ

Obtížnost: :1:

 

Osnova:

1. Úvod, co je to switch

2. Kdy a jak použít switch

3. Další možnosti case

4. Ukázky použití

5. Závěr

 

1. Úvod

Zdravím Vás u sedmého návodu pro začínající pawnery. Tímto navážeme na minulý návod (přečtěte si ho) a rozebereme si, k čemu slouží switch a kdy jej použít namísto normálních podmínek.

 

Napřed ale co je to ten switch. Switch (česky přepínač) je struktura, která v konkrétním případě nahrazuje soustavu if – else if – else. Jeho účelem je vykonat ten blok, který odpovídá jeho hodnotě. Proto také přepínač, obecně se dá říct, že přepne na blok dané hodnoty.

 

2. Kdy a jak použít switch

Už jsem řekl, že se používá v konkrétním případě. Tím případem je tato soustava podmínek:

.

new cislo = 2;

if(cislo == 1)
{
    //hodnota je 1
}
else if(cislo == 2)
{
    //hodnota je 2
}
else if(cislo == 3)
{
    //hodnota je 3
}
else
{
    //hodnota je jiná
}

.

Pokud v podmínkách porovnáváme takto hodnoty, lze k tomu použít kratší a přehlednější switch. Syntaxe switche je následovná:

.

switch(cislo)
{
    case 1:
    {
        //hodnota je 1
    }
    case 2:
    {
        //hodnota je 2
    }
    case 3:
    {
        //hodnota je 3
    }
    default:
    {
        //hodnota je jiná
    }
}

.

Do závorek switche jsme dosadili proměnnou, ze které zjišťuje hodnotu. case je klíčové slovo, které nám zde tvoří větev pro konkrétní hodnotu. Jak je vidět, nahrazuje nám else if a podmínku. Na jedno si musíme dát pozor – je potřeba za case a hodnotu uvést dvojtečku. default je bez hodnoty a plní funkci else – provede se vždy, když hodnota neodpovídá žádnému case. Narozdíl od case ale není nutné jej použít.

 

3. Další možnosti case

Switch dokáže pracovat jak s celými čísly, tak se znaky a desetinnými čísly.

.

case 1: //zápis pro celé číslo
case 'a': //zápis pro znak
case 3.14: //zápis pro desetinné číslo

.

Jazyk nám též umožňuje zapsat v jednom case několik hodnot, když je to třeba, stačí je oddělit čárkou.

.

case 1, 3, 5: //několika celých čísel
case 'a', 'b', 'c': //několik znaků
case 3.14, 1.4, 8.2: //několik desetinných čísel (tečka je desetinná čárka)

.

Pro zajímavost (rozklikněte spoiler):

Spoiler

.

4. Ukázky použití

Před koncem si ještě ukážeme pár příkladů, jak switch používat.

 

Dialogy

Spoiler

.

Kombinovaný zápis

Spoiler

.

5. Závěr

Switchem jsme definitivně ukončili téma podmínek. Kromě if, else if a else teď znáte už i switch a víte, kdy a jak ho použít. Poslední varování na závěr: v jiných jazycích (C/C++, C#, Java, Javascript, PHP atd.) se blok case a default ukončuje klíčovým slovem break a neuvádějí se složené závorky. Pro Pawn to prostě neplatí, takže tuto syntaxi si nechte pro ostatní jazyky.

 

Tento návod, stejně jako ty předchozí, je určen pro nováčky, pokročilejší věci byly buďto úplně vynechány, nebo jsou uvedeny ve spoilerech. Přesto, zdá-li se Vám, že jsem něco opomněl, někde jsem se spletl nebo se jen chcete vyjádřit, pište do tohoto tématu.

 

Ověřený návod

Tento návod prošel validací, a lze ho proto považovat za ověřený.


  • 5


I always enjoy meeting people more chemically imbalanced than myself. -Trevor Philips
It's hard to follow the train when you are hauling two number nines; a number nine large; a number six with extra dip; a number seven; two number 45s, one with cheese; and a large soda. -guess who


#2
Tanga

Tanga

    Dieta internetu

  • Uživatel
  • Příspěvků: 1 141

Uživatelova ocenění

        

Obtiaznost: ****

 

Pawn je vykonávaný na abstraktnom stroji (Abstract Machine eXecutor). Tento číta výsledný skompilovaný kód a vykonáva dané inštrukcie. Ak narazí na switch(), porovnávanie hodnôt vykonáva automaticky (porovnávací kód sa nenachádza v skompilovanom súbore).

 

2. Kdy a jak použít switch

 

Okrem toho, že switch vyzerá krajšie, je aj rýchlejší.

Rýchlosť budem porovnávať s týmto kódom:

compif(x) {
    if (x == 1) {
        return;
    } else if (x == 2) {
        return;
    } else if (x == 3) {
        return;
    } else if (x == 4) {
        return;
    } else {
        return;
    }
}

compswitch1(x) {
    switch(x) {
        case 1..4: return;
        default: return;
    }
}

compswitch2(x) {
    switch(x) {
        case 3: return;
        case 2: return;
        case 4: return;
        case 1: return;
        default: return;
    }
}

Čím viac hodnôt (case-ov) porovnávate, tým viac sa oplatí používať switch.

Porovnanie (GetTickCount()) môže vyzerať nejak takto:

[02:55:21] iftime: 14435
[02:55:29] switchtime1: 8038
[02:55:37] switchtime2: 8053

Rovnako testovanie na dvoch hodnotách (case 1..2) (ale viac iterácií):

[03:09:03] iftime: 17946
[03:09:17] switchtime1: 14004
[03:09:33] switchtime2: 16093

A testovanie na 30 hodnotách:

[03:14:07] iftime: 72057
[03:14:26] switchtime1: 19457
[03:14:43] switchtime2: 19146

Ako je vidieť, switch už moc nenaberá na čase s viac hodnotami. A tiež switch1 má rovnakú rýchlosť ako switch2.

 

 

6. Ako funguje switch

 

Prečo je switch rýchlejší? Ostatné (Pawn viacmenej tiež) jazyky používajú tzv. Jump table.

 

Najprv ukážem ako vyzerá bežný if (kód vyššie) po skompilovaní: (kod som vytiahol cez oficialny pawndisasm.c)

* Niektore zbytocne instrukcie som kvoli prehladnosti odstranil. Kvoli tomu adresy nepojdu "za sebou".

* pri je (abstraktny register) miesto v pamati, ktore použiva Pawn AMX, kedze nedokaze porovnat priamo dve premenne. Vsetky operacie sa robia cez pri. Mozete si to predstavit ako premennu s rychlym pristupom.

* Okomentoval som to pre lahsie citanie, staci si pozriet komenty a adresy kam to skáče.

; compif(x)
; adresa | instrukcia
00000354  proc compif
; if (x == 1)
0000035c  load.s.pri 0000000c ; pri = x
00000364  eq.c.pri 00000001   ; pri != 1?
0000036c  jzer 00000380       ; ak plati, skoc na adresu 00000384 (dalsi else if)
0000037c  retn                ; (neplati) return
; else if (x == 2)
00000384  load.s.pri 0000000c ; pri = x
0000038c  eq.c.pri 00000002   ; pri != 2?
00000394  jzer 000003a8       ; ak plati, skoc na 000003a8
000003a4  retn                ; return
000003a8 ; ... dalsie else if

Porovnáva každý if s danou hodnotou, v prípade, že sa nerovnajú, "preskočí" na ďalší else-if. Ten skok trvá najdlhšie.

 

Jump table

 

V RAM vyzera dana tabulka takto: (vlavo adresy v RAM, vpravo inštrukcia na danej adrese)

RAM:
--------------------------
| jmptable:              |
| 0x01: JUMP 0x2349807   |
| 0x02: JUMP 0x0938490   |
| 0x03: JUMP 0x6454299   |
| ..                     |
| 0x2349807 kod z case 1 |
| ..                     |
--------------------------

Kód

switch (x) {..}

sa teda kompilerom prepíše na

jump (jmptable + x);

Ideálne teda nedochádza k žiadnemu porovnaniu hodnôt, iba k jednému skoku.

 

Switch v Pawn

Pawn je teda v tomto trochu iný. Tabulka (v Pawn nazýzvaná "casetbl") sa rovnako vygeneruje, ale nepoužíva sa priamo skok, ale len porovnávanie hodnôt. AMX V reálnom čase porovnáva hodnotu x so všetkými "cases" a až keď nájde rovnakú hodnotu, skočí na danú adresu.

compswitch1 z kódu uvedeného vyššie:
 

00000404  proc compswitch1
0000040c  load.s.pri 0000000c ; pri = x
00000414  switch 00000444     ; switch (pri), jump table je na adrese 00000444  
; case 1..4:
00000424  retn                ; return - vnutro case
00000428  jump 00000470       ; skoc za casetbl, v pripade ze nenasiel ziadnu hodnotu v tabulke
; case: default
00000438  retn                ; return, resp. iny kod
0000043c  jump 00000470       ; skoc za "casetbl", teda na dalsi kod
00000444  casetbl 00000004 00000438 ; celkovo 4 moznosti, pri default skoč na 00000438
                  00000001 00000424 ; case 1: jmp 00000424 
                  00000002 00000424 ; case 2: jmp 00000424 
                  00000003 00000424  
                  00000004 00000424  
00000470 ; ..

Je teda zrejmé, že "1..4" vygeneruje zápisy pre všetky možnosti medzi tým s rovnakou skokovou adresou.

 

Kód cmpswitch2 vyzerá podobne. Pre stručnosť sem dám len casetbl.

00000478  proc compswitch2
; ..
000004f4  casetbl 00000004 000004e0 ; 4 zapisy
                  00000001 000004cc ; x == 1 -> skoc na prvy case
                  00000002 000004a4 ; x == 2 -> druhy case
                  00000003 00000490
                  00000004 000004b8
000004e0 ; ..

Rozdiely medzi cmpswitch1 a 2 sú, že každý case má odlišnú adresu kam skočiť.

 

Záver

Možno ste si všimli, že hodnoty sú v compswitch2 po skompilovaní zoradené. Kompiler ich zoradil automaticky.

The records in the case table are sorted on their value. An abstract machine may take advantage of this lay-out to search through the table with a binary search.
(z Pawn Implementer Guide). Podľa zdrojového kódu amx sa však nepoužíva binary search, ale lineárne porovnávanie všetkých hodnôt zaradom.

  • 3

“The only Zen you find on the tops of mountains is the Zen you bring up there.” ~Robert M. Pirsig

 

96b259ac47244701b5097887d9439120.png

 

Ku kódu nezabudnite priložiť SSCCE.

Spoiler

#3
ATomas

ATomas

    RZE for life, SP for ever !

  • Ověřený uživatel
  • Příspěvků: 2 819
  •   

 

(porovnávací kód sa nenachádza v skompilovanom súbore).

S tímto bych nesouhlasil. V kompilovanem kodu je vsechno. Ale pri spusteni se cely nahraje do pameti (Tj muzes po spusteni mod smazat ze slozky gamemodes a furt svr pojede (do resetu)). Taky jeden z duvodu proc nema moc smysl resit jestli vytvorit pole o 50 nebo 100 znacich kdyz ma cely kompilovany kod 10MB :d


  • 0
play.superparba.eu:7777
www.superparba.eu
pawno.cz kazí dva typy lidí:
1. "Najdi do to na googlu/wiki" <- sakra tak od toho je tu ta sekce help ne ? Protože to asi nenašel / nepochopil / neví
2. Ovce. <- Člověk by se mohl smát kdyby to nebylo tak smutné jak tu někdo zavedl termín kid/děcko a všichni ho začali bezhlavě používat na každého, kdo se jenom opováží na něco zeptat nebo projevit svůj nazor.

#4
Tanga

Tanga

    Dieta internetu

  • Uživatel
  • Příspěvků: 1 141

Uživatelova ocenění

        

Sry venďo, že ti spamujem do navodu :p

 

S tímto bych nesouhlasil. V kompilovanem kodu je vsechno. Ale pri spusteni se cely nahraje do pameti (Tj muzes po spusteni mod smazat ze slozky gamemodes a furt svr pojede (do resetu)). Taky jeden z duvodu proc nema moc smysl resit jestli vytvorit pole o 50 nebo 100 znacich kdyz ma cely kompilovany kod 10MB icon_e_biggrin.gif

Myslel som to tak, že ak použiješ switch, vo vyslednom subore je len "switch (adresa tabulky)" a samotna casetbl. Porovnavanie hodnot a nasledny skok na tu spravnu hodnotu tam nie je, robí to amx na pozadí.


  • 0

“The only Zen you find on the tops of mountains is the Zen you bring up there.” ~Robert M. Pirsig

 

96b259ac47244701b5097887d9439120.png

 

Ku kódu nezabudnite priložiť SSCCE.

Spoiler





Také označeno jedním nebo více klíčovými slovy: Návod, tut, tutorial, Pawn, samp, switch, case, default, rozsah, range

0 uživatelů si prohlíží toto fórum

0 uživatelů, 0 návštěvníků 0 anonymních uživatelů

© 2015 IPS, Inc.

Zajímat Vás mohou ještě aktuální zprávy. sleviště, slevy dnes Herbalife je skvělou cestou pro dobré zdraví. Je libo dětský web?