Comment vérifier l'entrée? Langue Ada
Je viens de commencer à apprendre Ada et je ne peux pas comprendre comment maintenir le programme en cours d'exécution lorsque l'entrée utilisateur est au-delà de la plage déclarée d'une variable. Je voudrais imprimer des informations sur une mauvaise plage d'entrée, puis demander à nouveau à l'utilisateur de le saisir.
Voici mon code simple:
with Ada.Text_IO;
use Ada.Text_IO;
procedure Main is
type Score is range 0..100;
a : Score;
begin
Put_Line ("Enter value range 0-100: ");
a := Score'Value(Get_Line);
if a'Valid then
Put_Line ("You entered" & Score'Image (a));
else
Put_Line ("Bad range of input");
end if;
end Main;
Ne devrais-je pas utiliser la "plage" pour vérifier l'entrée, mais plutôt certains si avec>, <restrictions?
Mon autre approche était d'essayer ceci avec des exceptions, mais cela ne fonctionne pas non plus comme je le souhaite:
with Ada.Text_IO;
with Ada.IO_Exceptions;
use Ada.Text_IO;
procedure Main is
type Score is range 0..100;
a : Score;
begin
loop
begin
Put_Line ("Enter value range 0-100: ");
a := Score'Value(Get_Line);
Put_Line ("You entered" & Score'Image (a));
exit;
exception
when Ada.IO_Exceptions.Data_Error =>
Put_Line("Bad range of input");
end;
end loop;
end Main;
Je crois que le problème est dans mon manque de compréhension de cette langue, mais j'espère qu'il y a une sorte de solution facile pour cela, merci pour toute aide.
Réponses
Vous connaissez maintenant une incantation magique qui fonctionne, mais je doute que vous compreniez pourquoi cela fonctionne, ou pourquoi vos autres incantations n'ont pas fonctionné. J'entrerai dans des détails pédagogiques douloureux à ce sujet, dans l'espoir que certains d'entre eux pourraient être utiles ou intéressants.
Dans Ada, lorsque vous déclarez un type, le type est anonyme et le nom ( Score) que vous donnez est le nom du sous-type nommé en premier . Le sous-type nommé en premier peut avoir des contraintes qui ne s'appliquent pas au type de base anonyme. Pour certains types, y compris les types entiers, il est possible de faire référence au type de base anonyme avec 'Base.
Puisque vous avez déclaré Scoreutiliser range, il s'agit d'un type entier signé et son type de base est (à peu près) symétrique autour de zéro. Donc, votre déclaration équivaut à quelque chose comme
type Score'Base is range -128 .. 127;
subtype Score is Score'Base range 0 .. 100;
(ce n'est pas Ada et ne compilera pas).
Score'Valuerenvoie une valeur de Score'Base( ARM 3.5 (53) ), donc si vous entrez "101"ou "-3", Score'Valueréussira et renverra la valeur appropriée. Lorsque vous affectez cette valeur à votre variable de sous Score- type , une vérification est effectuée que la valeur est dans la plage de Score; quand cela échoue, Constraint_Errorest soulevé. Si vous entrez une image non valide, telle que "200"ou "xyz", Score'Valueéchoue et se déclenche Constraint_Error. Vous avez donc deux types d'entrées incorrectes entraînant deux échecs différents, qui provoquent tous deux la même exception.
Votre première version a échoué car vous n'êtes jamais arrivé à la ifdéclaration. Votre deuxième version a échoué car Ada.Text_IO.Get_Linene relance jamais Data_Error.
En ce qui concerne l'entrée numérique, je vous conseille de lire une ligne complète dans une chaîne et d'analyser ensuite la ou les valeurs de cette chaîne, comme vous l'avez fait. Cependant, 'Valuerejettera certaines entrées que vous voudrez peut-être considérer comme valides. Par exemple, vous voudrez peut-être accepter "23 skidoo"et obtenir la valeur 23 de celui-ci. Pour cela, vous voudrez peut-être instancier Ada.Text_IO.Integer_IOpour votre (sous) type numérique et utiliser la Getfonction qui prend un Stringparamètre:
package Score_IO is new Ada.Text_IO.Integer_IO (Num => Score);
...
Score_IO.Get (From => "23 skidoo", Item => A, Last => Last);
sera mis Aà 23 et Lastà l'index de '3'in From(2).
HTH