用褶皱画一本书的封面 (Ada)

Drawing a book's cover with folds (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>
|--|------|----|-|---| 
|  |      |    | |   |
|  |      |    | |   |   
|--|------|----|-|---|

我在 exercise_bluebook_main.adb 的第 25 行遇到了很多问题,但最让我烦恼的是

exercise_bluebook_main.adb:25:11: expected type "Standard.Integer" exercise_bluebook_main.adb:25:11: found type "Breaking_Array" defined at exercise_bluebook.ads:7

当我输出定义的数组时,为什么它需要一个标准整数?此外,我认为在主程序第 15 行的声明部分我遇到了麻烦,因为 :=get_line 已经被 "Title" 占用。你会如何解决这个问题,有人吗?

也许代码中的错误比这更多,我感谢所有建设性的输入!

我的 .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;

Ada.Integer_Text_IO 包中的 Get 子程序将只读取一个整数。您可以通过添加循环来扩展它:

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;

输出(元素太多,只读取前4个)。

$ ./main
1 2 3 4 5 6

Result:
 1
 2
 3
 4

输出(元素太少)。

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

输出(非数字数据)。

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

输出(元素值超出范围)。

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

就目前而言,主程序提示输入标题,然后为 Title 调用 Get_Line,然后为 Author 调用另一个 Get_Line。下面的数据是使用Gets读取的;工作的方式是读取字符,跳过白色 space 直到找到可能是数字一部分的内容,然后读取更多字符直到找到不能成为数字一部分的内容。

我们一直在推荐表格的原因

   declare
      Title : constant String := Get_Line;

是一个String是一个fixed-length字符数组;你怎么能提前知道要多长时间呢?其工作方式是所需的实际长度在 运行 时间由 Get_Line.

返回的初始化值的长度确定

您可以通过更改提示来解决缺少作者提示的问题:"Enter the book’s name and the author’s name, hit RET after each:".

或者您可以嵌套它们:

   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;