Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1367 connectés 

  FORUM HardWare.fr
  Programmation
  Ada

  Problème de "taille"

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Problème de "taille"

n°1861722
dj_titeuf
Posté le 15-03-2009 à 12:15:15  profilanswer
 

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! :bounce:  
 

Code :
  1. with Ada.Text_IO, Ada.Integer_Text_IO;
  2. use Ada.Text_IO, Ada.Integer_Text_IO;
  3. procedure Gestion is
  4.  
  5.    -- Définition des types et sous-types
  6.  
  7.    subtype Un_Resultat is Natural range 0..20;
  8.  
  9.    type Info_Sportif is record
  10.       Nom: String(1..20);
  11.       age: Positive;
  12.       resultat: Un_Resultat;
  13.    end record;
  14.  
  15.    type Un_Tableau_Releve is array(Natural range <> ) of Info_Sportif;
  16.  
  17.    -- Définition des sous-programmes
  18.  
  19. function Saisir return Un_Tableau_Releve is
  20.  
  21.    T: Un_Tableau_Releve;
  22.  
  23. begin
  24.  
  25.    for I in T'range loop
  26.       Put("Veuillez rentrer les noms, âges et résultats des sportifs: " );
  27.       New_Line(2);
  28.       Put("Nom: " );
  29.       Get(T(I).nom);
  30.       Put("Age: " );
  31.       Get(T(I).age);
  32.       Put("Resultat: " );
  33.       Get(T(I).resultat);
  34.       Skip_Line;
  35.    end loop;
  36.  
  37.    return T;
  38.  
  39. end Saisir;
  40. procedure Afficher(T: in Un_Tableau_Releve) is
  41.  
  42. begin
  43.    for I in T'range loop
  44.       Put("Nom: " );
  45.       Put(T(I).nom);
  46.       Put("Age: " );
  47.       Put(T(I).age);
  48.       Put("Resultat: " );
  49.       Put(T(I).resultat);
  50.    end loop;
  51. end Afficher;
  52. N: Positive;
  53. begin
  54.  
  55.    Put("Quel est le nombre de sportifs?" );
  56.    Get(N);
  57.    Skip_Line;
  58.  
  59.    declare
  60.      
  61.       T: Un_Tableau_Releve(1..N);
  62.      
  63.    begin
  64.      
  65.       T:= Saisir;
  66.       Afficher(T);
  67.    end;
  68.  
  69. end Gestion;

mood
Publicité
Posté le 15-03-2009 à 12:15:15  profilanswer
 

n°1861746
Wyruz
Posté le 15-03-2009 à 14:37:37  profilanswer
 

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.


Message édité par Wyruz le 15-03-2009 à 14:37:50
n°1861749
dj_titeuf
Posté le 15-03-2009 à 14:44:44  profilanswer
 

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?

n°1861762
Un Program​meur
Posté le 15-03-2009 à 15:58:53  profilanswer
 

Comment veux-tu que la contrainte de la ligne 70 influence la ligne 23?

n°1861765
dj_titeuf
Posté le 15-03-2009 à 16:07:57  profilanswer
 

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.

n°1861773
Un Program​meur
Posté le 15-03-2009 à 16:48:48  profilanswer
 

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.
 

n°1861774
dj_titeuf
Posté le 15-03-2009 à 16:59:02  profilanswer
 

...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.


Message édité par dj_titeuf le 15-03-2009 à 17:00:20
n°1861779
Un Program​meur
Posté le 15-03-2009 à 17:11:54  profilanswer
 

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.

n°1861785
dj_titeuf
Posté le 15-03-2009 à 17:21:00  profilanswer
 

Ok, je vais essayer. Mais j'en reviens à ma première question: pourquoi ce que j'ai fait ne fonctionne pas?

n°1861789
Un Program​meur
Posté le 15-03-2009 à 17:27:11  profilanswer
 

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.


mood
Publicité
Posté le 15-03-2009 à 17:27:11  profilanswer
 

n°1861797
dj_titeuf
Posté le 15-03-2009 à 17:45:54  profilanswer
 

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! :bounce: 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!  
 
http://pics.imagup.com/01/1237166276_screeshot.jpg
 
D'où cela vient-il?


Message édité par dj_titeuf le 15-03-2009 à 19:19:15
n°1861872
Wyruz
Posté le 15-03-2009 à 20:49:24  profilanswer
 

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 :
  1. ...
  2.    declare
  3.    
  4.       T: Un_Tableau_Releve(1..N);
  5.    
  6.  function Saisir return Un_Tableau_Releve is
  7.  begin
  8.      for I in T'range loop
  9.            Put("Veuillez rentrer les noms, âges et résultats des sportifs: " );
  10.            New_Line(2);
  11.            Put("Nom: " );
  12.            Get(T(I).nom);
  13.            Put("Age: " );
  14.            Get(T(I).age);
  15.            Put("Resultat: " );
  16.            Get(T(I).resultat);
  17.            Skip_Line;
  18.      end loop;
  19.     return T;
  20.    end Saisir;
  21.    begin
  22. ...


 
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 :
  1. Get_Line(S,nb);


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" ;)


Message édité par Wyruz le 15-03-2009 à 21:01:20
n°1861936
dj_titeuf
Posté le 16-03-2009 à 01:15:21  profilanswer
 

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!


Message édité par dj_titeuf le 16-03-2009 à 01:15:34
n°1862008
Wyruz
Posté le 16-03-2009 à 10:21:07  profilanswer
 

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  :jap:  
 
 
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 :
  1. procedure Get_Line
  2.   (Item : out String;
  3.    Last : out Natural);


 
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 :
  1. Nom: String(1..20);


 
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  :jap:

n°1862182
dj_titeuf
Posté le 16-03-2009 à 17:20:01  profilanswer
 

Merci beaucoup pour tes explications, ça commence à s'éclairer doucement! :)  
 
Encore deux trois précisions cependant stp: :D
 
* 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! ;)


Message édité par dj_titeuf le 16-03-2009 à 17:22:24

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Ada

  Problème de "taille"

 

Sujets relatifs
[réglé] Probleme taille fenetre popupProblème pour adapter la taille d'une image à la cellule d'un tableau
Javascript et IE7 : probleme de taille !Problème taille police IE
[résolu] Probleme pour connaitre la taille d'une chaine de caracteresProblème de copier coller sous vba:comment réduire la taille de la sél
Probleme taille blocproblème taille police IE Firefox
Probleme de taille de police avec Mozilla firefoxProblème taille pages sous dreanweaver (urgent !!)
Plus de sujets relatifs à : Problème de "taille"


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR