Karakterláncok
Karakterek elérése
A karakterláncokkal már eddig is sokat foglalkoztunk, de még nem igazán tudunk bánni velük. Ki tudjuk íratni, meg összefűzögetni, de itt nagyjából véget is ér a tudomány. A karakterláncokkal végezhető műveletek alapját az képezi, hogy el tudjuk érni az egyes karaktereket (olvasni és írni tudjuk őket). Ha minden egyes karaktert külön tudunk kezelni, akkor bármilyen műveletet elvégezhetünk egy karakterlánccal.
Azért csak most tanuljuk ezt, mert a karakterláncok karaktereinek kezelése nagyon hasonló a tömbök kezeléséhez. A karakterláncot most úgy kéne elképzelnünk, mint egy egész számokkal indexelt tömböt, melynek elemei karakterek. Az indexelés 0-val kezdődik, az egyetlen különbség, hogy az indexelő operátor nem [] (szögletes zárójel), hanem {} (kapcsos zárójel).
Például van egy karakterláncunk:
$string = "php";
Ekkor a $string{0} értéke a "p" karakterlánc, a $string{1} a "h", a $string{2} pedig a "p". Vagyis a karakter alatt nem egy új adattípust kell érteni, hanem egy egy karakterből álló karakterláncot, amivel ugyanazokat a műveleteket lehet elvégezni, mint bármilyen más karakterlánccal. Mivel az strlen() függvénnyel meg tudjuk állapítani egy karakterlánc hosszát, az indexelés pedig mindig 0-val kezdődik, így könnyen be tudunk járni egy karakterláncot:
$string = "php";
for ($n = 0; $n < strlen($string); ++$n){
print $string{$n};
}
A print helyett persze valami más műveletet kell odaképzelni, mivel ennek csak annyi az értelme, hogy belassítottuk a weblapunkat. Például egy értelmes művelet lehet ez:
$hossz = strlen($string);
for ($n = 0; $n < $hossz; ++$n){
if ($string{$n} == " "){
$string{$n} = "_";
}
}
A {} operátorral ugyanúgy használhatjuk a karakterlánc karaktereit, mintha tömbelemek lennének, így például azokat meg is változtathatjuk. A fenti program a karakterláncban minden szóközt lecserél aláhúzás karakterre.
Változóhelyettesítés
Sok esetben előfordul, hogy változókat szeretnénk beszúrkálni egy karakterlánc különböző helyeire. Ezt könnyen megtehetjük az összefűtő operátor segítségével, például:
$lang = "php"; $num = 1000; print "A ".$lang." nyelvben több mint ".$num." beépített függvény van!";
A PHP nyelvben azonban nem csak sok beépített függvény van, hanem lehetőség van arra is, hogy ezeket a változókat közvetlenül beszúrkáljuk a karakterláncba:
print "A $lang nyelvben több mint $num beépített függvény van!";
Ebben az esetben nem az fog kiíródni, amit a kódban látunk, mivel a $lang és $num változók helyére a változók értékei fognak bekerülni, vagyis a böngészőben ugyanazt látjuk, mint a fenti esetben:
A php nyelvben több mint 1000 beépített függvény van!
Ez a fícsör csak idézőjelekkel határolt karakterláncokban működik, ha aposztrófok közé rakjuk ugyanezt, akkor a változók nevei fognak kiíródni, vagyis pontosan az, amit a kódban látunk.
A dolog nagyjából úgy működik, hogy ha a PHP kódot értelmező szerver egy idézőjelekkel határolt karakterláncban dollárjelet lát, és ha közvetlen utána egy betű következik, akkor az első illegális karakterig terjedő karakterlánc-darabot egy változó nevének tekinti, és behelyettesíti a változó értékét. Illegális karakternek azt nevezem itt, amelyik nem lehet egy változó nevének a része, pl szóköz, vagy valamilyen írásjel. Ha azonban valamilyen betű vagy szám jön közvetlenül a változónév után, akkor kapcsos zárójelekkel kell jeleznünk a változó nevét:
print "A $lang nyelvben {$num}nél is több beépített függvény van!";
Vagyis a változó nevét a dollárjellel együtt kapcsos zárójelek közé kell raknunk. Ezt egyébként a másik esetben is alkalmazhatjuk, tehát ha biztosra akarunk menni, rakjuk a változó nevét kapcsos zárójelek közé! Ezzel a módszerrel tömbelemeket is beszúrhatunk a karakterláncba:
$lang = array("html", "php");
$kif = array(
"igen" => "vannak",
"nem" => "nincsenek"
);
print "A {$lang[0]} nyelvben {$kif['nem']} függvények!";
Ez az alábbi kimenetet eredményezi:
A html nyelvben nincsenek függvények!
Tömbelemek esetén muszáj használni a kapcsos zárójeleket, asszociatív tömb kulcsát pedig a fent látható módon, aposztrófok között érdemes megadni. A kapcsos zárójelek között más operátorok is használhatók, de eléggé korlátozott a használhatóságuk, és a változók ilyen módon történő beszúrásának a célja, hogy a kód olvashatóságát növejle, így célszerű változókat, és nem összetett kifejezéseket beszúrni ilyen módon. Ha összetett kifejezést szeretnénk beszúrni karakterláncba, inkább használjuk az összefűző operátort.
Felmerülhet a kérdés, hogy ha az első példában lévő karakterláncot idézőjelek közé rakjuk, de úgy szeretnénk kiíratni, hogy a változók nevei szerepeljenek benne, akkor azt hogy tehetjük meg? Ahhoz hogy a php ne tekintse változónak a $ jellel kezdődő szót a karakterláncban, azt escape karakterként kell beszúrnunk így: \$ például:
print "A \$lang nyelvben több mint \$num beépített függvény van!";
Ez az alábbi kimenetet adja:
A $lang nyelvben több mint $num beépített függvény van!
Vagy egyszerűbb, ha aposztrófok között íratjuk ki, ilyenkor nem kell backslash-t rakni a $ jel elé, mivel ott nincs változóhelyettesítés.
Én a továbbiakban az összefűző operátort fogom használni a példákban, Te viszont ismét választhatsz! Ha megtetszett ez a módszer, nyugodtan használhatod.
Karakterlánc-kezelő függvények
Most, hogy már elvileg bármit meg tudunk csinálni egy karakterlánccal, mutatok két, viszonylag gyakran használatos beépített függvényt.
substr()
Ez a függvény a paraméterként átadott karakterlánc egy darabját adja vissza. Első paraméterként meg kell adni a karakterláncot, aminek egy darabját szeretnénk megkapni, a második paraméter egy egész szám, ami a darab elejét határozza meg, a harmadik pedig a darab hossza. A darab elejét a karakter indexével adhatjuk meg (ahogy fentebb a {} operátor esetén láttuk).
Nézzük például az alábbi esetet:
$string = "hosszú szöveg"; $darab = substr($string, 7, 4);
Ekkor a $darab változóba a "szöv" karakterlánc kerül, mivel a $string{7} helyen az "s" betű áll, és onnantól szedünk ki egy 4 karakter hosszúságú karakterláncot. A harmadik paraméter egyébként elhagyható, ekkor az átadott karakterlánc végéig kapjuk meg a darabot. Vagyis az előző esetben a substr($string, 7); visszatérési értéke a "szöveg" karakterlánc.
A második paraméternek megadhatunk negatív számot is. Ebben az esetben a karakterlánc végéhez képest adhatjuk meg a darab első karakterének helyét. Például:
$darab = substr($string, -4, 2);
Így a visszatérési érték az "öv" karakterlánc lesz. Most a második paraméter -4, ami azt jelenti, hogy a darab első karaktere a $string{strlen($string)-4}, és 2 karakter hosszú.
Persze felmerülhet a kérdés, hogy a {} operátor ismeretében mi hasznát vehetjük ennek a függvénynek, mivel egy ilyen vagy ehhez hasonló függvényt viszonylag könnyen meg lehet írni. Amellett, hogy gyakori használat esetén kényelmesebb egy beépített függvényt használni, egy fontosabb ok, hogy szinte biztosan gyorsabban végzi el a beépített függvény a feladatot, mint egy "kézzel írt" kód. Sokszor nincs túl nagy esély rá, hogy a leggyorsabb algoritmussal írjuk meg a függvényt, ráadásul a beépített függvények többnyire nem PHP nyelven vannak megvalósítva. Így a legtöbb esetben eleve ki van zárva, hogy olyan gyors függvényt írjunk, mint a beépített.
strstr()
Ezt a függvényt is meg lehetne írni kézzel, bár ez egy nagyságrenddel nehezebb lenne az előzőhöz képest. Ezzel a függvénnyel egy karakterláncban kereshetünk egy részláncot. Az első paraméter a hosszabb karakterlánc, amiben keressük a második paraméterként megadott rövidebb karakterláncot. Persze lehetne a második paraméter a hosszabb, de az nem túl valószínű, hogy egy rövid karakterlánc tartalmaz egy saját magánál hosszabbat :). A függvény visszatérési értéke az első paraméter egy darabja, méghozzá a részlánc első előfordulásának helyétől a karakterlánc végéig. Ha a részlánc nincs benne, akkor pedig false értéket ad vissza. Például:
$hosszu = "Nem tudják megölni. Maguk mind meghalnak, de ő életben marad, hogy igazoljon engem!"; $s = strstr($hosszu, "meg");
Ezt a szöveget egy idétlen szörnyfilmben hallottam. Persze most nem ez a lényeg, hanem az hogy a "meg" szó kétszer is előfordul a $hosszu karakterláncban, de a függvény az első előfordulást keresi, így a visszatérési érték a "megölni. Maguk mind meghalnak, de ő életben marad, hogy igazoljon engem!" karakterlánc lesz. A függvény egyébként a kis- és nagybetűk közt különbséget tesz, így például az strstr($hosszu, "Igazol"); hívás false értéket adna vissza.
A függvényt általában arra használjuk, hogy megtudjuk, a karakterlánc tartalmazza-e a második paraméterként megadott részláncot. Ezt például így deríthetnénk ki:
if (strstr($hosszu, $resz) == false){ //nem jó!
print "Nincs benne";
}
Ezzel az a probléma, hogy ha az strstr() visszatérési értéke egy üres karakterlánc, vagy "0", akkor az átkonvertálódik false értékké, pedig a $resz benne volt a $hosszu karakterláncban. Hogy ezt elkerüljük, ennél a függvénynél a === vagy !== operátort kell használnunk:
if (strstr($hosszu, $resz) === false){
print "Biztos nincs benne";
}
Itt az if ág csak akkor fut le, ha az strstr() függvény false logikai értékkel tér vissza.
Ha minket esetleg az első előfordulás helye is érdekel, akkor a visszatérési értékként kapott karakterlánc hossza alapján könnyen kideríthetjük. Például, ha ki szeretnénk deríteni a részlánc első karakterének pozícióját, akkor így tehetjük meg:
$len = strstr($hosszu, $resz);
if ($len !== false){
$position = strlen($hosszu) - strlen($len);
}
A $position azt fogja megadni, hogy a $hosszu melyik indexű karakterénél kezdődik a $resz első előfordulási helye. Például a
$hosszu = "php"; $resz = "h";
esetben könnyen látszik a helyzet, az strstr() függvény a "hp" karakterlánccal tér vissza, így a $positition értéke 1 lesz. A "h" karakterlánc pedig valóban a $hosszu{$position} helyen kezdődik.
Ékezetes karakterláncok rendezése
Most az eddig tanult eszközök segítségével megpróbáljuk megoldani az előző leckében felvetett problémát, az ékezetes karaktereket tartalmazó karakterláncok rendezését. Nyilván a sort() függvénynek nem sok hasznát vesszük ebben az esetben. A megoldás az eddigi ismeretek alapján az lenne, hogy megírnánk az egész rendező algoritmust kifejezetten erre az esetre. Ezt úgy csinálhatnánk, hogy készítünk egy összehasonlító kódot, ami két karakterlánc esetén megállapítja, hogy melyik a "nagyobb" (vagyis melyik jön későb az abc-ben), és írnánk egy rendező algoritmust. A PHP annyiban megkönnyíti a helyzetet, hogy a rendező algoritmust nem kell megírnunk, mivel van olyan beépített rendező függvény, ami az elemek összehasonlítására egy általunk definiált függvényt használ. Ilyen például az usort() függvény.
usort()
A függvény tömbök rendezésére szolgál, első paramétere a rendezni kívánt tömb, a második pedig egy karakterlánc, amiben egy általunk megírt függvény neve szerepel. A függvény visszatérési értéke true vagy false attól függően, hogy sikerült-e rendezni a tömböt vagy sem. Például a sima sort() függvénnyel egyenértékű működést így érhetünk el:
usort($tomb, "osszehasonlit");
Itt a függvény feltételezi, hogy van a környéken egy osszehasonlit() nevű függvény, amit már megírtunk. Ennek a függvénynek a következőképpen kell viselkednie. Két paramétert vár, amik közül el kell döntenie, hogy melyik a nagyobb. Ha az első paraméter a nagyobb, akkor a visszatérési értékének 1-nek kell lennie, ha a második a nagyobb, akkor -1-nek. Ha a két paraméter egyenlő, akkor 0-t kell visszaadnia. Ha a sort()-tal egyező működést akarunk, és feltételezzük, hogy a $tomb csak számokat tartalmaz, akkor az alábbi összehasonlító függvényt használhatjuk:
function osszehasonlit($a, $b){
if ($a > $b){
return 1;
}
if ($a < $b){
return -1;
}
return 0;
}
A paraméterek elnevezése tetszőleges. A fentieknek megfelelően, ha az első nagyobb, 1-et adunk vissza, ha a második, akkor -1-et. Ha egyik if ág sem hajtódott végre, akkor a két paraméter egyenlő, ekkor visszaadunk 0-t.
Az usort() ismeretében nincs más dolgunk, mint megírni egy összehasonlító függvényt, amely két karakterláncot kap paraméterként, amikről el kell döntenie, hogy melyik jön később az abc-sorrendben. Amelyik később jön, az a nagyobb. Először valósítsuk meg olyan karakterláncokra, amik csak egy betűből állnak. Ebben az esetben két betűről kellene eldönteni, hogy az abc-ben melyik jön előbb, illetve később. Talán az első ötlet ami kipattanhat a fejünkből, valamilyen else-if vagy switch szerkezetekből összetákolt monstrum lehetne, amiben minden lehetséges betűpár összehasonlítása szerepelne, és ezek alapján dőlne el a visszatérési érték. Ez nem tűnik túl jó ötletnek, de nem véletlenül tanultuk ebben a leckében a {} operátort!
Például készíthetünk egy karakterléncot, amiben felsoroljuk a karaktereket a magyar abc-nek megfelelő sorrendben, majd amelyik karakternek kisebb az indexe (előbb szerepel a karakterláncban) az a kisebb. Egyenlőre foglalkozzunk csak a kisbetűkkel!
function comp($a, $b){
$abc = "aábcdeéfghiíjklmnoóöőpqrstuúüűvwxyz";
$len_abc = strlen($abc);
for ($k = 0; $k < $len_abc; ++$k){
if ($a == $abc{$k}){
$loc_a = $k;
}
if ($b == $abc{$k}){
$loc_b = $k;
}
}
if ($loc_a > $loc_b){
return 1;
}
if ($loc_a < $loc_b){
return -1;
}
return 0;
}
A feladat egyszerűen hangzik, és a program is valójában egyszerű, csak első ránézésre ijesztő lehet. Tulajdonképpen csak annyi történik, hogy a for-ciklusban végigjárjuk az $abc karakterláncot, hogy megkeressük a két paraméter helyét. Az $a helye (vagyis az indexe) bekerül a $loc_a változóba, így ez megadja, hogy a paraméter az abc hanyadik betűje. Hasonlóan, a $loc_b változóba a második paraméter indexe kerül. Ezután már csak össze kell hasonlítani a $loc_a és $loc_b egész számokat, és ezek alapján visszaadni a megfelelő visszatérési értéket.
Ahhoz, hogy tetszőleges hosszúságú karakterláncokat is össze tudjunk hasonlítani, csak annyit kell tennünk, hogy a fenti függvényt végigfuttatjuk a karakterláncok karakterein. Egyszerűen csak be kell raknunk egy ciklusba a fenti függvény törzsét, ami addig fut, amíg az egyik karakterlánc végére nem érünk. Vagyis egy ilyen ciklusba kell beágyazni a függvény törzsét:
$len_a = strlen($a);
$len_b = strlen($b);
for ($n = 0; $n < $len_a && $n < $len_b; ++$n){
...
}
A két if ág is bele fog kerülni ebbe a ciklusba, mivel mindkét karakterláncon párhuzamosan haladunk, és ha elérkezünk egy olyan karakterpárhoz, amik már különböznek, akkor eldőlt, hogy melyik karakterlánc a nagyobb. A return 0; utasítást viszont ki kell szednünk, különben az első karakterpárnál leállna a ciklus. Ha a ciklusból kikerülünk anélkül, hogy a függvényből kiléptünk volna, az azt jelenti, hogy az egyik karakterlánc megegyezik a másik elejével. Ekkor az jön később az abc-ben, amelyik hosszabb, vagyis ilyenkor a $len_a és $len_b változók összehasonlításával döntjük el a visszatérési értéket. A függvény tehát így néz ki:
function comp($a, $b){
$abc = "aábcdeéfghiíjklmnoóöőpqrstuúüűvwxyz";
$len_abc = strlen($abc);
$len_a = strlen($a);
$len_b = strlen($b);
for ($n = 0; $n < $len_a && $n < $len_b; ++$n){
for ($k = 0; $k < $len_abc; ++$k){
if ($a{$n} == $abc{$k}){
$loc_a = $k;
}
if ($b{$n} == $abc{$k}){
$loc_b = $k;
}
}
if ($loc_a > $loc_b){
return 1;
}
if ($loc_a < $loc_b){
return -1;
}
}
if ($len_a > $len_b){
return 1;
}
if ($len_a < $len_b){
return -1;
}
return 0;
}
Már csak az maradt hátra, hogy megfelelően kezeljük a nagybetűket is. Úgy kell megoldani ezt, hogy a kis- és nagybetűk egyenértékűek legyenek a rendezés szempontjából. Ezt többféle módon lehet csinálni (persze ez az eddigi problémákra is igaz volt), most mutatok egy lehetséges módot. Az egész összehasonlítás lényege tulajdonképpen a belső for-ciklus magjában van, ahol meghatározzuk egy karakter helyét az abc-ben. Azt kell elérnünk, hogy a nagybetűk abc-beli helye ugyanott legyen, mint a neki megfelelő kisbetűé, és ezt ebben a ciklusmagban kell meghatározni. Nézzük meg az első if-ág feltételét! Ha ($a{$n} == $abc{$k}) teljesül, akkor az $a{$n} karakter az abc $k-adik betűje. Ki kell egészítenünk a feltételt a nagybetűk esetére. Létrehozzuk az $ABC karakterláncot, ami a nagybetűk abc-sorrendjét tartalmazza, majd megvizsgáljuk a feltételben, hogy az $a{$n} karakter a nagybetűk abc-jének $k-adik eleme. Vagyis a feltétel így fog kinézni:
if ($a{$n} == $abc{$k} || $a{$n} == $ABC{$k}){
$loc_a = $k;
}
Ez azt jelenti, hogy ha az $a{$n} karakter a kisbetűk vagy a nagybetűk abc-jének $k-adik eleme, akkor a karakter helye az abc-ben $k. Ez persze csak akkor működik jól, ha az $abc és $ABC karakterláncok azonos sorrendben tartalmazzák a kis- és nagybetűket. A teljes összehasonlító függvény tehát így néz ki:
function comp($a, $b){
$abc = "aábcdeéfghiíjklmnoóöőpqrstuúüűvwxyz";
$ABC = "AÁBCDEÉFGHIÍJKLMNOÓÖŐPQRSTUÚÜŰVWXYZ";
$len_abc = strlen($abc);
$len_a = strlen($a);
$len_b = strlen($b);
for ($n = 0; $n < $len_a && $n < $len_b; ++$n){
for ($k = 0; $k < $len_abc; ++$k){
if ($a{$n} == $abc{$k} || $a{$n} == $ABC{$k}){
$loc_a = $k;
}
if ($b{$n} == $abc{$k} || $b{$n} == $ABC{$k}){
$loc_b = $k;
}
}
if ($loc_a > $loc_b){
return 1;
}
if ($loc_a < $loc_b){
return -1;
}
}
if ($len_a > $len_b){
return 1;
}
if ($len_a < $len_b){
return -1;
}
return 0;
}
Ha úgy gondoljuk, hogy megalkottuk a megfelelő összehasonlító függvényt, nincs más hátra, mint alaposan letesztelni. A tesztelést például így végezhetjük el:
$tomb = array(...); usort($tomb, "comp"); print "<pre>"; print_r($tomb); print "</pre>";
A ... helyén valamilyen ékezetes betűkben bővelkedő karakterláncokat tartalmazó tömböt kell létrehozni. Valójában a függvényre még mindig ráférne egy kis fejlesztés, például nem viselkedik valami jól, ha a karakterlánc olyan karaktert tartalmaz, ami egyik abc-ben sem szerepel (például szám, szóköz, esetleg valamilyen írásjel). Ilyenkor az if feltétele nem teljesül, így a $loc_a vagy a $loc_b változóban még az előző ciklusmag lefutásából származó érték marad meg.
Leginkább azért mutattam meg ezt a programot, hogy lássuk, mennyi problémát meg tudunk már oldani az eddig tanult eszközök segítségével. Persze egy ilyen súlyú probléma esetén jó sokat kell gondolkodni, meg nem árt egy kis gyakorlat, ha egy viszonylag egyszerű és használható megoldást szeretnénk találni. A házi feladat azért nem lesz ilyen nehéz!
Mivel ezt a függvényt csak illusztrációként mutattam meg, ezért semmi garancia sincs arra, hogy az összehasonlító függvénynek ez a létező legegyszerűbb (főleg nem leggyorsabb) alakja, ami itt látható. Még az is lehet, hogy a PHP-ben van olyan beépített függvény, ami normálisan rendezi az ékezetes karakterláncokat, csak én nem tudok róla...
Házi feladat
1.) Írd meg a substr() függvényt úgy, hogy a beépített függvények közül csak az strlen() függvényt használod. Próbáld meg megvalósítani az ebben a leckében leírt módon, hogy kezelje azt az esetet is, amikor a második paraméter negatív szám!
Először nézzük az egyszerűbb esetet, vagyis ha a második paraméter pozitív! A feladat tehát az, hogy adjuk vissza a $string karakterlánc $kezdet indexű karakterétől kezdődő, $hossz hosszúságú részét. Ezt megtehetjük például az alábbi ciklussal:
function substring($string, $kezdet, $hossz){
$ret = "";
for ($n = $kezdet; $n < $kezdet + $hossz; ++$n){
$ret .= $string{$n};
}
return $ret;
}
Itt a $ret karakterláncba berakosgatjuk azokat a karaktereket, amik a $kezdet és a $kezdet + $hossz indexek között vannak, majd ezt adjuk vissza.
Ha a $kezdet negatív, akkor a ciklusváltozó ($n) kezdőértékét úgy kell megadni, hogy az strlen($string) + $kezdet legyen, mivel ilyenkor ez lesz a visszaadandó részlánc első karaktere. Vagyis a ciklus előtt egy elágazással eldöntjük, hogy mi legyen a ciklusváltozó kedőértéke. Mivel ekkor a for-ciklus első ciklusvezérlő utasítása üres lesz, inkább átírom while-ciklussá:
function substring($string, $kezdet, $hossz){
$ret = "";
if ($kezdet >= 0){
$n = $kezdet;
}
else{
$n = strlen($string) + $kezdet;
}
while ($n < $kezdet + $hossz){
$ret .= $string{$n};
++$n;
}
return $ret;
}
Ha meg szeretnénk valósítani azt, hogy a harmadik paraméter elhagyható legyen, akkor kell neki adni egy alapértelmezett értéket (ld. 14. lecke). Az alapértelmezett értéknek ebben az esetben azt kell eredményeznie, hogy a karakterlánc végéig tart a visszaadandó részlánc. Így a $hossz változónak strlen($string) - $kezdet akapértelmezett értéket kellene adni. Csakhogy ha ezt megpróbáljuk beírni a paraméterlistába, egy szép kis hibaüzenetet fogunk kapni, alapértelmezett értéknek ugyanis nem lehet változót, vagy változókból álló összetett kifejezést megadni. Itt egy olyan számot érdemes alapértelmezett értéknek választani, amit egyébként nem használnánk, például a nullát, vagy egy negatív számot. Mondjuk válasszuk a nullát, majd ha a paraméter értéke egyezik az alapértelmezett értékkel, akkor a függvény törzsében már beállíthatjuk neki a kívánt értéket:
function substring($string, $kezdet, $hossz = 0){
if ($hossz == 0){
$hossz = strlen($string) - $kezdet;
}
$ret = "";
if ($kezdet >= 0){
$n = $kezdet;
}
else{
$n = strlen($string) + $kezdet;
}
while ($n < $kezdet + $hossz){
$ret .= $string{$n};
++$n;
}
return $ret;
}
Ha a harmadik paramétert elhagyjuk, vagy nullát adunk neki, akkor a visszaadott részlánc a karakterlánc végéig fog tartani.
2.) Az strstr() függvény a részláncnak csak az első előfordulási helyét keresi meg. Írj egy olyan függvényt, ami visszaadja egy részlánc minden előfordulási helyének pozícióját! A visszatérési érték lehet például egy egész számokból álló tömb. Egy példa:
$pos = search("Már várják a fiúk 500000 volt tiszta árammal!", "ár");
Itt a $pos egy tömb legyen, amibe az 1, 5, 37 számok kerülnek! Nyugodtan használhatod az itt megismert függvényeket.
A lényeg az, hogy az strstr() visszaadja a karakterlánc végét az első találati helytől számítva. Vagyis például az strstr("abcdefcde", "cd"); esetben a visszatérési érték "cdefcde". A megoldás az, hogy erre újra ráengedjük az strstr()-t. Pontosabban nem erre, mert a 0-s pozícióban ott van a keresett részlánc, így végtelen ciklusba kerülnénk. Tehát először levágjuk az első karaktert, majd utána engedjük rá: strstr("defcde", "cd"); Ekkor a visszatérési érték "cde". Ezzel elvégezve újra a műveletet: strstr("de", "cd"); a visszatérési érték false lesz, ekkor leállítjuk a ciklust.
function search($hosszu, $resz){
$pos = array();
$maradek = $hosszu;
while (($len = strstr($maradek, $resz)) !== false){
$pos[] = strlen($hosszu) - strlen($len);
$maradek = substr($len, 1);
}
return $pos;
}
A ciklus feltételében egy értékadás és egy feltételvizsgálat is szerepel. Egyrészt meg kell vizsgálni az strstr($maradek, $resz) !== false feltételt. Ugyanakkor a visszatérési értéket be kell rakni a $len változóba, mert a ciklusmagban szükség lesz rá. Ahelyett, hogy ott újra meghívnánk a függvényt, az értékadást elvégezhetjük a ciklusfeltételben is: $len = strstr($maradek, $resz). Ennek a kifejezésnek az értéke az lesz, ami a $len változóba került, vagyis az strstr() visszatérési értéke (ld. 8. lecke).







