Corebreaker | Déjà juste un avis, qui tiens qu'à moi.
Aux ligne 14 et 22 de ton code, les tests sur les booléens suffisent plutôt qu'une comparaison avec les constantes true et false. Les comparaisons sont superflus. Un simple test (ex: if Trouve then). De plus, ainsi l'expression ressemble plus à une phrase:
Code :
- if Dans(Indice) /= ' ' and not Trouve then
|
se traduit par: si Dans(Indice) n'est pas un espace et un mot pas trouvé alors...
Voilà ça ressemble pour moi à une phrase bien formé ce qui est dans l'esprit du langage ADA à été fait justement pour qu'un programme se lise comme une série de phrases.
Avant de voir ton problème, il y a une petite erreur à la ligne 31 de ton code:
Code :
- for Indice2 in (Dans'First + Indice -1)..Dans'Last loop
|
La partie "(Dans'First + Indice -1)" est erronnée.
En effet, la variable Indice est déjà dans l'intervalle Dans'First..Dans'Last à cause du "for" englobant.
La varible Indice n'est pas un offset (décalage) par rapport à Dans'First. Donc ceci est mieux:
Code :
- for Indice2 in Indice..Dans'Last loop
|
Pour ton problème maintenant.
Le problème de l'échec du test 5 vient du fait que la ligne 35 de ton code est exécuté plusieurs fois, ce qui écrase la valeur précédente. Donc en fait, l'argument Fin prends succéssivement les valeur 8, 9, 10 et 11 à chaque itération de la boucle. La valeur correcte 8 est bien afectée, mais est ecrasée ensuite. Il te faut une condition d'arrêt, c'est à dire un test qui disent si l'index de fin est trouvé.
De plus le test de la ligne 25 me parrait inutile, car il a l'air d'être une optimisation sans doute dans un souci d'une exécution plus rapide en enlevant des cas traités. Mais ce test ligne 25 offre une différence de comportement quand tu as plusieurs mots. Ton test unitaire 6 retroune un indice de fin différent si tu rajoute juste un espace à la fin de la chaine testée. A mon avis ce n'est pas ce que tu espérais, cela viens justement du test ligne 25.
Si pour autant tu souhaite concerver ce test, il te faut en fait partir de la fin de la chaine dans la boucle imbriquée (for Indice2) et remonter la chaine à l'envers pour trouvé le premier caractère qui ne soit pas un espace, cependant le test disparait au dépend justement de la boucle.
Je te poste 4 solutions:
1. Correction pour que cela fonctionne.
2. Correction plus complete en enlevant le test ligne 25
3. Autre correction plus complète avec un comportement homogène avec le test ligne 25 dans le cas où la chaine traitée a un espace à la fin.
4. Une solution plus performante.
Pourquoi la solution 4, car ton utilisation des boucles FOR, n'est pas une erreur en soit, puisque ça marche, mais si tu regarde attentivement, tu pourras voir des itérations dite poubelles, ces itérations, ne font rien, ne servent à rien, elles bouffent inutilement du temps de calcul. Et en plus, ces itérations "poubelle" introduit souvent des erreurs comme c'est le cas avec ton problème, donc comme avec le problème d'écrasement. En fait, ton problème de départ qui fait que le test unitaire 5 est erroné, est ce qu'on appelle justement un effet de bord qui n'est pas maitrisé.
De plus c'est assez visible, car le nombre de tests (if) dans la solution 4 est reduit au strict minimum.
Tu pourras faire des tests de vitesse, pour t'en convaincre, par exemple avec un ou plusieurs mots très longs, de mettre tes tests unitaire dans une boucle à 100000 itérations ou simplement de lancer plusieurs fois le même programme plusieurs fois (mais ce n'est pas très fiable comme test de vitesse).
Dans la solution 4, j'ai choisi de suivre l'idée de la solution 2, c'est à dire que l'index de fin pour le test unitaire 6 soit la in du premier mot. Ainsi on peut découper le texte en mots en appelant plusieurs fois la procédure Chercher_Mot, ce qui correspond pour moi au nom de la procédure: on cherche un mot. La solution 3 ressemble à une fonction Trim qui cherche à enlever les espaces de début et de fin.
Dans la solution 4, j'utilise la fonction Ada.Characters.Handling.Is_Alphanumeric plutôt que tester un simple espace, ainsi le mot découpé ne devrait contenir que des lettres et des chiffres et pas les retours à la ligne, les caractère de tabulation et des signes de ponctuation.
A la place de la fonction Ada.Characters.Handling.Is_Alphanumeric tu peux ainsi utiliser une autre fonction que tu veux pour sélectionner les caractères que tu veux dans le mot découpé. Tu peux aussi par la même occasion faire de la procédure Chercher_Mot une procédure générique avec comme paramètre une fonction de sélection des caractères.
Cette procédure Chercher_Mot est ainsi très proche des fonction strtok en C/C++ ou de la classe java.util.StringTokenizer en java si tu connais.
Solution 1: Code :
- with Ada.Text_IO, Ada.Integer_Text_IO;
- use Ada.Text_IO, Ada.Integer_Text_IO;
- procedure programme is
- procedure Chercher_Mot (Dans: in String; Trouve: out Boolean; Deb, Fin: out Positive) is
- Fin_Trouvee : Boolean := False;
- begin
- Trouve := False;
- for Indice in Dans'First..Dans'Last loop
- if Dans(Indice) /= ' ' and not Trouve then
- Deb := Indice;
- Fin := Indice;
- Trouve := True;
- end if;
- if Trouve and not Fin_Trouvee then
- if Dans(Dans'Last) /= ' ' then
- Fin := Dans'Last;
- Fin_Trouvee := True;
- else
- for Indice2 in Indice..Dans'Last loop
- if not Fin_Trouvee and Dans(Indice2) = ' ' then
- Fin := Indice2 - 1;
- Fin_Trouvee := True;
- end if;
- end loop;
- end if;
- end if;
- end loop;
- end Chercher_Mot;
- -- Test unitaire
- procedure Tester_Chercher_Mot is
- Mot_Trouve : Boolean;
- Indice_Deb,
- Indice_Fin : Positive;
- begin
- -- Cas 1 : Chaine nulle
- Chercher_Mot("", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put ("T1: Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T1:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 2: Chaine de longueur > 0 qu'avec des espaces
- Chercher_Mot(" ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T2: Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T2:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 3: Chaine contenant un mot, sans espaces
- Chercher_Mot("Bonjour!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T3:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T3:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 4: Chaine comportant un mot precede par des espaces
- Chercher_Mot(" Bonjour!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T4:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T4:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 5: Chaine comportant un mot suivi d'espaces
- Chercher_Mot("Bonjour! ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T5:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T5:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 6: Chaine comportant deux mots separes par des espaces
- Chercher_Mot("Bonjour! Bye!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T6:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T6:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 7: Chaine comportant deux mots separes par des espaces et un espace à la fin
- Chercher_Mot("Bonjour! Bye! ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T7:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T7:Mot non trouve!" );
- New_Line;
- end if;
- end Tester_Chercher_Mot;
- begin
- Tester_Chercher_Mot;
- end programme;
|
Solution 2: Code :
- with Ada.Text_IO, Ada.Integer_Text_IO;
- use Ada.Text_IO, Ada.Integer_Text_IO;
- procedure programme is
- procedure Chercher_Mot (Dans: in String; Trouve: out Boolean; Deb, Fin: out Positive) is
- Fin_Trouvee : Boolean := False;
- begin
- Trouve := False;
- for Indice in Dans'First..Dans'Last loop
- if Dans(Indice) /= ' ' and not Trouve then
- Deb := Indice;
- Fin := Indice;
- Trouve := True;
- end if;
- if Trouve and not Fin_Trouvee then
- for Indice2 in Indice..Dans'Last loop
- if not Fin_Trouvee and Dans(Indice2) = ' ' then
- Fin := Indice2 - 1;
- Fin_Trouvee := True;
- end if;
- end loop;
- end if;
- end loop;
- end Chercher_Mot;
- -- Test unitaire
- procedure Tester_Chercher_Mot is
- Mot_Trouve : Boolean;
- Indice_Deb,
- Indice_Fin : Positive;
- begin
- -- Cas 1 : Chaine nulle
- Chercher_Mot("", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put ("T1: Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T1:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 2: Chaine de longueur > 0 qu'avec des espaces
- Chercher_Mot(" ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T2: Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T2:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 3: Chaine contenant un mot, sans espaces
- Chercher_Mot("Bonjour!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T3:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T3:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 4: Chaine comportant un mot precede par des espaces
- Chercher_Mot(" Bonjour!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T4:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T4:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 5: Chaine comportant un mot suivi d'espaces
- Chercher_Mot("Bonjour! ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T5:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T5:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 6: Chaine comportant deux mots separes par des espaces
- Chercher_Mot("Bonjour! Bye!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T6:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T6:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 7: Chaine comportant deux mots separes par des espaces et un espace à la fin
- Chercher_Mot("Bonjour! Bye! ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T7:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T7:Mot non trouve!" );
- New_Line;
- end if;
- end Tester_Chercher_Mot;
- begin
- Tester_Chercher_Mot;
- end programme;
|
Solution 3: Code :
- with Ada.Text_IO, Ada.Integer_Text_IO;
- use Ada.Text_IO, Ada.Integer_Text_IO;
- procedure programme is
- procedure Chercher_Mot (Dans: in String; Trouve: out Boolean; Deb, Fin: out Positive) is
- Fin_Trouvee : Boolean := False;
- begin
- Trouve := False;
- for Indice in Dans'First..Dans'Last loop
- if Dans(Indice) /= ' ' and not Trouve then
- Deb := Indice;
- Fin := Indice;
- Trouve := True;
- end if;
- if Trouve and not Fin_Trouvee then
- if Dans(Dans'Last) /= ' ' then
- Fin := Dans'Last;
- Fin_Trouvee := True;
- else
- for Indice2 in reverse Indice..Dans'Last loop
- if not Fin_Trouvee and Dans(Indice2) /= ' ' then
- Fin := Indice2;
- Fin_Trouvee := True;
- end if;
- end loop;
- end if;
- end if;
- end loop;
- end Chercher_Mot;
- -- Test unitaire
- procedure Tester_Chercher_Mot is
- Mot_Trouve : Boolean;
- Indice_Deb,
- Indice_Fin : Positive;
- begin
- -- Cas 1 : Chaine nulle
- Chercher_Mot("", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put ("T1: Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T1:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 2: Chaine de longueur > 0 qu'avec des espaces
- Chercher_Mot(" ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T2: Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T2:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 3: Chaine contenant un mot, sans espaces
- Chercher_Mot("Bonjour!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T3:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T3:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 4: Chaine comportant un mot precede par des espaces
- Chercher_Mot(" Bonjour!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T4:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T4:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 5: Chaine comportant un mot suivi d'espaces
- Chercher_Mot("Bonjour! ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T5:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T5:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 6: Chaine comportant deux mots separes par des espaces
- Chercher_Mot("Bonjour! Bye!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T6:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T6:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 7: Chaine comportant deux mots separes par des espaces et un espace à la fin
- Chercher_Mot("Bonjour! Bye! ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T7:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T7:Mot non trouve!" );
- New_Line;
- end if;
- end Tester_Chercher_Mot;
- begin
- Tester_Chercher_Mot;
- end programme;
|
Solution 4: Code :
- with Ada.Text_IO, Ada.Integer_Text_IO;
- use Ada.Text_IO, Ada.Integer_Text_IO;
- with Ada.Characters.Handling; use Ada.Characters.Handling; -- Is_Alphanumeric
- procedure programme is
- procedure Chercher_Mot (Dans: in String; Trouve: out Boolean; Deb, Fin: out Positive) is
- Indice : Positive := Dans'First;
- begin
- Trouve := False;
- while Indice <= Dans'Last and then not Is_Alphanumeric(Dans(Indice)) loop
- Indice := Positive'Succ(Indice);
- end loop;
- if Indice <= Dans'Last then
- Trouve := True;
- Deb := Indice;
- while Indice <= Dans'Last and then Is_Alphanumeric(Dans(Indice)) loop
- Indice := Positive'Succ(Indice);
- end loop;
- Fin := Positive'Min(Indice, Dans'Last);
- end if;
- end Chercher_Mot;
- -- Test unitaire
- procedure Tester_Chercher_Mot is
- Mot_Trouve : Boolean;
- Indice_Deb,
- Indice_Fin : Positive;
- begin
- -- Cas 1 : Chaine nulle
- Chercher_Mot("", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put ("T1: Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T1:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 2: Chaine de longueur > 0 qu'avec des espaces
- Chercher_Mot(" ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T2: Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T2:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 3: Chaine contenant un mot, sans espaces
- Chercher_Mot("Bonjour!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T3:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T3:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 4: Chaine comportant un mot precede par des espaces
- Chercher_Mot(" Bonjour!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T4:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T4:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 5: Chaine comportant un mot suivi d'espaces
- Chercher_Mot("Bonjour! ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T5:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T5:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 6: Chaine comportant deux mots separes par des espaces
- Chercher_Mot("Bonjour! Bye!", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T6:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T6:Mot non trouve!" );
- New_Line;
- end if;
- -- Cas 7: Chaine comportant deux mots separes par des espaces et un espace à la fin
- Chercher_Mot("Bonjour! Bye! ", Mot_Trouve, Indice_Deb, Indice_Fin);
- if Mot_Trouve then
- Put("T7:Mot trouve!" );
- Put(Indice_Deb);
- Put(Indice_Fin);
- New_Line;
- else
- Put("T7:Mot non trouve!" );
- New_Line;
- end if;
- end Tester_Chercher_Mot;
- begin
- Tester_Chercher_Mot;
- end programme;
|
Message édité par Corebreaker le 14-06-2009 à 05:43:04
|