Différentes fonctions permettent de faire des recherches de caractères ou de chaînes à l'intérieur d'une chaîne.

Parmi toutes les fonctions de recherche, les plus employées sont :

- strpos() qui renvoie la position d'une sous-chaîne à l'intérieur d'une chaîne,
- strrpos() qui renvoie la dernière position d'un caractère à l'intérieur d'une chaîne,
- strstr() qui renvoie une partie de chaîne à partir de la position d'une sous-chaîne
- stristr() est identique à strsstr, mais ignore les différences majuscules/minuscules
- strrchr() qui renvoient une partie de chaîne à partir de la dernière position d'un caractère à l'intérieur d'une chaîne.

ATTENTION IMPORTANT

Toutes les fonctions de recherche retournent FALSE si elles ne trouvent pas ce qu'elles cherchent. Afin d'éviter de confondre le 0 de FALSE et le 0 de la position du premier caractère d'une chaîne, il faut toujours tester le résultat de ces fonctions avec l'opérateur d'identité === et pas avec l'opérateur d'égalité ==.

Soit le code suivant :

    $x = 'François';
    $pos = strpos($x, 'F');

$pos sera égal à 0, car 'F' est à la position 0 dans la chaîne $x.

Le test avec l'opérateur d'égalité simple :

    if ($pos == false) { ...

ne permettra pas de faire la différence entre le nombre 0 et le booléen FALSE. Le script sera donc faux car il considérera que 'F' n'a pas été trouvé dans 'François'.
Pour éviter le transtypage automatique de l'opérateur d'égalité simple et bien récupèrer le booléen FALSE ou le nombre 0, il faut tester la valeur de retour de la fonction avec l'opérateur d'identitié :

    if ($pos === false) { ...

Exemple : rechercher dans une chaîne
<?php require('bib_fonctions.php'); htmlDebut('Recherches'); $x = 'Le langage PHP'; echo '<h4>Chaîne de test</h4>', $x; echo '<h4>Position de "langage"</h4>', strpos($x, 'langage'); echo '<h4>Position du premier"e"</h4>', strpos($x, 'e'); echo '<h4>Position du dernier "e"</h4>', strrpos($x, 'e'); echo '<h4>Renvoie une chaîne à partir de "langage"</h4>', strstr $x, 'langage'); echo '<h4>Renvoie une chaîne à partir du premier "e"</h4>', strstr($x, 'e'); echo '<h4>Renvoie une chaîne à partie du dernier "e"</h4>', strrch ($x, 'e'); htmlFin(); ?>

PHP permet de rechercher la dernière position d'un caractère dans une chaîne, mais n'offre pas de fonction permettant de rechercher la dernière position d'une sous-chaîne dans une chaîne. Pour réaliser ce travail, nous pouvons utiliser la fonction strrev() qui inverse l'ordre des caractères dans une chaîne.

Exemple : recherche de la dernière sous-chaîne
<?php require('bib_fonctions.php'); htmlDebut('La dernière sous-chaîne'); $x = 'ce bonbon est bon et même délicieux'; echo strLastStr($x, 'bon'); //--------------------------------------------------------- function strLastStr($boteDeFoin, $aiguille) { if ($boteDeFoin == '' || $aiguille == '') { return false; } $pos = strpos(strrev($boteDeFoin), strrev($aiguille)); if ($pos === false) { return false; } $pos = strlen($boteDeFoin) - $pos - strlen($aiguille); return $pos; } htmlFin(); ?>

### Exercice : tester une adresse e-mail

Ecrivez la fonction exo_isAdresseMail qui vérifie qu'une adresse email est composée de :

- au moins un caractère alphabétique, suivi éventuellement d'autres caractères
- le caractère @
- au moins un caractère alphabétique, suivi éventuellement d'autres caractères
- le caractère .
- de deux à quatre caractères alphabétiques

La chaîne ne doit contenir aucun espace.
Il ne peut y avoir qu'un caractère @
Les caractères doivent avoir l'un des codes ASCII suivants :

- 45 : -
- 46 : .
- 48 à 57 : 0 à 9
- 64 à 90 : @, A à Z
- 95 : _
- 97 à 122 : a à z

Exemples à tester :
piat@univ-fcomte.frfr
piat@lifc.univ-fcomte.fr
piatunifc-fcomte.fr
piat@univfcomte-fr

Une solution possible

Exercice : tester une adresse e-mail
<?php require('bib_fonctions.php'); /** * Teste si une chaîne est une adresse e-mail * * @param string $txt chaîne à tester * @return boolean true si adresse mail */ function exo_isAdresseMail($txt) { // des espaces ? if (strpos($txt,' ') !== false) { return false; } // un arobase et un seul if (substr_count($txt, '@') != 1) { return false; } //premier caractère alpha if (!is_alpha($txt{0})) { return false; } //un point ? $pos = strrpos($txt,'.'); if ($pos === false) { return false; } // au moins 1 caractère alpha avant le . if (!is_alpha($txt{$pos - 1})) { return false; } // caractères après le . $fin = substr($txt,$pos + 1); $long = strlen($fin); if ($long < 2 || $long > 4) { return false; } for ($i = 0; $i < $long; $i++) { if (!is_alpha($fin{$i})) { return false; } } // pas de caractères interdits ? for ($i = 0; $i < $pos; $i++) { if (is_alpha($txt{$i})) { continue; } $c = ord($txt{$i}); if ($c > 44 && $c < 47) { continue; // - et . } if ($c > 47 && $c <58) { continue; // 0 à 9 } if ($c == 64 || $c == 95) { continue; // @ et _ } return false; } return true; } /** * Teste si un caractère est alphabétique * * @param string $c caractère à tester * @return boolean true si alpha */ function is_alpha($c) { $c = ord($c); if ($c > 64 && $c < 91) { return true; } if ($c > 96 && $c < 123) { return true; } return false; } //--------------------------------------------------------- htmlDebut('Tester une adresse e-mail'); tester('exo_isAdresseMail', 'piat@univ-fcomte.frfr', TRUE); tester('exo_isAdresseMail', 'piat@univ-fcomte.fr', TRUE); tester('exo_isAdresseMail', 'piatunifc-fcomte.fr', FALSE); tester('exo_isAdresseMail', 'piat@univfcomte-fr', FALSE); htmlFin(); ?>

Vous serez sans doute surpris à la lecture du code par l'utilisation de la fonction tester. C'est une fonction qui se trouve dans la bibliothèque bib_fonctions.php et qui permet comme son nom l'indique de tester si une fonction renvoie le résultat attendu.
Cette fonction accepte au minimum 3 paramètres :

- le nom de la fonction à tester sous la forme d'une chaîne de caractères
- le ou les paramètres attendus par la fonction à tester
- la valeur de retour de la fonction à tester

Si le résultat renvoyé par la fonction à tester est celui attendu, le nom de la fonction est affiché en vert. Si ça n'est pas le cas, le nom de la fonction est affiché en rouge.

    /**
     * Testeur de fonction
     *
     * @param string	arg[0]		nom de la fonction à tester
     * @param mixed		arg[1 à n-1] paramètres à passer à la fonction
     * @param mixed		arg[n]		résultat attendu
     */
    function tester() {
    	$args = func_get_args();
    	if (count($args) < 3) {
    		echo '<hr>La fonction tester doit avoir ',
    						'au moins 3 paramètres.';
    		return;
    	}

    	$fonction = array_shift($args);
    	$attendu = array_pop($args);
    	$retour = call_user_func_array($fonction, $args);

    	$iMax = count($args);

    	echo '<hr><span style="color:',
    			($retour === $attendu) ? 'green' : 'red', '">',
    			'<b>', $fonction, '</b></span>',
    			'<br>Paramètre', ($iMax > 1) ? 's : ' : ' : ';

    	for ($i = 0; $i < $iMax; $i++) {
    		echo '<span style="background:#ebebeb;margin:0 5px;">';
    		var_dump($args[$i]);
    		echo '</span>';
    	}

    	echo '<br>Attendu : ';
    	var_dump($attendu);

    	echo '<br>Retourné : ';
    	var_dump($retour);
    }