2015-04-08 2 views
1

J'essaie d'utiliser une chaîne dans une déclaration de cas, mais il me donne expected a discrete type. Found type Standard.String Je comprends que les chaînes ne sont pas discrètes. Je me demande s'il y a un travail ou non. Voici mon code:Déclaration de cas Ada avec des chaînes

function Is_Valid_Direction(Direction_To_Go : in String) return Integer is 
    Room : Integer := 0; 
    begin 
     --if (Direction_To_Go = "NORTH" or Direction_To_Go = "N") then 
     -- Room := Building(currentRoom).exits(NORTH); 
     --elsif (Direction_To_Go = "SOUTH" or Direction_To_Go = "S") then 
     -- Room := Building(currentRoom).exits(SOUTH); 
     --elsif (Direction_To_Go = "EAST" or Direction_To_Go = "E") then 
     -- Room := Building(currentRoom).exits(EAST); 
     --elsif (Direction_To_Go = "WEST" or Direction_To_Go = "W") then 
     -- Room := Building(currentRoom).exits(WEST); 
     --elsif (Direction_To_Go = "UP" or Direction_To_Go = "U") then 
     -- Room := Building(currentRoom).exits(UP); 
     --elsif (Direction_To_Go = "DOWN" or Direction_To_Go = "D") then 
     -- Room := Building(currentRoom).exits(DOWN); 
     --end if; 
     case Direction_To_Go is 
     when "NORTH" | "N" => Room := Building(currentRoom).exits(NORTH); 
     when "SOUTH" | "S" => Room := Building(currentRoom).exits(SOUTH); 
     when "EAST" | "E" => Room := Building(currentRoom).exits(EAST); 
     when "WEST" | "W" => Room := Building(currentRoom).exits(WEST); 
     when "UP" | "U" => Room := Building(currentRoom).exits(UP); 
     when "DOWN" | "D" => Room := Building(currentRoom).exits(DOWN); 
     when others => Room := 0; 
     end case; 
     return Room; 
    end Is_Valid_Direction; 

La section commentée fait exactement ce que je veux, mais avec des instructions if. J'essaie juste de voir si c'est possible avec une déclaration de cas.

+0

Non. Ada n'est pas Java. – ajb

+0

Il peut être utile de réfléchir aux choses «à l'envers» - commencer par les internes, puis aller à l'interface utilisateur - plus précisément, réfléchir sur le problème en termes de types. http://blog.kickin-the-darkness.com/2007/08/fundamental-theory-of-ada.html – Shark8

Répondre

5

Vous pouvez mapper vos chaînes à un type discret. Le moyen le plus étant un type énuméré:

procedure Light (Colour : in  String) is 
    type Colours is (Red, Green, Blue); 
begin 
    case Colours'Value (Colour) is -- ' <- magic ;-) 
     when Red => 
     Switch_Red_LED; 
     when Green => 
     Switch_Green_LED; 
     when Blue => 
     Switch_Blue_LED; 
    end case; 
exception 
    when Constraint_Error => 
     raise Constraint_Error with "There is no " & Colour & " LED."; 
end Light; 
3

J'utilise souvent une map réelle pour faire ce genre de cartographie, car il vous donne plus de flexibilité que énumérations. Vos «noms» ne doivent pas nécessairement être conformes à la syntaxe d'énumération, et vous pouvez facilement fournir des variantes qui correspondent toutes à une seule valeur.

Pour la définition de la fonction souhaitée, tel que prévu dans un paquet:

package Case_Map is 

    function Is_Valid_Direction(Direction_To_Go : in String) return Integer; 

end Case_Map; 

Cette (non-compilation en raison du manque de déclarations spécifiques au jeu) la mise en œuvre utilise une cartographie de chaînes à un ENUM qui est à son tour la expression de cas:

with Ada.Characters.Handling; 
with Ada.Containers.Indefinite_Ordered_Maps; 

package body Case_Map is 

    use Ada.Characters.Handling; 

    type Directions is (Go_North, Go_South, Go_East, Go_West, Go_Up, Go_Down); 

    package Direction_Management is new Ada.Containers.Indefinite_Ordered_Maps 
    (String, Directions); 

    Direction_Map : Direction_Management.Map; 

    function Is_Valid_Direction(Direction_To_Go : in String) return Integer is 
     Room : Integer := 0; 
    begin 
     case Direction_Map(To_Upper(Direction_To_Go)) is 
     when Go_North => Room := Building(CurrentRoom).Exits(NORTH); 
     when Go_South => Room := Building(CurrentRoom).Exits(SOUTH); 
     when Go_East => Room := Building(CurrentRoom).Exits(EAST); 
     when Go_West => Room := Building(CurrentRoom).Exits(WEST); 
     when Go_Up => Room := Building(CurrentRoom).Exits(UP); 
     when Go_Down => Room := Building(CurrentRoom).Exits(DOWN); 
     end case; 
     return Room; 
    exception 
     when Constraint_Error => 
     return 0; 
    end Is_Valid_Direction; 

begin 
    Direction_Map.Insert("NORTH", Go_North); 
    Direction_Map.Insert("N", Go_North); 
    Direction_Map.Insert("SOUTH", Go_South); 
    Direction_Map.Insert("S", Go_South); 
    Direction_Map.Insert("EAST", Go_East); 
    Direction_Map.Insert("E", Go_East); 
    Direction_Map.Insert("WEST", Go_West); 
    Direction_Map.Insert("W", Go_West); 
    Direction_Map.Insert("UP", Go_Up); 
    Direction_Map.Insert("U", Go_Up); 
    Direction_Map.Insert("DOWN", Go_Down); 
    Direction_Map.Insert("D", Go_Down); 
end Case_Map; 
0

Le compilateur GNAT lui-même utilise une table de hachage que les chaînes cartes (identifiants, mots-clés, ...) en entier. Ceci est le paquet namet.ads, et GNATCOLL.Symbolic fournit une API similaire. Cela simplifie un certain nombre de choses (la comparaison de chaînes par exemple est beaucoup plus rapide), et permet l'utilisation des instructions de cas comme dans votre exemple. Donc, si vous utilisez une liste de chaînes limitée (ou au moins à croissance lente), GNATCOLL.Symbolic pourrait être une approche appropriée