Рисование обложки книги со складками (Ада) - PullRequest
1 голос
/ 28 мая 2020

Я работаю над назначением, которое похоже на проблему пакета флагов, уже решенную на этом сайте ( Тела пакетов и основные программы. Простое назначение (Ada) )

Однако на этот раз мне нужно чтобы нарисовать обложку книги с 4 сгибами, как показано ниже:

Book with folds at the breaking points: 3, 10, 15, 17.
Height = 2, Width = 20, 
Title (string(1..100),
Author (string(1..50).

<Title>
<Author>
|--|------|----|-|---| 
|  |      |    | |   |
|  |      |    | |   |   
|--|------|----|-|---|

Я получаю множество проблем, исходящих из строки 25 в упражнении_bluebook_main.adb, но основная проблема, которая меня беспокоит больше всего, -

упражнение_bluebook_main.adb: 25: 11: ожидаемый тип «Standard.Integer» упражнение_bluebook_main.adb: 25: 11: обнаружен тип «Breaking_Array», определенный в упражнении_bluebook.ads:7

Почему ожидается стандартное целое число, когда Im выходит для массива, как определено? Кроме того, я думаю, что в части объявления основной процедуры 15 строки у меня проблемы, так как: = get_line уже занята заголовком. Как бы вы это разрешили, кто-нибудь?

Может быть, в коде больше ошибок, я благодарен за любой ввод, если он конструктивен!

мой файл .ads

with ada.text_IO; use ada.text_IO;
with ada.integer_text_IO; use ada.integer_text_IO;

package Exercise_BlueBook is

   subtype Break_Points is integer range 1..20;
   type Breaking_Array is array (1..4) of Break_Points;
   type Book_Type is private;

   procedure Get (Item: out Book_Type;
          Title: in String;
          Author: in String;
          Width: in Integer;
          Height: in Integer;
          Break_Points: in Breaking_Array);

   procedure Put (Item: in Book_Type);


private

   type Book_Type is
      record

     Title : String(1..100);
     Title_L : Integer;
     Author : String(1..50);
     Author_L : Integer;
     Width : Integer;
     Height : Integer;
     Break_Points : Integer; 

      end record;

end Exercise_BlueBook;

мой файл adb тела пакета

with ada.text_IO; use ada.text_IO;
with ada.integer_text_IO; use ada.integer_text_IO;

with Exercise_Bluebook; use Exercise_Bluebook;

package body Exercise_BlueBook is

  procedure Get (Item: out Book_Type;
         Title: in String;
         Author: in String;
         Width: in Integer;
         Height: in Integer;
         Break_Points: in Breaking_Array) is

  begin

     Item.Title_L := Integer'Min (Item.Title'Length, Title'Length);
     Item.Title (1..Item.Title_L) := Title(Title'First .. Item.Title_L);
     Item.Author_L := Integer'Min (Item.Author'Length, Author'Length);
     Item.Author (1..Item.Author_L) := Author (Author'First .. Item.Author_L);
     Item.Width := Width;
     Item.Height := Height;
     Item.Break_Points := Break_Points;

  end Get;

  procedure Put (Item: in Book_Type) is


  begin

     Put_Line(Item.Title(1..Item.Title_L));
     Put_Line(Item.Author(1..Item.Author_L));


     for H in 1..Item.Height loop
    Put("!");

    for I in 1..Item.Width loop
       Put("-");
       if I = Breaking_Array(1) then
          Put("!");
       elsif I = Breaking_Array(2) then
          Put("!");
       elsif I = Breaking_Array(3) then
          Put("!");
       elsif I = Breaking_Array(4) then
          Put("!");
       end if;
    end loop;
    Put_Line("!");
     end loop;

     end Put;

end Exercise_BlueBook;

моя основная процедура

with ada.text_IO; use ada.text_IO;
with ada.integer_text_IO; use ada.integer_text_IO;

with Exercise_Bluebook; use Exercise_Bluebook;

procedure Exercise_BlueBook_Main is

   B : Book_Type;

begin

   Put("Enter the name of the book: ");
   declare
      Title : constant String := Get_Line; -- First Get_Line already taken
      Author: constant String := Get_Line; -- How do I solve this for "Author"?
      Width: Integer;
      Height: Integer;
      Break_Points : Exercise_BlueBook.Breaking_Array;
   begin
      Put("Enter the book's width: ");
      Get(Width);
      Put("Enter the book's height: ");
      Get(Height);
      Put("Enter the breaking points for the fold: ");
      Get(Break_Points); -- Won't read this as an array?

      Get(B, 
      Title => Title,
      Author => Author,
      Width => Width,
      Height => Height,
      Break_Points => Break_Points);
   end;

   New_Line;
   Put(B);


end Exercise_BlueBook_Main;

Ответы [ 2 ]

4 голосов
/ 28 мая 2020

В существующем виде основная программа запрашивает название, затем вызывает Get_Line для Title, затем еще Get_Line для Author. Следующие данные считываются с использованием Get s; это работает так: символы читаются с пропуском пробелов до тех пор, пока не будет найдено что-то, что могло бы быть частью числа, затем считываются другие символы, пока не будет найдено то, что не может быть частью числа.

Причина, по которой мы предлагаем форму

   declare
      Title : constant String := Get_Line;

, заключается в том, что String - это массив символов фиксированной длины; как можно заранее узнать, сколько времени осталось сделать? и способ, которым это работает, заключается в том, что фактическая требуемая длина определяется во время выполнения длиной значения инициализации, возвращаемого Get_Line.

Вы можете исправить отсутствие приглашения для автора, изменив приглашение : "Введите название книги и имя автора, нажимайте RET после каждого:".

Или вы можете вложить их:

   Put("Enter the name of the book: ");
   declare
      Title : constant String := Get_Line;
   begin
      Put("Enter the author's name: ");
      declare
         Author: constant String := Get_Line;
         Width: Integer;
         Height: Integer;
         Break_Points : Exercise_BlueBook.Breaking_Array;
      begin
         Put("Enter the book's width: ");
         Get(Width);
         Put("Enter the book's height: ");
         Get(Height);
         Put("Enter the breaking points for the fold: ");

И теперь мы подошли к чтению Break_Points. Вам нужно прочитать каждый элемент со своим Get:

         for J in Break_Points'Range loop
            Get(Break_Points(J));
         end loop;
         Get(B,
             Title => Title,
             Author => Author,
             Width => Width,
             Height => Height,
             Break_Points => Break_Points);
      end;
   end;
2 голосов
/ 28 мая 2020

Подпрограмма Get из пакета Ada.Integer_Text_IO будет читать только одно целое число. Вы можете расширить его, добавив al oop:

main.adb

with Ada.Text_IO; use Ada.Text_IO;

procedure Main is

   generic
      type Num is range <>;
      type Arr is array (Integer range <>) of Num;
   procedure Get (From : String; Item : out Arr);

   ---------
   -- Get --
   ---------

   procedure Get (From : String; Item : out Arr) is

      package Num_IO is
        new Ada.Text_IO.Integer_IO (Num);

      Last : Integer := From'First - 1;

   begin
      for Idx in Item'Range loop
         Num_IO.Get (From (Last + 1 .. From'Last), Item (Idx), Last);
      end loop;
   end Get;


   subtype Break_Points is Integer range 1 .. 20;
   type Breaking_Array is array (Integer range <>) of Break_Points;

   procedure Get_Breaking_Array is
     new Get (Break_Points, Breaking_Array);

   BA : Breaking_Array (1 .. 4);

begin

   Get_Breaking_Array (Get_Line, BA);

   New_Line;
   Put_Line("Result:");

   for BP of BA loop
      Put (BP'Image);
      New_Line;
   end loop;

exception
   when Data_Error  =>
      Put_Line ("Error: Invalid data.");

   when End_Error  =>
      Put_Line ("Error: Not enough elements.");

end Main;

output (слишком много элементов, только первые 4 читаются).

$ ./main
1 2 3 4 5 6

Result:
 1
 2
 3
 4

вывод (слишком мало элементов).

$ ./main
1 2 3
Error: Not enough elements.

вывод (нечисловые c данные ).

$ ./main
1 2 x 4
Error: Invalid data.

вывод (значение элемента вне диапазона).

$ ./main
1 2 3 100
Error: Invalid data.
...