[Pascal] limité le type de la variable

limité le type de la variable [Pascal] - Delphi/Pascal - Programmation

Marsh Posté le 28-09-2005 à 20:50:53    

Bonjour,
 
J'ai écrit un programme ( inintéressant au possible mais faut bien s'entrainer :x )
dans lequel je déclare la variable "an" du type "integer"
 
le problème c'est quand je met un "read(an)" et que l'utilisateur tape un caractère qui n'est pas un entier cela fait planter mon programme.
 
J'aurais voulu savoir comment je pouvais faire pour interdir un certain type de réponse.
 
Merci d'avance,
Philippe  :hello:

Reply

Marsh Posté le 28-09-2005 à 20:50:53   

Reply

Marsh Posté le 28-09-2005 à 22:20:43    

Technique pas super clean mais qui marche : Dire à ton compilateur d'arrêter de se faire suer avec les vérifications de types le temps de la lecture, puis après, récupérer une éventuelle erreur.

Code :
  1. {$i-}
  2. ReadLn(an);
  3. {$i+}
  4. if (IOResult <> 0) then
  5.   WriteLn('Je t''ai demandé un entier, boulet.');


 
Tu mets ça dans une boucle repeat pour que ça redemande autant de fois que nécessaire.
 
Je ne suis plus sûre du "i", s'il est en minuscule ou majuscule ou si on s'en fiche. Tu dois pouvoir trouver de la doc sur la directive de compilation (ça s'appelle comme ça) $i ainsi que sur IOResult.
 
 
 
Technique plus jolie : reprogrammer toi-même ton propre ReadLn d'entiers en regardant ce que l'utilisateur appuie comme touches, avec KeyPressed() et ReadKey(), en ignorant toutes les touches non numériques. C'est le genre de fonctions qui sert tout le temps et sur lesquelles il vaut le coup de passer un peu de temps au début.
 
 
 
(Le côté clean ou pas, joli ou pas, c'est principalement une affaire de goûts perso. Certains trouveront peut-être le coup du $i- propre.)

Reply

Marsh Posté le 29-09-2005 à 00:24:35    

Merci beaucoup pour la réponse :)
 
Je ne sais pas comment reprogrammer soi même les Read et Readln alors je vais essayé la 1ere solution.
 
Merci encore !

Message cité 1 fois
Message édité par HolySpirit le 29-09-2005 à 00:25:54
Reply

Marsh Posté le 29-09-2005 à 10:26:52    

HolySpirit a écrit :


Je ne sais pas comment reprogrammer soi même les Read et Readln alors je vais essayé la 1ere solution.


Pas bien compliqué. Tu commence par un "readln(chaine)" ou chaine est de type String, puis tu test la chaine.
 
En delphi, et probablement dans les version avancé du turbo pascal, il y a la fonction "TryStrToInt".
En Pascal pur, les chaine sont en fait des tableau de caractere. Donc "Chaine[10]" te donera le 10ième caractère de la chaine (et chaine[0], convertit en Byte, donne la longueur). Il te reste donc à analyser la chaine avec un programme ininteressant au possible, mais faut bien...

Reply

Marsh Posté le 29-09-2005 à 11:21:48    

Cate Winigan a écrit :

Technique pas super clean mais qui marche : Dire à ton compilateur d'arrêter de se faire suer avec les vérifications de types le temps de la lecture, puis après, récupérer une éventuelle erreur.

Code :
  1. {$i-}
  2. ReadLn(an);
  3. {$i+}
  4. if (IOResult <> 0) then
  5.   WriteLn('Je t''ai demandé un entier, boulet.');


 
Tu mets ça dans une boucle repeat pour que ça redemande autant de fois que nécessaire.
 
Je ne suis plus sûre du "i", s'il est en minuscule ou majuscule ou si on s'en fiche. Tu dois pouvoir trouver de la doc sur la directive de compilation (ça s'appelle comme ça) $i ainsi que sur IOResult.


 
C'est plus simple de recupérer l'exception avec try/except que de passer par IOResult...  (enfin, pour autant que le programme qui "plante" ce soit juste une exception, mais si c'est du Pascal et non Delphi je ne sais pas si tout ça s'applique...)


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 29-09-2005 à 14:19:17    

Merci pour toute vos réponses,
 
j'ai essayé la méthode de Cate Winigan ( qui marche parfaitement )
 
Les autres je n'ai pas encore le niveau ^^
 
Par contre, j'ai une question :
 
Je croyais que en pascal le contenu des balises (* *) et { } étaient des commentaires ?
Alors quel est le rôle de la ligne :  {$i-}  ?
 
est-ce vraiment un commentaire ou ai-je loupé un chapitre dans mon tutorial ? ^^

Reply

Marsh Posté le 29-09-2005 à 14:27:38    

Et sinon ( désolé pour le double post ) pour ma boucle,
je dois mettre UNTIL (IOResult = 0); ?
 
<> signifiant bien "différent" ? donc je présume que <> 0 veut dire différent d'un entier ?

Reply

Marsh Posté le 29-09-2005 à 16:28:32    

{$...} c'est pour les instructions aux compilateur, donc ce ne sont pas vraiment des commentaires même si ça utilise la même syntaxe
 
Tu peux montrer ton code ? Que je donne un exemple avec try/except pour que tu testes (si tu utilises Delphi et non un simple compilateur Pascal...)


Message édité par antp le 29-09-2005 à 16:28:45

---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 30-09-2005 à 09:48:10    

program Age;
 
var
 
  an_n,
  mois_n,
  jour_n,
  an,
  mois,
  jour,
  an_f,
  mois_f,
  jour_f:integer;
 
begin
   
   writeln(' ---------------------------------------------------------------------------------------');
   writeln('| Programme de Calcul d''âge : ');
   writeln('|');
   write('| Veuillez indiquer votre année de naissance : '); read(an_n);
   write('| Veuillez indiquer votre mois de naissance : '); read(mois_n);
   if (mois_n<1) or (mois_n>12)
      then REPEAT
    write ('| Veuillez écrire le mois correct : '); read(mois_n);
           UNTIL (mois_n>0) and (mois_n<13);
   write('| Veuillez indiquer votre jour de naissance : '); read(jour_n);
   if (jour_n<1) or (jour_n>31)
      then REPEAT
           write ('| Veuillez écrire le jour correct : '); read(jour_n);
           UNTIL (jour_n>0) and (jour_n<32);
 
   write('| Veuillez indiquer l''année à partir de laquelle vous voulez calculer votre âge : '); read(an);
   if (an<an_n)
      then REPEAT
  write ('| Veuillez écrire une année postérieur à celle de votre naissance : '); read(an);
           UNTIL (an>=an_n);
   an_f:=an;
         write('| Veuillez indiquer le mois à partir duquel vous voulez calculer votre âge : '); read(mois);
   if (mois<1) or (mois>12)
      then REPEAT
    write ('| Veuillez écrire le mois correct en : '); read(mois);
           UNTIL (mois>0) and (mois<13);
   if (an=an_n) and (mois<mois_n)
      then REPEAT
  write('| Veuillez indiquer une date postérieur à celle de votre naissance : '); read(mois);
           UNTIL mois>=mois_n;
   mois_f:=mois;
   write('| Veuillez indiquer le jour à partir duquel vous voulez calculer votre âge : '); read(jour);
   if (jour<1) or (jour>31)
      then REPEAT
           write ('| Veuillez écrire le jour correct en chiffre : '); read(jour);
           UNTIL (jour>0) and (jour<32);
   if (an=an_n) and (mois=mois_n) and (jour<jour_n)
      then REPEAT
             write('| Veuillez indiquer une date postérieur à celle de votre naissance : '); read(jour);
           UNTIL jour>=jour_n;
   jour_f:=jour;
   if jour<jour_n
      then
       begin
  (mois):=(mois-1);
  (jour):=(jour+30);
       end;
   if mois<mois_n
      then
        begin
  (an):=(an-1);
  (mois):=(mois+12);
 end;
 
      writeln('|-> Le ',(jour_f),'/',(mois_f),'/',(an_f),', vous aviez ',(an-an_n),' an(s), ',(mois-mois_n),' mois et ',(jour-jour_n),' jours.');  
   writeln('| Fin de l''execution du programme.');
   write(' ---------------------------------------------------------------------------------------               ')
   
   
end.


Message édité par antp le 30-09-2005 à 12:10:42
Reply

Marsh Posté le 30-09-2005 à 12:14:47    

j'ai replacé les tags "quote" par "fixed", c'était illisible là
 
La gestion par try/except ça ne s'applique pas vraiment à ce genre de code procédural en fait, du coup il faudrait bricoler un truc comme ça :
 


  Write('| Veuillez indiquer votre année de naissance : ');
  while True do
    try
      Read(an_n);
      Break;
    except
      Write('| Veuillez entrer une année correcte : ');
    end;


Il ne sort de la boucle que quand la lecture de l'année n'a pas provoqué d'erreur.
C'est peut-être pas ce qu'il y a de plus pratique dans ce cas-ci. Un repeat/until sur IOResult sera plus simple.
Pour ne pas avoir à entrer les $i à chaque lecture on peut configurer ça au niveau du projet.


Message édité par antp le 30-09-2005 à 12:15:50

---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 30-09-2005 à 12:14:47   

Reply

Marsh Posté le 03-10-2005 à 17:19:31    

HolySpirit a écrit :

<> signifiant bien "différent" ? donc je présume que <> 0 veut dire différent d'un entier ?

Oui, "<>" signifie bien "différent". Cela dit, "<> 0" ne signifie pas "différent d'un entier" mais "différent de 0". IOResult prend differentes valeurs selon l'erreur d'entrée/sortie (Input/Output, I/O, IO). En cas de fichier non trouvé dans un répertoire, IOResult prend la valeur 18 je crois, d'après ma mémoire. Pour une erreur de type dans Read, je sais pas. En absence d'erreur, IOResult vaut 0. Donc si IOResult <> 0 c'est qu'il y a eu une erreur. Pour savoir précisément quelle erreur, faudra regarder la valeur de IOResult, et pas se contenter de savoir qu'elle est non nulle. Dans ton cas, on se fiche un peu de savoir quelle erreur est survenue, tout ce qu'on souhaite c'est que l'utilisateur recommence une saisie, donc pas besoin de fignoler.
 
{i-/} et IOResult ne capturent pas toutes les erreurs possibles de Pascal ou Delphi, mais juste un certain nombres d'erreurs d'entrées sorties qu'on peut rencontrer avec Read, BlockWrite, FindFirst ou des procedures du genre.

Reply

Marsh Posté le 03-10-2005 à 17:44:51    

Merci pour toute vos réponses ! je vais mettre tout ca en application :)  
 
MERCI !

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed