2015-04-08 4 views
1

Я пытаюсь использовать строку в выражении case, но она дает мне expected a discrete type. Found type Standard.String Я понимаю, что строки не являются дискретными. Мне интересно, есть ли работа или нет. Вот мой код:Оператор case Ada со строками

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; 

Прокомментированный раздел выполняет именно то, что я хочу, но с операторами if. Я просто пытаюсь понять, возможно ли это с помощью case case.

+0

No. Ada is not Java. – ajb

+0

Это может помочь подумать о вещах «по-другому» - начать с внутренних дел, а затем перейти к пользовательскому интерфейсу - точнее, подумать о проблеме с точки зрения типов. http://blog.kickin-the-darkness.com/2007/08/fundamental-theory-of-ada.html – Shark8

ответ

5

Вы можете сопоставить свои строки с дискретным типом. Проще быть перечислимый тип:

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

Я часто использую фактические map сделать этот вид отображения, так как это дает вам больше гибкости, чем перечисления. Ваши «имена» не должны соответствовать синтаксису перечисления, и вы можете легко предоставить варианты, которые все сопоставляются с одним значением.

Для нужного определения функции, как это предусмотрено в пакете:

package Case_Map is 

    function Is_Valid_Direction(Direction_To_Go : in String) return Integer; 

end Case_Map; 

Это (не-компиляции из-за отсутствия игры конкретных заявлений) реализации использует отображение строк на перечисление, который в свою очередь дело выражение:

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

комара компилятор сам использует хэш-таблицу, которая отображает строки (идентификаторы, ключевые слова, ...) в целое. Это пакет namet.ads, а GNATCOLL.Symbolic предоставляет аналогичный API. Это упрощает ряд вещей (сравнение строк, например, намного быстрее), и позволяет использовать аргументы case, как в вашем примере. Поэтому, если вы используете ограниченный (или, по крайней мере, медленно растущий) список строк, GNATCOLL.Symbolic может быть подходящим подходом

Смежные вопросы