Как сохранить текст Doubly_Linked_Lists в файл для языка Ada? Также, как иметь не фиксированный размер строки ввода? - PullRequest
2 голосов
/ 12 апреля 2020

Я пишу школьный проект для сохранения строки в двусвязном списке, но я не знаю, как сохранить окончательный список в текстовом файле. Я также, что пользователь выбрать имя текстового файла. Может кто-нибудь показать мне, как это сделать? Также для Ады я могу иметь строку не фиксированной длины в качестве входных данных? Прямо сейчас я установил длину строки на 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;

Ответы [ 3 ]

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

Пара наблюдений:

(1) Хотя String является объектом фиксированной длины, длина может быть определена при инициализации:

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

Возможно, вам придется проявите немного творческого подхода к использованию значения в Str вне его области, блока объявления. Например, если это имя открываемого файла, открываемый объект File_Type может находиться во внешней области видимости.

(2) Если вы хотите прочитать целое число, используйте Ada.Integer_Text_IO.Get (за которым следует Skip_Line, потому что Get завершается, когда число прочитано, оставляя оставшуюся часть строки, включая терминатор, во входном буфере)

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

Ты выглядишь, как будто у тебя есть все части. Вы можете использовать Text_IO для записи в файл, и вы можете использовать Unbounded_String для хранения строк любого размера. Для чтения строк любого размера вы можете использовать процедуру Get_Line в Text_IO, которая возвращает строку любой длины, или, если вы действительно хотите использовать Unbounded_Strings, вы можете использовать Ada.Text_IO.Unbounded_IO. Get_Line . Я также мог бы дополнительно предложить посмотреть Indefinite_Doubly_Linked_List вместо использования Unbounded_String, в зависимости от вашего варианта использования.

Для записи в файл просто l oop над списком и запись каждого элемента в файл с использованием функций стиля 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;

Примечание: если вы тратите больше времени на поиск данных, чем на создание своего списка, вы также можете посмотреть на пакеты Map. У Ады есть хэшированные и упорядоченные карты (также с неопределенными опциями).

1 голос
/ 12 апреля 2020

Похоже, что вы на правильном пути.

Пара моментов:

  • вы можете попросить пользователя ввести имя файла (например, в функции, возвращающей строку, используется инициализировать переменную, как в ответе Саймона. Эта функция может предложить значение по умолчанию, которое будет использоваться, если пользователь просто нажимает Return. Затем вы передаете эту строку в вызов Create.
  • Вероятно, лучший способ вывода Такие сложные вещи, как списки, - это изучение потокового ввода-вывода. Это может быть сложнее настроить, чем вам нужно сейчас, но в конечном итоге это позволит вам просто «записать» весь список в файл за одну операцию. Каждый тип данных имеет Атрибуты 'Read и 'Write - это процедуры, которые вы можете перегружать своими собственными процедурами для форматирования файла, однако вы sh. Атрибут 'Write по умолчанию для списка будет перебирать весь список, вызывая собственные * для каждого элемента 'Write процедура. (Также может вставлять информацию о списке, который вам не нужен, поэтому он перегружен ...)
...