如何将 Doubly_Linked_Lists 文本保存到 Ada 语言的文件中?还有如何输入不固定大小的字符串?

How to save Doubly_Linked_Lists text to a file for Ada language? Also how to have not fixed size string input?

我正在编写一个将字符串存储到双向链表的学校项目,但我不知道如何将最终列表保存到文本文件。我还用什么用户来选择文本文件名。有人可以告诉我该怎么做吗?同样对于 Ada,我可以输入一个不固定长度的字符串吗?现在我将字符串长度设置为 5,但我真的希望字符串具有灵活的长度。下面是我的代码谢谢。

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;
with Ada.IO_Exceptions;

procedure main is
   type Command is (A, C, P, E, M);
   package Command_IO is new Ada.Text_IO.Enumeration_IO (Command);
   package String_List is new Ada.Containers.Doubly_Linked_Lists(Unbounded_String);
   use String_List;
   Userinput : String(1 .. 5) := (others => ' '); --This string length is 5
   InsertLocation : String(1 .. 5) := (others => ' '); --This string length is 5
   text : List; -- List is from Doubly_Linked_Lists
   F : File_Type;

begin   
   loop     
      declare
         Cmd : Command;


   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
         Put_Line("*****************************");
         Put_Line("*Enter A to add a text      *");
         Put_Line("*Enter C to insert a text   *");
         Put_Line("*Enter P the print text list*");
         Put_Line("*Enter E the exit program   *");
         Put_Line("*Enter M to save the list   *");
         Put_Line("*****************************");
         Put_Line(" ");
         Put(">> ");

         Command_IO.Get (Cmd);

         Ada.Text_IO.Skip_Line;

         Put_Line ("read " & Cmd'Image);                -- ' to sort out the not-fully-Ada-aware syntax highlighting
         Put_Line ("  " );
         case Cmd is

         when a =>
            Put_Line("Enter a text " );
            Put(">> " );
            Get(Userinput);  
            text.Append(To_Unbounded_String(Userinput)); -- if letter is a add it to the doubly link list  
            Put_line("  " );

         when c => 
            Put_Line("Enter a text location you want to insert " );
            Put(">> " );
            Get(Userinput);
            Put_Line("Enter a text " );
            Put(">> " );
            Get(InsertLocation);


            text.Insert(Before => text.Find(To_Unbounded_String(Userinput)), New_Item => To_Unbounded_String( InsertLocation ));

         when p =>      
            text.Iterate(Print'access);
            Put_line("  " );


         when m =>
            Put_Line("Save to file"); 
            Create (F, Out_File, "file.txt");
            Put_Line (F, "This string will be written to the file file.txt");
            Close (F);

         when e =>      
            Put_Line("Program Exit");

            exit;   

         end case;   

      exception
         when Ada.IO_Exceptions.Data_Error =>
            Put_Line ("unrecognised command");
            Put_Line (" ");

      end;
   end loop;
end main;

你看起来像所有的部分。您可以使用 Text_IO 来写入文件,您可以使用 Unbounded_String 来保存任意大小的字符串。要读取任何大小的字符串,您可以使用过程 Get_Line in Text_IO which returns a string of any length or if you really want to use Unbounded_Strings, you can use Ada.Text_IO.Unbounded_IO.Get_Line. I could also optionally suggest looking at Indefinite_Doubly_Linked_List 而不是使用 Unbounded_String,具体取决于您的用例。

要写入文件,只需遍历列表并使用 Text_IO 样式函数将每个元素写入文件。

这里有一些脚手架展示了其中的一些内容。

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Indefinite_Doubly_Linked_Lists;
use Ada.Containers;


procedure Hello is

    package Lists is new Indefinite_Doubly_Linked_Lists(String);
    Text : Lists.List;
begin
    Put_Line("Hello, world!");


    Put_Line("Enter a text:" );
    declare
        User_Input : String := Get_Line;
    begin
        Text.Append(New_Item => User_Input);
    end;

    Put_Line("Enter Text to Insert at:");
    declare
        Location : String := Get_Line;
    begin
        Put_Line("Enter New Text:");
        declare
            User_Input : String := Get_Line;
        begin
            Text.Insert(Before => Text.Find(Location), New_Item => User_Input);
        end;
    end;

    -- Loop through list and write each element
    for Line of Text loop
        Put_Line(Line);
        -- Write to file here using Text_IO file operations
    end loop;

end Hello;

旁注,如果您搜索数据所花费的时间多于创建列表所花费的时间,您还可以查看地图包。 Ada 有两个 hashed and ordered 映射(也有不确定的选项)。

一些观察:

(1)虽然aString是一个定长对象,但长度可以在初始化时确定:

declare
   Str : constant String := Get_Line;
begin
   ...

Str 的范围之外使用值,声明块,您可能需要有点创意。例如,如果它是要打开的文件的名称,则要打开的 File_Type 对象可能在外部范围内。

(2) 如果要读取一个整数,使用Ada.Integer_Text_IO.Get(后面是Skip_Line,因为Get在读取完数字时终止,剩下的输入缓冲区中的行,包括终止符)

看来您的方向是正确的。

几点:

  • 您可以要求用户输入文件名(例如,在返回字符串的函数中,用于初始化变量,如 Simon 的回答。此函数可以建议默认值,如果用户只需按 Return。然后将该字符串传递给 Create 调用。
  • 可能输出列表等复杂事物的最佳方法是学习 Stream I/O。这可能比您现在需要的设置更复杂,但最终它会让您简单地 "Write" 整个列表在一次操作中归档。每种数据类型都有 'Read'Write 属性,这些是您可以用自己的过程重载以根据需要格式化文件的过程。列表的默认 'Write 属性将遍历整个列表,调用每个元素自己的 'Write 过程。 (它也可能会插入有关您不想要的列表的信息,这就是它可重载的原因...)