如何使用 Ada 双向链表

How to use Ada doubly linked lists

我正在使用 Ada 编程语言进行学校项目。教授要我们用不熟悉的语言来写。我需要使用 Ada 双向链表来编写一个文本编辑器程序。该程序在调用时将采用一个可选的命令行参数,该参数将指定默认文件名。如果该文件已经存在,则应将其内容加载到文本缓冲区中。保存文件后,缓冲区的内容将转储到具有指定名称的文件中,覆盖任何现有文件。

例如,如果我输入

a -- 追加命令

你好

世界

.

文件将有

你好

世界

附加到文档末尾

如果我输入

3个

你好

世界

.

然后在文档的第 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;

您不能将 String 用作 case 语句 (ARM 5.4(4)) 的 "selecting expression",因为它不是离散类型(不仅仅是实数,或者一个记录,是)。

您可以尝试使用下面示例中的枚举(这留下了如何像您的示例 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;;为了清楚起见,不在这里。

实现应用程序的诀窍是将其分解为功能组件,并在单独的(系列)包中实现它们中的每一个。例如,您可以这样开始:

  • 从命令作用于文本缓冲区的地方拆分命令的解析。定义并实现(作为示例)具有以下规范的包:

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;
  • 使用包 ParserText_Buffers 构建您最终的文本编辑器应用程序。我建议将应用程序逻辑(初始化和主循环)也放入一个单独的包中,并从 Main 调用 Run(见下文):

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;