Valid XHTML     Valid CSS2    

Décomposition, Conception et Réalisation d'Applications

T.D. 4 : Expressions régulières, tests et nombres aléatoires

                    gilles.hunault "at" univ-angers.fr

Table des matières cliquable

  1. Le paradigme "Expressions régulières"

  2. Programmation concise en Php

  3. Test d'une page Web par script

  4. Qu'est-ce qu'un installeur local comme npm, gem/bundler, composer et sans doute pip ?

  5. Génération de nombres aléatoires pour tests de charge

  6. Mais que fait ce programme Perl ?

  7. Mais que fait ce programme Java ?

  8. Tester la qualité d'un générateur de nombres aléatoires

Il est possible d'afficher toutes les solutions via ?solutions=1 et de les masquer via ?solutions=0.

 

1. Le paradigme "Expressions régulières"

Les expressions régulières sont un moyen souvent sous-estimé ou sous-utilisé de détecter, extraire et remplacer des blocs de chaines de caractères, blocs éventuellement non contigus. On pourra lire notre tuteur sur les expressions régulières pour se rafraichir les idées sur leur définition et leur utilisation. Pour maitriser le sujet, l'ouvrage suivant est parfait :

non su

Voici donc des exercices pour ces trois types d'actions que fournissent les expressions régulières.

1.1 Paraphrases

Essayer de décrire par des phrases à quoi correspondent les expressions régulières suivantes :

  1. [1-9][0-9]?|100

  2. ^[A-Z][a-z]*$

  3. (^\s+)|(\s+$)

Expliquer ensuite la différence entre les commandes suivantes :


     grep "%AB[^C]" *.txt
     grep "%AB"     *.txt | grep -v "%ABC"
     

1.2 Quelques expressions à trouver

