Как использовать Ада двусвязные списки - PullRequest
2 голосов
/ 11 апреля 2020

Я работаю над школьным проектом на языке программирования Ada. Профессор хочет, чтобы мы использовали язык, на котором мы не знакомы, чтобы писать. Мне нужно использовать Ада двусвязный список, чтобы написать программу текстового редактора. Программа при вызове примет единственный необязательный аргумент командной строки, который задает имя файла по умолчанию. Если этот файл уже существует, его содержимое должно быть загружено в текстовый буфер. После сохранения файла содержимое буфера будет выгружено в файл с указанным именем, перезаписывая любой существующий файл. Например,

, если я введу команду

a - для добавления

привет

мир

.

файл будет иметь

привет

мир

добавляется в конец документа

если я наберу

3 a

привет

world

.

затем к строке 3 документа добавляется та же строка.

Вот код, который я написал до сих пор, но я не могу понять, как использовать строку в качестве условия моего оператора case.

Может кто-нибудь помочь мне с этим проектом?

with Ada.Containers.Doubly_Linked_Lists;
with Ada.Text_Io; use Ada.Text_Io;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;


procedure main is
   package String_List is new Ada.Containers.Doubly_Linked_Lists(Unbounded_String);
   use String_List;
   --Userinput : String(1 .. 10) := (others => ' '); --This string length is 10
   Last: Integer; --This is use to count input string length
   currentAddress: Integer := 0;
   text : List; -- List is from Doubly_Linked_Lists
   type Userinput is (a, c, p, e);
   --size: Integer; --This is use to count input string length


   procedure Print(Position : Cursor) is -- this subprogram print all string from list
   begin
      Put_Line(To_String(Element(Position)));
      --Put_Line("K");
   end Print;



begin
   loop

      Put( Integer'Image (currentAddress) & " >> " );

      Get_Line(Userinput);

      case Userinput is

         when a =>
            Put( Integer'Image (currentAddress) & " >> " );
            Get_Line(Userinput);  
            text.Append(To_Unbounded_String(Userinput)); -- if letter is a add it to the doubly link list        

         when c =>      
            --text.Insert(Before => text.Find(To_Unbounded_String(Userinput)), New_Item => To_Unbounded_String( ? ));

         when p =>      
            text.Iterate(Print'access);
         when e =>      
            Put_Line("Program Exit");                     
            exit;
         when others =>
            Put_Line ("No command found ");   

      end case;

   end loop;

end main;

Ответы [ 2 ]

3 голосов
/ 11 апреля 2020

Вы не можете использовать String в качестве «выражения выбора» оператора case ( ARM 5.4 (4) ), потому что это не дискретный тип (больше, чем действительное число, или запись есть.)

Вы можете попробовать использовать перечисление, как в примере ниже (что оставляет открытым вопрос о том, как поступать с вводом, как в вашем примере 3 a):

with Ada.Text_IO;
with Ada.IO_Exceptions;
procedure Alan is
   type Command is (A, C, P, E);
   package Command_IO is new Ada.Text_IO.Enumeration_IO (Command);
begin
   loop
      declare
         Cmd : Command;
      begin
         Command_IO.Get (Cmd);
         Ada.Text_IO.Skip_Line;
         Ada.Text_IO.Put_Line ("read " & Cmd'Image);                -- ' to sort out the not-fully-Ada-aware syntax highlighting
         case Cmd is
            when A => ...
            ...
            when E => exit;
         end case;
      exception
         when Ada.IO_Exceptions.Data_Error =>
            Ada.Text_IO.Put_Line ("unrecognised command");
      end;
   end loop;
end Alan;

Обычно я бы use Ada.Text_IO;; не здесь, для ясности.

2 голосов
/ 11 апреля 2020

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

  • Разбить синтаксический анализ команды, из которой она действует в текстовом буфере. Определите и внедрите (в качестве примера) пакет со следующей спецификацией:

parser.ads

package Parser is

   Parse_Error : exception;   

   type Command_Kind is (Insert, Delete, Clear);

   subtype Line_Number is Natural;   
   No_Line_Number : constant Line_Number := 0;

   type Command is record
      Kind : Command_Kind;
      Line : Line_Number;
   end record;      

   function Parse (Str : String) return Command;
   --  Parses the given string and returns a command data object on success.

end Parser;
  • Реализация абстрактного текстового буфера , Возможно, вы захотите использовать Indefinite_Vectors вместо Doubly_Linked_List в качестве контейнера по вашему выбору, так как вы будете интенсивно работать с номерами строк (векторы могут быть проиндексированы легче по сравнению с двусвязными списками). Определите и внедрите (в качестве примера) пакет со следующей спецификацией:

text_buffers.ads

with Ada.Containers.Indefinite_Vectors;

package Text_Buffers is

   type Text_Buffer is private;

   subtype Line_Number is Positive;   --  Different from Parsers.Line_Number!

   procedure Load 
     (Buffer   : in out Text_Buffer; 
      Filename : String);
   --  Loads a text file into the text buffer.

   procedure Save 
     (Buffer   : in out Text_Buffer;
      Filename : String);
   --  Saves a text buffer into a text file.

   function Line_Count 
     (Buffer : Text_Buffer) return Natural;
   --  Gets the number of lines in the buffer.

   function Get_Line
     (Buffer : Text_Buffer;
      Line   : Line_Number) return String;
   --  Gets the text of the given line.

   procedure Clear 
     (Buffer : in out Text_Buffer);
   --  Clears the text buffer.

   procedure Insert
     (Buffer : in out Text_Buffer; 
      Text   : String; 
      After  : Line_Number);
   --  Inserts line of text to the text buffer.

   procedure Delete
     (Buffer : in out Text_Buffer; 
      Line   : Line_Number);
   --  Deletes a line of text from the text buffer.

   --  ... other actions.   

private

   package Vector_String is 
     new Ada.Containers.Indefinite_Vectors (Line_Number, String);  
   use Vector_String;

   type Text_Buffer is new Vector with null record;

end Text_Buffers;
  • Использование пакетов Parser и Text_Buffers для создания вашего окончательного текстового редактора. Я бы посоветовал поместить логи приложения c (инициализация и основной l oop) также в отдельный пакет и вызвать Run из Main (см. Ниже):

editor.ads

package Editor is

   procedure Run (Filename : String);
   --  Runs the editor application.

end Editor;

editor.adb

with Parser;
with Text_Buffers;

package body Editor is

   ---------
   -- Run --
   ---------

   procedure Run (Filename : String) is
   begin      
      -- Initialization & Program loop.
      null;
   end Run;      

end Editor;

main.adb

with Ada.Command_Line;
with Editor;

procedure Main is
  Filename : String;
begin
   --  Process command line options, set Filename.
   Editor.Run (Filename);
end Main;
...