Objevil jsem chybu v php (funkce strPos)

obrázek k článku Objevil jsem chybu v php (funkce strPos)Před odjezdem na mou dovoulenou jsem programoval zajímavý script na import dat z xml souboru. Programoval jsem tzv. "antidebilní" script, kde jsem byl nucen použít plno ajaxu a mých vědomostí. Script se mi docela dobře povedlo naprogramovat (aspoň si to myslím, zatím bez velkých ohlasů firmy mírně script upravujeme podle jejich představ). Při programování jsem narazil na chybu samotného php!

Komerční Reklama


Známá php funkce strpos. Funkce která vyhledá pozici nějakého stringu v jiném stringu. Výsledkem je tedy int pozice. Do této funkce zadáváte parametry (string vstupní řetězec, string hledaný řetězec [, int pozice od které začne hledat]).

Funkce skvěle fungující. Problém ovšem nastává pokud řetězec nebyl nalezen. V takovém případě má funkce vracet hodnotu false. Ovšem mě se stalo že řetězec byl na nulté pozici řetězce a výsledkem byla tedy 0. Při podmínce zda výsledek hledání rovná se false, čili zda řetězec nebyl nalezen výsledek byl stejný jak u nulté pozice tak i pokud řetězec nebyl nalezen.

Proč tento problém nastal?
Odpověď je jednoduchá. Díky tomu že v php se proměné automaticky přetypovávají došlo k problému, že po přetypování int na boolen či naopak 0==false a 1==true. Takže pokud jsem se ptal na to zda výsledkem je false vracelo mi to ve dvou případech, pokud řetězec nebyl nalezen a nebo pokud je řetězec na nulté pozici.

Jiné jazyky
Například v C/C++/C# kde tyto funkce existují je výsledkem záporné číslo (-1) pokud řetězec nebyl nalezen. Kdyby php fungovalo stejně nebyl by problém.

Řešení v php
Řešení které mě ve spěchu napadlo (dolaďoval jsem to 20 minut před odjezdem na dovolenou, opravdu jsem měl naspěch) je takovéto:

<?
function strposo($kde,$co,$poc=0)
{
  $pozice = strpos($kde,$co,$poc); //zjištění pozice přes chybnou funkci php
  $vys = true//pomocná proměná pokud true vyhodí výsledek předchozí funkce pokud false vyhodí nenalezeno čili -1
  if($pozice==0) //pokud pozice je 0 nastává zmíněný problém, že řetězec neexistuje nebo je na nulté pozici
  {
   //cyklem procházíme písmeno po písmeno od nulté pozice
   for($i=0;$i<strlen($co);$i++)
   {
    //pokud se písmena nultých pozic nerovnají cyklus ukončíme
    if($co[$i]!=$kde[$i])
    {
     break;
    }
   }
   //zeptáme se zda byl cyklus ukončen, pokud ano víme že na nulté pozici hledaný výraz se nenachází, takže heldaný výraz není v řetězci
   if($i!=strlen($co))
   {
    $vys = false//změníme obsah proměné, výsledkem má být -1
   }
  }
  //otázka jaký výsledek máme vyhodit zda pozici nebo nenalezeno -1
  if($vys == true )
  {
   return $pozice;
  }
  else
  {
   return -1;
  }
}
?>

Vytvořili jsme funkci inspirovanou funkcí z jiných jazyků. Funkce fungující naprosto stejně jako strpos akorát je vychytaný problém. Pokud řetězec nebyl nalezen výsledkem je -1.
Příkladem použití opravené funkce:

<?
$text = "Rád navštěvuji tyto stránky. Chodím na ně pravidelně."//text ve kterém budeme vyhledávat
$hledam = "Rád"//text který vyhledáváme
$pozice = strposo($text,$hledam); //zjistíme pozici pomocí opravené funkce
if($pozice==-1) //otázka zda řetězec se vyskytuje nebo nevyskytuje
{
 echo "Řetězec nebyl nalezen!"//nevyskytuje se
}
else
{
 echo "Řetězec byl nalezen na pozici ".$pozice//vyskytuje se
}
?>



Závěr
Doufám, že jsem někomu ulehčil práci s vymýšlením opravy této funkce a možná jsem inspiroval tvůrce php k budoucí opravě...
Pokud jste nalezli lepší řešení určitě nám ho napiště do komentářů!

Komentáře (6) Programování vitek 25.7.2008 18:49

Ohodnoťte článek: Ohodnotit 1 bodyOhodnotit 2 bodyOhodnotit 3 bodyOhodnotit 4 bodyOhodnotit 5 bodyOhodnotit 6 bodyOhodnotit 7 body (hlasováno: 42×, průměr: 3.4)

MediaBlog.cz Jaggni to ! pošli na vybrali.sme.sk Linkuj si !


Komentáře

fialover (anonym) - To není chyba - 5.8.2008 14:07

avatarZkus:
var_dump(strpos("Ahoj světe", "Ahoj"));
var_dump(strpos("Čau světe", "Ahoj"));

podmínka jestli se tam řetězec nevyskytuje se nechá zformulovat takto:

if(strpos("Čau světe", "Ahoj") === false) echo "řetězec nenalezen";

Komerční Reklama

vitek - nedošlo - 5.8.2008 15:03

avatarj nj v tom spěchu sem uplně na === zapoměl... tak pro příště:)

Swihi (anonym) - Hokus pokus - 13.1.2011 12:21

avatarAhoj rychlejší úprava by mohla být následující:

strpos(" "."Ahoj světe", "Ahoj");

Pokud budeš mít řetězec v proměnné, tak následovně.

strpos(" ".$string, "Ahoj");

jen při vracení pozice od ní odečíst 1, je-li tedy větší než 0.

;)

Uprava tedy bude na dva řádky.

NICK (anonym) - Neni to chyba - 11.8.2011 21:25

avatarMusíš to porovnávat takto:
if(strpos($a,"něco")===false) echo "Něco";

Banké? (anonym) - Lze to i jinak - 30.11.2011 20:00

avatarif(gettype(strpos($a,"něco")) == "integer") {echo "je to vždy pozice nalezeného řetězce";}

ZocZeSYJDF (anonym) - aWeKgdANyH - 18.12.2011 11:35

avatarThis article ahciveed exactly what I wanted it to achieve.

Zobrazit všechny komentáře

Komentáře vyjadřují názory čtenářů. Provozovatel webu neodpovídá ani nenese žádnou zodpovědnost za jejich obsah.