Autor Zpráva
ethernetlord
Profil
Zdravím, mám kousek PHP skriptu, se kterým si nevím rady.

function getNumberOfQuestionMarks($q) {
  $count = substr_count($q, "?");
  $q = str_replace("\\'", "", $q);

  $pos = 0;
  while(TRUE) {
    $pos1 = strpos($q, "'", $pos);
    if($pos1 === FALSE) {
      break;
    }

    $pos2 = strpos($q, "'", ++$pos1);
    if($pos2 === FALSE) {
      throw new Exception("Unclosed single quotes!");
    }

    $substr = substr($q, $pos1, $pos2 - $pos1);
    $fakemarks = substr_count($substr, "?");
    $count -= $fakemarks;

    $pos = ++$pos2;
  }

  return $count;
}

Jedná se o funkci, která má vrátit počet otazníků ve stringu, ale nepočítat ty, které se nacházejí mezi jednoduchými uvozovkami (').
Funkce je řešena tak, jak je napsáno výše a funguje jak má, nicméně se mi tam nelíbí to while(TRUE).

Jde mi o to cyklus ukončit, když se proměnná $pos1 rovná booleanu FALSE (tedy když už se žádné další uvozovky ve stringu nenacházejí), ale cyklus je třeba ukončit hned, jak se hodnota $pos1 zjistí a nevykonávat kód, který se nachází v cyklu pod ní (jinak to nefunguje), což by se stalo, kdybych tu podmínku vložil přímo do do-while cyklu (pokud bych použil while, musel bych proměnnou definovat před začátkem cyklu, aby to neházelo undefined variable a měl bych v tom ještě větší zmatek).

Je to možné řešit nějak bez while(TRUE) nebo klidně i úplně jinak pomocí nějakých jiných funkcí apod.?

Děkuji za odpovědi.
Keeehi
Profil
Dá se to napsat takto, ale nevím, zda ti to přijde čitelnější. Mně tedy ne.
while(($pos1 = strpos($q, "'", $pos)) !== false) {
 
    $pos2 = strpos($q, "'", ++$pos1);
    if($pos2 === FALSE) {
    ...

Já bych to napsal takto
function getNumberOfQuestionMarks($q) {
    $q = preg_replace("~'[^']*'~", '', $q);
    
    if(strpos($q, "'") !== false) {
      throw new Exception("Unclosed single quotes!");
    }
    
    return substr_count($q, "?");
}

Ten preg_replace smaže všechno, co je mezi dvěma, k sobě patřícíma, apostrofy a pak se jen přepočítá počet zbylých otazníků, případně se vyhodí výjimka pokud tam nějaký apostrof zbyl, protože byl lichý.
ethernetlord
Profil
Keeehi:
Díky moc, dělá přesně to, co potřebuju. :-)
S regexama jsem si chvilku pohrával, nicméně nic jsem nevymyslel, tak jsem rád, že je zde někdo, kdo s nima umí, protože zde je příklad toho, jak takto udělat celý zápis funkce 2x jednodušší a 2x kratší.
Keeehi
Profil
ethernetlord:
Regexpy jsou celkem mocné, i když ne všemocné. Kdyby to byly závorky a ne apostrofy, tak už by na to nestačily.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0