Recherche de mot - Ada - Programmation
Marsh Posté le 14-06-2009 à 05:37:30
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 :
|
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 :
|
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 :
|
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 :
|
Solution 2:
Code :
|
Solution 3:
Code :
|
Solution 4:
Code :
|
Marsh Posté le 03-05-2009 à 00:43:51
Bonsoir,
J'essaie d'écrire un programme me permettant de déterminer si une chaîne de caractères présente un (ou des) mot(s) ou non, et de connaître également les indices correspondant à la première lettre et la dernière lettre. Afin de voir si ce que j'ai écrit fonctionne, j'ai procédé à 6 tests unitaires; seulement, l'un d'entre eux ne fonctionne pas, comme vous allez le voir... Voici mon code:
Il s'agit du Test 5 qui ne fonctionne pas, puisque le programme me revoit comme indice de fin, 11, au lieu de 8. Voyez-vous ce qui pose problème? Si des explications concernant mon code sont nécessaires, n'hésitez pas à me le faire savoir, je tenterai d'éclaircir ce que j'ai voulu faire!
Merci d'avance!