Forritunargátan
Það var lögð fyrir mig forritunargáta áðan sem er svona:
if (substr($fjoldi, strlen($fjoldi) - 1, 1) == 1
&& substr($fjoldi, strlen($fjoldi) - 2, 1) != 1)
Hvað gerir þetta og í hvað er það notað?
Svarið er sennilega ekki augljóst en það var það fyrir mig vegna þess að ég hef gert þetta áður. Þetta athugar hvort að síðusta stafurinn í tölu sé 1 og hvort að næst síðasti stafurinn sé það ekki.
Þetta er notað til þess að athuga hvort að orð eru í fleirtölu í íslensku. Töluorð sem enda á 1 stýra eintölu nema ef þau enda á 11, þá krefjast þau fleirtölu.
Eina vandamálið er að þessi kóði virkar ekki. Hann klikkar ef hann fær töluna 1 inn.
Vandamálið er undarleg hegðun í PHP sem veldur því að ef byrjunin á streng sem á að klippa úr öðrum lendir fram fyrir byrjun strengsins þá virðist vera talið frá fyrsta staf.
return substr("test", -16, 1) // skilar "t".
Það er svosem hægt að komast hjá þessu vandamáli með því að skella t.d. bili framan á strenginn áður en hann er metinn, en það er ekki alvöru lausn.
Mér finnst besta leiðin til þess að gera þetta vera reikniaðferð. Þá er þetta gert svona:
function is_plural($val) {
return (($val-1) % 10) && (($val-11) % 100);
}
Verði ykkur að góðu. :-)
Uppfært: 22. Maí 2006:
Ég lagaði bæði færsluna og einfaldaði kóðann örlítið. Það má einnig skrifa þetta svona:
function is_plural($val) {
return !(($val % 10) == 1) && (($val % 100) !== 11);
}
Það verður örlítið lengri kóði í PHP, en í öðrum forritunarmálum gæti þetta verið styttra.

5 ummææli við “Forritunargátan”
Nú vil ég mótmæla harðlega, þar sem upphaflegi kóðinn er allt öðruvísi en þú birtir hann, það sem ég sendi frá mér höndlaði töluna 1.
Það viðurkennist hins vegar að fallið sem þú lætur fylgja í lokin er fallegri leið til að sama marki.
Frank Cassata skrifaði 24.5.2005 12:11
Ég skrifaði þetta bara hratt eftir minni og var ekkert að athuga hvort þetta yfirleitt virkaði eða ekki. Ég hef lagað kóðann í spurningunni yfir í það sem ég fékk upprunalega í hendurnar (að ég held, ég er ekki með log) og prufað hann.
Hann virkar ekki á 1 í PHP 5.0.4. Ég er búinn að gera fleiri tilraunir og hef komist að ýmsu undarlegu í strengjameðhöndlun.
T.d. virkar $fjoldi{-2} ekki neitt og $fjoldi{strlen($fjoldi)-2} virkar bara rétt ef $fjoldi er þegar strengur fyrir, en það veldur notice meldingu.
Ef það þarf hvort eð er að breyta þessu í streng væri líka hægt að gera þetta svona: return !(preg_match("/[^1]1$/", " $fjoldi"));
Þetta er ákaflega óþægilegt ósamræmi í málinu sem ætti ekki að vera til staðar. $str{-8}, substr($str, -1000 ,1), o.s.frv. ættu auðvitað að vera að skila "" eða Null eða bara einhverju öðru en fyrsta staf. :-|
Mér dettur í hug að misræmið í þessu hjá okkur sé því að kenna að strengjameðhöndlun hefur verið "löguð" á milli útgáfa. Sem er þá enn betri ástæða til þess að fara reiknileiðina.
Ég var annars ekkert að áfellast þig neitt. Ég vildi með þessu annars vegar vekja athygli á undarlegri hegðun PHP og hins vegar pósta aðferð sem virkar fullkomlega svo sem flestir geti notið góðs af grúskinu. :-)
Borgar skrifaði 24.5.2005 12:49
Sæll aftur, mistökin voru hjá mér, ég peistaði vitlausri útgáfu af þessu if-skilyrði á hann Krilla. Mótmælin eru því snarlega dregin til baka. Það sem ég var með er svona:
if (substr($fjoldi, strlen($fjoldi)-1,1) == 1 && substr($fjoldi, strlen($fjoldi)-2,1) != 1 || $fjoldi == 1)
sem höndlar töluna 1, en angar af skítmixi. Þín aðferð er klárlega sú betri.
En þú færð líka hrós fyrir að hafa verið önnur manneskjan sem skilur af því einu að horfa á línuna hvað hún gerir. Á anna tug forritara hafa séð þetta hjá mér og gapað, aðeins þú og Krilli hafa fattað þetta, til hamingju =)
Frank Cassata skrifaði 24.5.2005 16:50
Rúst!
krilli skrifaði 25.5.2005 0:09
Það er eitthvað voðalega fallegt við þetta sem ég á erfitt með að útskýra en lætur mér líða vel. Ég tel heiminn núna betri stað:)
Jonni skrifaði 25.5.2005 1:03