Autor | Zpráva | ||
---|---|---|---|
Joker Profil |
Autor: Joker
Odkaz na aktuální verzi textu: Základní kurz 7: Přetypování zveřejněno Odkud se vede diskuse k aktuálnímu stavu textu: První příspěvek po poslední revizi textu |
||
Joker Profil |
#2 · Zasláno: 3. 9. 2012, 09:23:37
První verze textu
PHP - základní kurz PřetypováníV [odkaz]předchozí kapitole[/odkaz] jsme se seznámili s proměnnými a datovými typy. V této kapitole si ukážeme, jak lze hodnoty převádět na jiné datové typy. V některých situacích se hodnoty mohou přetypovat automaticky aniž by si to programátor vyžádal nějakým zvláštním příkazem, je tedy potřeba znát, za jaké situace a podle jakých pravidel se hodnoty přetypují. Vynucené přetypováníUkažme si nejdříve přetypování vynucené programátorem, které je vcelku přímočaré.Prostě se to, na co chceme přetypovat, napíše do závorky před hodnotu nebo proměnnou, kterou chceme přetypovat. Možnosti přetypování jsou tyto: - (string) přetypuje na řetězec
- (boolean) nebo (bool) přetypuje na logickou hodnotu
- (integer) nebo (int) přetypuje na celé číslo
- (real) , (float) nebo (double) přetypuje na reálné číslo
- (array) přetypuje na pole. O polích si povíme později
- (object) přetypuje na objekt. Objekty jsou nad rámec tohoto základního kurzu, ale po jeho dokončení si
o nich můžete přečíst v sekci o objektovém programování. - (unset) přetypuje na NULL. Prakticky zbytečné, místo [pre]$nic = (unset)"něco";[pre] můžete psát rovnou
$nic = NULL; . Jen si pamatujte, že (unset) je něco jiného, než funkce unset() z minulé
kapitoly. Zatímco unset($promenna); zruší danou proměnnou, (unset)$promenna jen vrátí NULL
a proměnná zůstane beze změny. Ukázka přetypování: <?php $cislo = 1; // číslo $retezec = (string) 1; // číslo přetypované na řetězec // Necháme si vypsat hodnoty proměnných: echo 'hodnota $cislo: '; var_dump($cislo); echo 'hodnota $retezec: '; var_dump($retezec); ?> Vypíše, že hodnota $cislo je 1 typu int (celé číslo) a hodnota $retezec je '1' typu string (řetězec). Přetypování proměnné jen vrátí hodnotu nového datového typu, ale nezmění samotnou proměnnou. Chcete-li na nový datový typ změnit hodnotu proměnné, musíte pak výsledek přiřadit zpátky do té proměnné. <?php $cislo = 1; // číslo $retezec = (string) $cislo; // $retezec bude řetězec "1", ale $cislo bude pořád číslo $cislo = (float)$cislo; // Takto se změní datový typ samotné proměnné Jak se co přetypuje?Možná vás teď napadlo, že ne všechna přetypování mají intuitivní výsledek, například:$hodnota = (int)"Ahoj!"; Pravidla přetypování jsou tato: - Přetypování na řetězec (string): Číslo se jednoduše převede na odpovídající řetězec (třeba 15 na "15"). Dejte jen pozor, že u reálných čísel nemusí být výsledekem číslo "hezky formátované". Jednak desetinná tečka versus čárka a jednak velmi vysoká nebo velmi malá čísla jsou zapsána v tzv. exponenciálním tvaru: Jde vlastně o zápis používaný třeba ve fyzice, kdy se např. číslo 1999000000000 zapíše jako 1,999 x 10^12. zde se jen vynechá to "krát deset na" a místo toho je písmeno "E". Čili například (string)100000000000000 vrátí řetězec "1.0E14", nebo (string)0.000036 vrátí
řetězec "3.6E-5". - Přetypování na celé číslo (int): Z reálného čísla se bere celá část (takže se nezaokrouhluje), například 17.9 se převede na 17. Při konverzi výsledku nějakého výpočtu ale nezapomeňte na specifika ukládání reálných čísel, jak je zmíněno v minulé kapitole. Výsledek výpočtu s reálnými čísly bude v paměti uložen jako nejbližší uložitelné reálné číslo, které se tedy může nepatrně lišit od skutečného výsledku. To ale znamená, že přesně celočíselný výsledek výpočtu může být uložený jako nepatrně nižší reálné číslo. A jelikož převod na celé číslo bere celou část, může pak výsledkem být číslo o 1 nižší. Příklad: <?php $vysledek = (0.7 + 0.1) * 10; var_dump($vysledek); // $vysledek je 8 typu float $vysledek = (int)$vysledek; // přetypujeme na celé číslo var_dump($vysledek); // $vysledek není 8, ale 7 typu int ?> U řetězce se jde od jeho začátku tak dlouho, dokud ho lze interpretovat jako číslo a případný zbytek řetězce se ignoruje. Pokud začátek řetězce vůbec nejde převést na číslo (nebo je řetězec prázdný), je výsledkem 0. Například (int)"-15" je -15, (int)"10Kč" je 10, (int)"Vlak s 10 vagóny" je 0.
Rozpozná i výše zmíněný exponenciální tvar, tedy např. "1.2e3" se převede na 1200. - Přetypování na reálné číslo (real/double/float) Analogické k přetypování na celé číslo, jen méně záludné. - Přetypování na logickou hodnotu (bool) Pokud jde o číslo, převede se 0 na false, cokoli jiného na true. V případě řetězce se prázdný řetězec převede na false, všechno ostatní na true. Pozor, znamená to, že i řetězec "false" se převede na true! Neosvojujte si proto zvyk některých začátečníků psát uvozovky kolem všech hodnot, nejen řetězců. - Krátká poznámka k polím a objektům Jak už je napsáno výše, polím se bude věnovat pozdější kapitola a objektům až další část tohoto webu po skončení základního kurzu. Když je ale řeč o přetypování, pro úplnost zmiňme, že přetypování polí či objektů na jiné typy, ani přetypování jiných datových typů na pole či objekty obvykle nedává valný smysl. Pokus o přetypování objektu na jiný datový typ dokonce může skončit chybovou hláškou. Skryté (automatické) přetypováníKromě přetypování vynuceného programátorem jsou v PHP i situace, kdy se datový typ hodnoty změní automaticky důsledkemnějakého výpočtu. I když to není úplně přetypování, o kterém jsme mluvili výše, připomeňme si z minula, že datový typ proměnné je určený její hodnotou. Přiřazení hodnoty jiného typu tedy změní datový typ proměnné. <?php $promenna = 1; // $promenna je typu integer (celé číslo) $promenna = "ahoj"; // $promenna je nyní typu string (řetězec) ?> Z předchozí kapitoly o datových typech dále víte, že celé číslo, které je příliš vysoké (nebo příliš nízké záporné), než aby šlo uložit do typu integer, se automaticky převede na typ float (a pokud se nevejde ani do jeho rozsahu, změní se na speciální hodnotu INF, reprezentující nekonečno). Příklad: var_dump(99*99); var_dump(9999999999*9999999999); což znamená 9.999999998 * 10^19, neboli 99999999980000000000. Všimněte si, že ve skutečnosti má výsledek toho součinu být 99999999980000000001. Opět jde o nepřesnost kvůli způsobu uložení reálných čísel, o které jsme už mluvili. Důležitý poznatek tedy je, že nepřesnost při uložení reálných čísel není pevná, ale závisí na velikosti uloženého čísla. Přesně se uloží prvních 15 cifer čísla. To může vést k paradoxním situacím: $soucin = 99999999980000000000; $soucet = $soucin + 100; var_dump($soucin); var_dump($soucet) A to dokonce přesto, že ve skriptu máme pouze celá čísla. Je to způsobené mechanismem popsaným výše, tedy příliš vysoké celé číslo se automaticky převedlo na reálné. Protože řád prvního čísla je 10^19, jakékoli změny menšího řádu než 10^4 (tedy desetitisíce) nemusejí dávat přesné výsledky. Také operandy ve výrazech se automaticky přetypují na datový typ, který je vyžadován použitým operátorem. <?php $vysledek = "10" + "1"; // $vysledek bude 11 ?> na čísla, aby bylo možné spočítat výsledek. Zároveň si zapamatujte, že operátorem + nejdou v PHP "sčítat", tedy spojovat, řetězce (jak ukazuje i příklad výše). U proměnných opět platí, že se přetypuje pouze hodnota použitá ve výrazu, ale ne hodnota samotné proměnné: <?php $vstup = "5"; $vysledek = $vstup + 1; // $vysledek je číslo (integer) 6, v $vstup zůstane řetězec "5" ?> Také příkazy jako echo , pokud dostanou hodnotu jiného datového typu než očekávají, ji přetypují.
Příklad: <?php $logicka = true; echo $logicka; ?> Vypíše 1, protože echo očekává řetězec a logická hodnota se přetypuje na řetězec "1".
Když v příkladu použijete false místo true, nevypíše se nic (false se převádí na prázdný řetězec, vzpomínáte?) Jiné techniky převodu datových typůPoměrně často se stává, že potřebujete změnit datový typ, ale podle jiných pravidel, než těch výše uvedených.Například potřebujete převádět mezi logickou hodnotou a řetězcem tak, aby hodnota true odpovídala řetězci "ano" a hodnota false řetězci "ne". Tato situace je možná častější, než použití standardního přetypování. Takovéto podmínky je ovšem potřeba odprogramovat přímo v kódu. Některá možná řešení si ukážeme v následujících kapitolách. ShrnutíDatový typ hodnoty může změnit sám programátor příkazem pro přetypování, nebo se datový typ může změnit automatickyběhem výpočtu, pokud operátor nebo příkaz vyžaduje jiný datový typ, než hodnota má. Také funkce většinou u svých argumentů počítají s nějakým datovým typem, ačkoliv se při definici argumentů datový typ nespecifikuje (PHP ostatně ani u proměnných nemá pevné datové typy). Při práci s argumentem uvnitř funkce se hodnota obvykle přetypuje. Některé funkce si typ argumentů kontrolují a je-li předaná hodnota špatného typu (nebo nejde přetypovat na ten správný), mohou vyhodit chybovou hlášku Jak již víme z předchozí kapitoly, celá čísla vyšší než dokáže pojmout datový typ integer se automaticky přetypují na reálná čísla (float), která trpí určitou nepřesností vlivem způsobu uložení reálných čísel v paměti. Přitom tato nepřesnost roste s hodnotou uloženého čísla, takže je dobré na to dát pozor, pokud byste například sčítali velmi vysoká čísla s velmi nízkými. Často je potřeba převést datové typy mezi sebou podle jiných pravidel, než standardní PHP přetypování. Toto je nutné odprogramovat ve skriptu a některé příklady si ukážeme později v tomto se |
||
Alphard Profil |
#3 · Zasláno: 3. 9. 2012, 09:39:38
Máte někde zmíněné funkce jako is_numeric()? U proměnných je vyhledávání nenašlo, tady taky nejsou. Nebo se nebudou uvádět?
Větu „Pokus o přetypování objektu na jiný datový typ dokonce může skončit chybovou hláškou.“ bych možná formuloval jinak. Tohle může působit tak, že skrytí hlášky (nebo když se kvůli odlišnému nastavení neobjeví) řeší problém. |
||
Jan Tvrdík Profil |
#4 · Zasláno: 3. 9. 2012, 11:32:08
|
||
Joker Profil |
#5 · Zasláno: 3. 9. 2012, 16:47:32
Alphard:
Jo, dobrá poznámka, já myslel, že to je už u proměnných a datových typů, ale není. „Větu ‚Pokus o přetypování objektu na jiný datový typ dokonce může skončit chybovou hláškou.‘ bych možná formuloval jinak.“ Mno, upřímně řečeno, já si sám nejsem úplně jistý, jak to vlastně je. Přetypovávat objekty na něco jiného nemá moc smysl, snad nikdy jsem to v reálném programu nedělal a popis v manuálu nejspíš neodpovídá realitě. Na to, že některá ta přetypování nelze provést (přestože manuál tvrdí že lze) jsem přišel jen díky tomu, že jsem si to pro jistotu ještě ověřoval na reálných kódech. Takže manévrovací prostor pro správný popis situace nemám velký :) Jan Tvrdík: Díky, ještě to zvážím |
||
panther Profil |
#6 · Zasláno: 3. 9. 2012, 16:52:13
Jan Tvrdík:
„Možná by se hodilo stručně uvést funkce gettype a settype.“ o těchto bych se asi nezmiňoval, tak často se nepoužívají a nemyslím, že je nutné je v základním kurzu zmiňovat. „Doplnit za první výskyt slova ‚přetypovat‘ jeho význam“ význam je uveden před ním - „V této kapitole si ukážeme, jak lze hodnoty převádět na jiné datové typy. V některých situacích se hodnoty mohou přetypovat“. Více to asi není třeba rozepisovat, co se přetypování jako slova týče. |
||
Časová prodleva: 8 dní
|
|||
Norman Profil |
#7 · Zasláno: 11. 9. 2012, 19:08:14
Velice pěkně sepsáno ...
Tak jestli můžu dodat pár poznámek (jestli ne smažte to..): - [odkaz]předchozí kapitole[/odkaz] // napravil bych :) - [pre]$nic = (unset)"něco";[pre] // taktéž - I když nevím jestli to sem tak úplně patří, nicméně určitě je dle mého vhodné s OOP seznámit hned od začátku Pěkný příklad má na webu Jakub (http://php.vrana.cz/objektove-literaly-v-php.php) $obj = (object) array("vlastnost1" => "hodnota", "vlastnost2" => "hodnota"); |
||
panther Profil |
#8 · Zasláno: 11. 9. 2012, 20:34:47
Norman:
„- [odkaz]předchozí kapitole[/odkaz] // napravil bych :)“ to je jen symbolický zápis, později z toho budou skutečné odkazy a obarvený kód. „určitě je dle mého vhodné s OOP seznámit hned od začátku“ to si nemyslím. Začátečník v této fázi nemá pořádně pojem o tom, co je proměnná. „$obj = (object) array("vlastnost1" => "hodnota", "vlastnost2" => "hodnota");“ zrovna tento kousek řádku, který jsi odcitovat, smysl nedává. Objektům musí být věnována samostatná kapitola, nejde o nich psát jen tak mimochodem. |
||
Norman Profil |
#9 · Zasláno: 11. 9. 2012, 21:14:21
ok, omlouvám se, moje chyba :)
|
||
Joker Profil |
#10 · Zasláno: 11. 9. 2012, 21:48:48
Norman:
Ty značky v hranatých závorkách se upraví před zveřejněním článku. „určitě je dle mého vhodné s OOP seznámit hned od začátku“ V základním kurzu jde hlavně o pozorumění syntaxi a hlavním pravidlům tvorby efektivního a přehledného kódu, což se samozřejmě pak hodí i v kurzu OOP. Bude ale vhodné ty základy udržet co nejjednodušší, takže bych do toho nemotal ještě výuku teorie objektově-orientovaného programování. Navíc přetypování mezi objektem a jiným datovým typem je něco tak exotického, že to v základním kurzu snad ani nemá cenu rozebírat. Uvedený příklad je užitečný jen v hodně specifických situacích, do kterých se začátečník nejspíš nedostane. |
||
Časová prodleva: 1 rok
|
|||
Joker Profil |
#11 · Zasláno: 6. 2. 2014, 16:46:27
Přidal jsem na Péhápko.
Tři články zveřejněné během jednoho týdne, to se snad ještě nepovedlo :-) |
||
Časová prodleva: 9 let
|
0