Problème de "taille" - Ada - Programmation
Marsh Posté le 15-03-2009 à 14:37:37
Je ne fait plus trop d'ADA, mais pourquoi ne pas simplement transformer Saisir en une procédure avec comme paramètre T en "in out" ?
Par contre ton Get(T(I).nom); n'est pas idéal car il va attendre que l'utilisateur tape 20 caractères avant de passer à l'instruction suivante.
Marsh Posté le 15-03-2009 à 14:44:44
Pour ce qui est de la fonction en procédure, c'est une consigne que je dois respecter: on veut une fonction pour la saisie et non une procédure. Du coup, le problème reste entier...
Concernant le Get(T(I).nom), j'ignorais qu'il fallait entrer les 20 caractères pour pouvoir passer à l'instruction suivante: comment remédier au problème?
Marsh Posté le 15-03-2009 à 15:58:53
Comment veux-tu que la contrainte de la ligne 70 influence la ligne 23?
Marsh Posté le 15-03-2009 à 16:07:57
Je pensais que la structure "générale" du programme commence au begin de la ligne 61; ce qui se situe avant ne sont que les définitions des différents sous-programmes exécutés dans la structure principale du programme. En effet, ça n'est qu'à la ligne 74 que j'appelle ma fonction pour la première fois! Mon raisonnement n'est pas correct? Si tel n'est pas le cas, pouvez-vous m'expliquer pourquoi, et comment y remédier svp?
Merci d'avance.
Marsh Posté le 15-03-2009 à 16:48:48
Je donnerais un paramètre N à Saisir, rendrais le tableau de la ligne 70 non contraint et assignerais directement Saisir(N) à ce tableau. Mais ça doit faire 10 ans que j'ai plus fait d'Ada.
Marsh Posté le 15-03-2009 à 16:59:02
...sauf que Saisir ne prend pas de paramètre dans mon cas! Peux-tu préciser un peu stp?
En fait, je ne saisis pas pourquoi ce que j'ai fait ne fonctionne pas.
Marsh Posté le 15-03-2009 à 17:11:54
Qu'est-ce qui t'empèche de lui en donner un?
Tu essaies de déclarer une variable d'un type non contraint. Le fait que dans ton programme tu vas l'assigner (au travers d'un retour de fonction non contraint) à une variable d'un type contraint ne propage pas la contrainte.
Marsh Posté le 15-03-2009 à 17:21:00
Ok, je vais essayer. Mais j'en reviens à ma première question: pourquoi ce que j'ai fait ne fonctionne pas?
Marsh Posté le 15-03-2009 à 17:27:11
dj_titeuf a écrit : Ok, je vais essayer. Mais j'en reviens à ma première question: pourquoi ce que j'ai fait ne fonctionne pas? |
Qu'est-ce que tu ne comprends pas dans:
Un Programmeur a écrit : Tu essaies de déclarer une variable d'un type non contraint. Le fait que dans ton programme tu vas l'assigner (au travers d'un retour de fonction non contraint) à une variable d'un type contraint ne propage pas la contrainte. |
Marsh Posté le 15-03-2009 à 17:45:54
Qu'entends-tu exactement par "assigner"?
Et au passage, qu'est-ce qu'il faut modifier pour éviter de devoir rentrer 20 caractères lors de la saisie avant de passer à l'instruction suivante?
Et une dernière chose au passage: j'ai réussi à faire les modifs que tu m'as conseillées, et ça compile! Par contre, en faisant un test (j'ai modifié certains caractères comme sportif en élève, etc.. mais rien d'important), l'affichage du tableau est quelque peu... étrange!
D'où cela vient-il?
Marsh Posté le 15-03-2009 à 20:49:24
Le declare forme un bloc,
donc ton T : Un_Tableau_Releve(1..N) est une variable locale de ce bloc ! Elle est donc inaccessible dans ta fonction déclarée plus haut et par la même occasion supprimé a la sortie du bloc : si tu fait un Afficher(T) après le end de ton déclare, T ne sera pas reconnu non plus !
Pour y remédier tu peut mettre ta fonction Saisir a l'intérieur du declare, après la déclaration de ton T.
Code :
|
dsl pour l'indentation, histoire de tab/espace
Pour ne pas saisir les 20 char de ton Get, regarde du coté de Get_Line :
Code :
|
nb contient le nombre de caractères sauvegardées.
Par contre pense à bien initialiser et/ou remplir la fin de la chaine sous peine d'avoir des valeurs indéfinies.
Edit : Cela règlera par la même occasion ton problème de caractères "étrange"
Marsh Posté le 16-03-2009 à 01:15:21
Merci pour ta réponse wyruz, mais je souhaiterais revenir sur certains points (tous en fait!).
Tout d'abord, j'ai peur de ne pas bien saisir quand tu me dis que ma variable T est inaccessible dans ma fonction Saisir déclarée plus haut. Voici comment je vois les choses: dans le bloc declare, je définie ma variable T, ie je la contrains. Le programme déroule, et là, il arrive à T:= Saisir, ce qui signifie qu'on appelle la fonction Saisir, en prenant la variable T contrainte juste avant! C'est là que je comprends pas! Pourquoi cela ne se passe pas comme ça? Ce n'est pas logique?
Ensuite, concernant le get_line: l'ennui c'est que je ne peux connaître à l'avance le nb. Cela dépendra de la chaîne de caractères que va rentrer l'utilisateur. Dans l'idéal, je souhaiterais pouvoir passer à l'instruction suivante dès que l'utilisateur tape entrée après avoir terminée sa saisie, et ce quelque soit le nombre de caractères (<21 tout de même) rentré. Comment faire?
Enfin, pour ce qui est des problèmes d'affichage, je ne vois pas bien le rapport avec tout ça...
En espérant que tu pourras m'éclairer, merci d'avance!
Marsh Posté le 16-03-2009 à 10:21:07
Pour la variable T, si elle est passé en paramètre d'une fonction comme tu le dit c'est bon tu n'a pas besoin de la déclarer.
Or dans le cas présent elle prend simplement la valeur de retour de la fonction mais elle n'est pas passé en paramètre !
Le return n'est pas considérer comme un paramètre (d'ailleurs en C par exemple tu n'est pas obliger d'utiliser cette valeur même si elle est retournée)
La ligne T:= Saisir se déroule comme suit :
La fonction Saisir est appelée sans paramètre (donc le T n'est pas un paramètre connu a l'intérieur de la fonction) puis effectuée. A la fin de cette fonction elle renvoi un "Un_Tableau_Releve".
La valeur retournée est alors affecté a la variable T se trouvant dans ton bloc declare.
A aucun moment la fonction Saisir n'a travaillé sur ce T contraint se trouvant dans le declare, elle essaye de travailler avec la variable T que tu déclare au début de la fonction, celui ci qui est non contraint d'ou l'erreur de compilation
Pour la saisin de caractère (pour le traitement des chaines, ADA c'est vraiment pas terrible ... quoi qu'avec le paquetage stringfixed c'est deja mieux), la fonction Get_Line fait exactement ce que tu veut
le prototype :
Code :
|
Les 2 paramètres sont en out, Elle va donc enregistrer dans Item tous les caractère jusqu'au "enter", et dans Last tu aura le nombre de caractère enregistrés.
si tu tape : "qwerty""ENTER", tu aura "querty" dans Item et 6 dans Last puis l'instruction suivant sera effectuée. Par contre si tu dépasse 20 tu va te retrouver avec une DATA_ERROR (je ne suis pas sur de l'exception mais tu en aura une c'est sur )
Tu n'est pas obliger de te servir de ce Last par la suite mais tu doit obligatoirement le mettre en paramètre. Sinon tu peut t'en servir pour "effacer" les caractères de la chaines qui n'ont pas reçu de valeur, cf la suite
Pour l'affichage, si tu déclare ton string sans l'initialiser comme suit :
Code :
|
la fonction Get_Line va remplir le début avec les caractères saisies, mais les derniers peuvent être tout et n'importe quoi (ce qu'il y avais a ces emplacement mémoire en fait car les 20 cases ne sont jamais initialisés) et l'affichage produit des caractères étrange comme tu a (contrairement au C, il n'y a pas d'arrêt lors du "\0" ) !
Solution : soit initialiser toute ta chaine dès la déclaration (le plus simple), soit remplir la chaine de Last(celui retourne par get_Line) jusqu'à Item'Last avec des espaces.
Je pense que ça sera plus clair maintenant
Marsh Posté le 16-03-2009 à 17:20:01
Merci beaucoup pour tes explications, ça commence à s'éclairer doucement!
Encore deux trois précisions cependant stp:
* Quand utiliser get_line plutôt que get et inversement? (même remarque avec put et put_line au passage)
* Pour ce qui est des problèmes d'affichage, je crois avoir trouvé une solution (en tout cas ça marche), mais je ne suis pas certain de comprendre réellement comment ça fonctionne. En effet, j'ai rajouté dans la fonction Saisir, la ligne T(I).nom := (others => ' '); ainsi que T(I).age := (others => ' '); et T(I).resultat := (others => ' ');.
Premier constat: ça marche très bien... à condition que j'enlève T(I).resultat := (others => ' ');, et uniquement celle-ci. Pourquoi?
A partir de là, je me suis demandé ce que ces lignes de code faisaient réellement: je suppose qu'avant de rentrer les caractères, on initialise la case correspondante (nom, age.. et pourquoi pas note du coup??) avec des blancs, ce qui règle le problème d'affichage dont tu parles dans ton dernier message. Par contre, que signifie le "others"? C'est ça que je ne saisie pas. Il m'aurait semblé plus naturel de mettre, par exemple, T(I).nom := ' '; et T(I).age := ' ';. Non?
En espérant que tu pourras de nouveau m'aider sur ces trois autres incompréhensions (l'histoire des get et put, la raison de la nécessité de l'absence d'initialisation pour la case resultat, et la signification de others), merci d'avance!
Marsh Posté le 15-03-2009 à 12:15:15
Bonjour,
En vue de faire un petit programme de gestion de résultats de sportifs, j'ai commencé par tester le début de ce que j'ai fait, sans succès. J'ai une erreur à la compilation: unconstrained subtype not allowed (need initialization) au niveau de la ligne 23. Pourtant, il me semble bien avoir déclaré une contrainte sur la taille de mon tableau (ligne en rouge)... non?
En espérant que vous pourrez m'aider, merci d'avance!