Essayer de trouver des expressions régulières qui correspondent aux descriptions suivantes :

  1. un nombre entier entre 0 et 23, avec éventuellement un 0 non significatif comme 08 pour les nombres inférieurs à 10 (de quoi s'agit-il ?) ;

  2. les anciens et nouveaux numéros de plaques d'immatriculation des voitures en France ;

  3. un email valide.

1.3 Détecter, extraire et remplacer avec des expressions régulières

Voici trois grands standards en expressions régulières :

  1. tester si une chaine est un nombre entier strictement positif ;

  2. extraire la valeur d'un élément input dans une page Web ;

  3. convertir une date française JJ-MM-AAAA en une date internationalisée AAAA-MM-JJ.

Réaliser ces trois opérations dans les langages suivants : Perl, Php, Javascript, R et Python. Afin d'homogéniser le code informatique, on nommera inpAge la chaine censée contenir l'entier, entree l'ensemble de l'élément input (supposé bien formé au sens de XML), et dateFR la date.

Voici des exemples à tester :

Variable Contenu Résultat(s)
inpAge 25 / bof OK / Pas OK
entree <input id='pomme' type='text' value='5' class='demo' /> 5
dateFR 31-08-1957 1957-08-31

On pourra utiliser les sites rubular et regex-tester pour tester les expressions régulières à utiliser, puis le site regex101 pour générer le code associé.

1.4 Un peu de culture sur les expressions régulières

Qu'affichent les commandes suivantes, basées sur Perl et une expression régulière ?


     perl -le '$_=shift ; (1x$_) !~ /^1?$|^(11+?)\1+$/ && print "$_ OUI"'  7
     perl -le '$_=shift ; (1x$_) !~ /^1?$|^(11+?)\1+$/ && print "$_ OUI"' 50
     

Que faut-il déduire de l'instruction MySQL suivante ?


     select if( "ABC" REGEXP "^ABC", 1 , 0 ) ;
     

Solution :  

 

2. Programmation concise en Php

On cherche à trouver le nombre de fois où le mot ANGERS est écrit dans un fichier texte, sachant que le mot peut aussi être écrit Angers ou angers. Pour simplifier le problème, on admettra que ce mot Angers est toujours précédé d'un espace et suivi d'un espace, d'une virgule ou d'un point à moins que ce ne soit en début de ligne ou en fin de ligne.

Donner le code Php qui lit un fichier texte nommé villes.txt supposé présent et qui renvoie le nombre de fois où on trouve ce mot ANGERS. On n'utlisera que les fonctions suivantes : fopen(), fgets(), fclose(), str_replace(), strpos() et substr().

Voici le contenu du fichier villes.txt :


     ANGERS et NANTES sont deux villes de l'ouest de la France.
     Si Angers est dans le département 49, Nantes est dans le 44.
     On peut dire que les universités à Angers, Nantes et le Mans sont des universités actives.
     
     Il n'y a pas de dangers ni de risques à dire qu'angers est une ville où il fait bon vivre.
     Angers, Nantes ou Nantes, Angers ? Difficile à dire.
     

Reprendre l'exercice en utilisant cette fois uniquement les fonctions file_get_contents() et str_replace(), preg_match_all().

Quel code est le plus concis ?

Comment fonctionnent les fonctions array_sum() et array_filter en Php ?

Est-ce que array_filter simplifie la résolution du problème du comptage des occurrences de "ANGERS" ?

Solution :  

 

3. Test d'une page Web par script

Il est assez facile d'écrire des tests pour une application qui s'exécute en ligne de commandes, ou pour tester une classe d'objets, par exe Php avec phpunit. Mais comment tester si une page Web s'affiche correctement ? Comment tester si appuyer sur le bouton Envoyer d'un formulaire Web envoie bien sur la bonne page ?

Essayer de décrire ce que fait le code Python suivant :


     # fichier pythonSelenium.py
     
     from selenium import webdriver
     import time
     
     browser = webdriver.Firefox()
     time.sleep(3)
     browser.maximize_window()
     time.sleep(3)
     browser.get("http://google.fr")
     time.sleep(3)
     
     search_field = browser.find_element_by_name("q")
     search_field.clear()
     search_field.send_keys("pomme")
     search_field.submit()
     
     time.sleep(5)
     browser.quit()
     

Essayer ensuite de comprendre ce que fait le code Python suivant :


     # -*- coding:latin1 -*-
     
     import requests
     import re
     
     try :
        page    = "http://localhost/~gh/internet/Lte/processSignin07.php"
        reponse = requests.post(url=page, data={"usernameSI": "admin","passwordSI": "admin","confirm_passwordSI": "admin"})
        res     = re.search("already taken",reponse.content.decode())
        if (res) :
           print(" OK test inscriptionIncorrectePOST SUCCESS ")
        else :
           print(" NO test inscriptionIncorrectePOST FAILED (2) ")
        # fin de si
     
     except :
        print( " NO test inscriptionIncorrectePOST FAILED (1) ")
     

Quel livre cité en cours détaille ce genre de tests ?

Solution :  

 

4. Qu'est-ce qu'un installeur local comme npm, gem/bundler, composer et sans doute pip ?

Pour installer des logiciels, il faut en général avoir des droits d'administrateur. Certains langages ont des installeurs locaux, comme npm, gem, composer et aussi sans doute pip. Pour quel langage ? Que font-ils exactement, quel en est l'intérêt ?

Solution :  

 

5. Génération de nombres aléatoires pour tests de charge

On voudrait remplir aléatoirement divers champs d'une base de données comme le champ VILLE, le champ AGE, le champ CODE-SEXE. On admettra pour l'instant qu'on se limite aux villes Angers, Paris et Nantes, que l'age est un entier entre 18 et 99, que le code-sexe est limité aux valeurs H et F.

5.1 Génération pseudo-aléatoire avec Php

De quelles fonctions dispose-t-on en Php pour générer de telles valeurs ?

Peut-on facilement générer des valeurs pour les villes avec des contraintes comme «  on veut 80 % de valeurs Paris, 15 % de valeurs Nantes, 5 % de valeurs Angers » ?

Peut-on facilement générer des valeurs pour les ages avec des contraintes comme «  la distribution des valeurs correspond à celle de la France, avec la même moyenne, la même médiane, et le même écart-type » ?

5.2 Modèles statistiques de génération

Quels sont les grands modèles statistiques de distribution de données ?

5.3 Génération pseudo-aléatoire avec R, Python, Php et Javascript

Comment fait-on informatiquement pour générer ces distributions avec les langages cités ?

Solution :  

 

6. Mais que fait ce programme Perl ?

Indiquer ce que produit et ce que calcule le programme Perl ci-dessous :


          0001   die(" il en faut  trois.") unless ($#ARGV>1) ; # faut ce qu'il faut !
          0002
          0003    ($nbobs,$nbtos,$href) = ($ARGV[0],$ARGV[1],$ARGV[2]) ;
          0004    $iobs = 1 ;
          0005
          0006    while ($iobs<=$nbobs) {
          0007      $som  = 0 ;
          0008      $itos = 1 ;
          0009      while ($itos<=$nbtos) {
          0010        $x    = rand() ;
          0011        if ($x>0.5) {
          0012           $x = 1 ;
          0013        } else {
          0014           $x = 0 ;
          0015        } ; # fin de si
          0016        $som += $x ;
          0017        $itos++ ;
          0018      } ; # fin tant que
          0019      $haut = $href ;
          0020      while ($som>$haut) { $haut += $href ; } ;
          0021      $tclass{$haut}++;
          0022      $iobs++ ;
          0023    } ; # fin tant que
          0024
          0025    foreach $v (sort keys %tclass) {
          0026      print sprintf("%05.2f",$v) ;
          0027      print "   ".sprintf("%4d",$tclass{$v})." \n" ;
          0028    } ; # fin pour
     

Que peut-on en conclure sur la lecture de code d'autres programmeurs ?

Solution :  

 

7. Mais que fait ce programme Java ?

Indiquer ce que produit et ce que calcule le programme Java ci-dessous :


     0001 // auteur (gH)
     0002
     0003 //#-#   Fichier simj.java issu de galg -a simj.alg -o java
     0004 //#-#  ===================================================
     0005
     0006 class simj {
     0007
     0008    import java.io.* ;
     0009    class simja {
     0010
     0011       public static void main(String args[]) {
     0012
     0013       int     nbobs, nbtos ;
     0014       int     mclass, iobs, itos, clas ;
     0015       double  href, haut, x,som ;
     0016       int[]   tclass ;
     0017
     0018
     0019       ///////////////////////////////////////////////////////////////
     0020
     0021        ... lignes pour initialiser le tableau et gérer les paramétres
     0022
     0023       ///////////////////////////////////////////////////////////////
     0024
     0025
     0026       mclass = 0 ;
     0027       iobs = 1 ;
     0028
     0029       while ((iobs <= nbobs)) {
     0030         som = 0 ;
     0031         itos = 1 ;
     0032         while ((itos <= nbtos)) {
     0033           x = randNorm() ;
     0034           som = som + x * x ;
     0035           itos = itos + 1 ;
     0036         } ; // sur itos
     0037         haut = href ;
     0038         clas = 0 ;
     0039         while ((som > haut)) {
     0040            haut = haut + href ;
     0041            clas = clas + 1 ;
     0042         } ; // sur som>haut
     0043         tclass[clas] = tclass[clas] + 1 ;
     0044         if (clas > mclass) {
     0045            mclass = clas ;
     0046         } ; // clas > mclass
     0047         iobs = iobs + 1 ;
     0048       } ; // sur iobs
     0049
     0050       for (int indi=1; indi<=mclass; indi++) {
     0051          System.out.println(format( indi, 3 )+" : "+format( tclass[indi], 5 )) ;
     0052       } ; // indi
     0053
     0054    } // fin de la méthode main()
     0055
     0056 } // fin de la classe simj
     0057
     0058 //#-#   Fin de traduction pour simj.java via de galg -a simj.alg -o java
     

Solution :  

 

8. Tester la qualité d'un générateur de nombres aléatoires

Comment tester la qualité d'un générateur de nombres aléatoires ? Peut-on garantir qu'un générateur de nombres aléatoires fournit de "bons" nombres pour la cryptographie ?

Solution :  

 

       retour au plan de cours  

 

Code-source PHP de cette page ; code Javascript associé.

 

retour gH    Retour à la page principale de   (gH)