有没有办法在 Ada 中格式化文本输出

发布于 2024-11-07 18:34:48 字数 472 浏览 4 评论 0原文

有没有办法格式化正在输出的字符串? 我正在尝试获得以下输出的漂亮视图

1: Ashley | 01033438392 | Wellington, New Zealand | 1987- 4-14  
2: Aloha | 01087651234 | Hawaii, United States of America | 1988- 9-23
3: Jack | 01082840184 | Beijing, China | 1989- 6-19

如果我用 C 进行编程,我会做类似的事情“

printf("%10s | %11s | %20s | %4d-%2d-%2d\n",name,phone,address,year,month,day);

是否可以在 Ada 05 中进行这种格式化?”

PS 请忽略姓名、电话号码、地址和出生日期。我只花了30秒就把它们编好了...

Is there a way to format the string being outputted?
I'm trying get a pretty view of the following output

1: Ashley | 01033438392 | Wellington, New Zealand | 1987- 4-14  
2: Aloha | 01087651234 | Hawaii, United States of America | 1988- 9-23
3: Jack | 01082840184 | Beijing, China | 1989- 6-19

If I was programming in C, I would do something like

printf("%10s | %11s | %20s | %4d-%2d-%2d\n",name,phone,address,year,month,day);

Would it be possible to do this kind of formatting in Ada 05?

PS Please just ignore the names, phone numbers, address, and birthdate. I made them up in like 30 seconds...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

妳是的陽光 2024-11-14 18:34:48

这是可以做到的,但机制有点麻烦,而且比较冗长。
我通常会做的是编写单独的过程来处理更复杂的输出,例如日期,并将其与其余的字符串处理一起使用以保持清晰。

package Integer_IO is new Ada.Text_IO.Integer_IO (Integer);

procedure Output_Date ( Day : in Integer; Month: in Integer; Year: in Integer) is 
begin  
  Integer_IO.Put(Item => Day, Width => 2); 
  Text_IO.Put("-");
  Integer_IO.Put(Item => Month, Width => 2); 
  Text_IO.Put("-");
  Integer_IO.Put(Item => Year, Width => 4);
end Output_Date;

procedure Output_String ( Item : in String; 
                          Width : in Integer; 
                          Separator : in String := "|";
                          Truncate : Boolean := False) is 
  Field_Index : Integer := Text_IO.Col;
begin 
  if Item'length > Width and Truncate then 
    Text_IO.Put(Item(1..Width) & Separator);
  else 
    Text_IO.Put(Item) & Separator;
  end if;

  Text_IO.Set_Col ( Field_Index + Width + 1 );
end Output_String;

这将强制执行固定长度字段,这将选择性地允许截断长字符串,或者将后续条目移动到下一行。 Set_Col 将设置下一次写入的行位置,如果当前写入位置已经超过请求的位置,则可能将其放置在下一行。

我在那里添加了字符串截断,作为使用数组切片和 Text_IO 输出操作的机会,但我一般不喜欢默认截断,因为允许字符串超出请求的宽度或在下一行缩进往往会导致格式错误更多明显的。

因此,根据上面的代码,打印出类似于第一行的内容可能类似于:

Name  : String  := "Ashley"
Phone : String  := "01033438392"
Address: String := "Wellington, New Zealand"

Day    : Integer := 14;
Month : Integer  := 4;
Year   : Integer := 1987;

Output_String(Item=> Name,    Width => 10);
Output_String(Item=> Phone,   Width => 11);
Output_String(Item=> Address, Width => 20);
Output_Date(Day,Month,Year);

Ada 中的 Text IO 通常很麻烦,但通常具有使您正在做的事情相对清晰的优点。

It can be done, but the mechanisms are a bit cumbersome and quite a bit more verbose.
What I would generally do is write separate procedures to handle your more complicated output, e.g. dates and use that with the rest of the string handling for clarity.

package Integer_IO is new Ada.Text_IO.Integer_IO (Integer);

procedure Output_Date ( Day : in Integer; Month: in Integer; Year: in Integer) is 
begin  
  Integer_IO.Put(Item => Day, Width => 2); 
  Text_IO.Put("-");
  Integer_IO.Put(Item => Month, Width => 2); 
  Text_IO.Put("-");
  Integer_IO.Put(Item => Year, Width => 4);
end Output_Date;

procedure Output_String ( Item : in String; 
                          Width : in Integer; 
                          Separator : in String := "|";
                          Truncate : Boolean := False) is 
  Field_Index : Integer := Text_IO.Col;
begin 
  if Item'length > Width and Truncate then 
    Text_IO.Put(Item(1..Width) & Separator);
  else 
    Text_IO.Put(Item) & Separator;
  end if;

  Text_IO.Set_Col ( Field_Index + Width + 1 );
end Output_String;

This will enforce fixed length fields, which will optionally allow truncation of long strings, or else move subsequent entries onto the next line. Set_Col will set the line position for the next write, potentially placing it on the next line if the current write position has already exceeded the one requested.

I threw string truncation in there as a chance to use array slicing and Text_IO's output manipulation, but I'm not generally a fan of default truncation, as allowing the string to overrun the requested width or indenting on the next line tend make formatting errors more obvious.

So printing out something like your first line, given the code above, might look something like:

Name  : String  := "Ashley"
Phone : String  := "01033438392"
Address: String := "Wellington, New Zealand"

Day    : Integer := 14;
Month : Integer  := 4;
Year   : Integer := 1987;

Output_String(Item=> Name,    Width => 10);
Output_String(Item=> Phone,   Width => 11);
Output_String(Item=> Address, Width => 20);
Output_Date(Day,Month,Year);

Text IO in Ada is usually cumbersome, but generally has the virtue of making what you are doing relatively clear.

别想她 2024-11-14 18:34:48

对于这种特定的格式设置有辅助工具。

Ada.Text_IO.Integer_IO

procedure Put(Item : in Num; Width : in Field := Default_Width; Base : in Number_Base := Default_Base);

放置一个字段Item 右对齐,空白字符作为填充符。其中 Width 是字段宽度,Base 默认为 10。

Ada.Strings.Fixed

function Head (Source : in String; Count : in Natural; Pad : in Character := Space) return String;
function Tail (Source : in String; Count : in Natural; Pad : in Character := Space) return String;

返回格式化的细绳。其中 Count 是字段宽度,Pad 是字段的填充符。 Head 将字符串左对齐。 Tail 将字符串右对齐。

让列宽为 8 个字符长并使用破折号作为填充符。

Put_Line (Head ("Ashley", 8, '-'));
Put_Line (Head ("Aloha", 8, '-'));
Put_Line (Head ("Jack", 8, '-'));
Put_Line (Tail ("Ashley", 8, '-'));
Put_Line (Tail ("Aloha", 8, '-'));
Put_Line (Tail ("Jack", 8, '-'));

输出

Ashley--
Aloha---
Jack----
--Ashley
---Aloha
----Jack

属性discrete_type'Width

返回一个长度, 离散类型需要表示为文本。

示例

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Calendar; use Ada.Calendar;

procedure Test is

   subtype Index is Positive range 95 .. 1223;

   procedure Put_Line ( I : in out Index; Name : String; Phone : Natural; Address : String; T : in out Time ) is
   begin
      Put (I, Index'Width);
      Put (": ");
      Put (Head (Name, 10, ' '));
      Put (" | ");
      Put (Tail (Phone'Img (Phone'Img'First + 1 .. Phone'Img'Last), 13, '0'));
      Put (" | ");
      Put (Head (Address, 20, ' '));
      Put (Year (T), Year_Number'Width);
      Put ("-");
      Put (Month (T), Month_Number'Width);
      Put ("-");
      Put (Day (T), Day_Number'Width);
      I := Positive'Succ (I);
      T := T + Duration (60 * 60 * 24 * 3);
      New_Line;
   end;

   I : Index := Index'First;
   Now : Time := Clock;
begin

   Put_Line (I, "Ashley", 1033438392, "Wellington, New Zealand", Now);
   Put_Line (I, "Aloha", 01087651234, "Hawaii, United States of America", Now);
   Put_Line (I, "Jack", 01082840184, "Beijing, China", Now);
   I := Index'Last - 3;
   Put_Line (I,"Ashley", 1033438392, "Wellington, New Zealand", Now);
   Put_Line (I,"Aloha", 01087651234, "Hawaii, United States of America", Now);
   Put_Line (I,"Jack", 01082840184, "Beijing, China", Now);

end;

输出

   95: Ashley     | 0001033438392 | Wellington, New Zeal 2015-  5- 24
   96: Aloha      | 0001087651234 | Hawaii, United State 2015-  5- 27
   97: Jack       | 0001082840184 | Beijing, China       2015-  5- 30
 1220: Ashley     | 0001033438392 | Wellington, New Zeal 2015-  6-  2
 1221: Aloha      | 0001087651234 | Hawaii, United State 2015-  6-  5
 1222: Jack       | 0001082840184 | Beijing, China       2015-  6-  8

我建议为电话号码创建一个类型,我不知道它应该是带有标题零的字符串还是数字,我猜电话号码可以有不同的长度。

There is auxiliary tools for this particular format setup.

Package Ada.Text_IO.Integer_IO

procedure Put(Item : in Num; Width : in Field := Default_Width; Base : in Number_Base := Default_Base);

Puts a field with Item aligned to right and white-space character as filler. Where Width is field width and Base is 10 as defualt.

Package Ada.Strings.Fixed

function Head (Source : in String; Count : in Natural; Pad : in Character := Space) return String;
function Tail (Source : in String; Count : in Natural; Pad : in Character := Space) return String;

Returns a formatted string. Where Count is the field width and Pad is filler for the field. Head aligns string to left. Tail aligns string to right.

Let column width be 8 character long and use dash as filler.

Put_Line (Head ("Ashley", 8, '-'));
Put_Line (Head ("Aloha", 8, '-'));
Put_Line (Head ("Jack", 8, '-'));
Put_Line (Tail ("Ashley", 8, '-'));
Put_Line (Tail ("Aloha", 8, '-'));
Put_Line (Tail ("Jack", 8, '-'));

Output

Ashley--
Aloha---
Jack----
--Ashley
---Aloha
----Jack

Attribute discrete_type'Width

Returns a length which the discrete type requires to be represented as text.

Example

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Calendar; use Ada.Calendar;

procedure Test is

   subtype Index is Positive range 95 .. 1223;

   procedure Put_Line ( I : in out Index; Name : String; Phone : Natural; Address : String; T : in out Time ) is
   begin
      Put (I, Index'Width);
      Put (": ");
      Put (Head (Name, 10, ' '));
      Put (" | ");
      Put (Tail (Phone'Img (Phone'Img'First + 1 .. Phone'Img'Last), 13, '0'));
      Put (" | ");
      Put (Head (Address, 20, ' '));
      Put (Year (T), Year_Number'Width);
      Put ("-");
      Put (Month (T), Month_Number'Width);
      Put ("-");
      Put (Day (T), Day_Number'Width);
      I := Positive'Succ (I);
      T := T + Duration (60 * 60 * 24 * 3);
      New_Line;
   end;

   I : Index := Index'First;
   Now : Time := Clock;
begin

   Put_Line (I, "Ashley", 1033438392, "Wellington, New Zealand", Now);
   Put_Line (I, "Aloha", 01087651234, "Hawaii, United States of America", Now);
   Put_Line (I, "Jack", 01082840184, "Beijing, China", Now);
   I := Index'Last - 3;
   Put_Line (I,"Ashley", 1033438392, "Wellington, New Zealand", Now);
   Put_Line (I,"Aloha", 01087651234, "Hawaii, United States of America", Now);
   Put_Line (I,"Jack", 01082840184, "Beijing, China", Now);

end;

Output

   95: Ashley     | 0001033438392 | Wellington, New Zeal 2015-  5- 24
   96: Aloha      | 0001087651234 | Hawaii, United State 2015-  5- 27
   97: Jack       | 0001082840184 | Beijing, China       2015-  5- 30
 1220: Ashley     | 0001033438392 | Wellington, New Zeal 2015-  6-  2
 1221: Aloha      | 0001087651234 | Hawaii, United State 2015-  6-  5
 1222: Jack       | 0001082840184 | Beijing, China       2015-  6-  8

I would recommend to create a type for a phone number, I dunno if it should be string or number with the about of heading zeros, phone number can have different length I guess.

下雨或天晴 2024-11-14 18:34:48

请注意,如今在 C++ 中,printf() 正处于被贬值的边缘,转而使用带有流格式化程序的流。它很方便,但非常不安全(至少在这个词的几种意义上)。如今,开发人员被鼓励使用 C++ 流(及其各种操纵器)。

在 Ada 中,您可以使用字符串连接运算符 & 以与 C++ 流非常相似的方式操作字符串,而 C++ 人员使用流插入运算符 (<<)。在某些方面,Ada 的方法更好,因为您可以嵌套连接表达式,而流插入表达式则无法做到这一点。

这里的问题是,没有任何方便的 C++ 格式化程序的等效项,例如 setfill()hexsetw()。确实应该有,并且(hex 除外)您自己编写它们并不难,但目前它们还不存在。

例如,setw()/setfill() 等效项类似于:

Fill_Char : Character := ' ';

function Set_Fill (New_Fill : Character) return String is
begin
    Fill_Char := New_Fill;
    return "";
end Set_Fill;

--// Dumb tail-recursive implementation. 
function Set_Width(Source : in String; Width : in Positive) return String is
begin
    if Width <= Source'length then --'
        return Source;
    else 
        return Fill_Char & Set_Width(Source, Width - 1);
    end if;
end Set_Width;

Unfilled_String : constant String := "123456";
Filled_String : constant String := Set_Width(Unfilled_String & Set_Fill('0'), 8);
--// The above string should end up being "00123456"

如果您确实想要一个 printf() 接口,则 printf() 当然可以从 Ada 调用。您必须担心 Ada 的大小字符串和 C 的 nul 终止字符串之间的转换,但这就是 Ada.Interfaces.C.Strings 的用途。

Note that in C++ these days printf() is on the verge of being depreciated, in favor of using streams with stream formatters. It is convenient, but massively unsafe (in at least a couple senses of the word). These days developers are encouraged to use C++ streams (with their assorted manipulators) instead.

In Ada you can manipulate strings in a very similar style to C++ streams using the string catenation operator & where C++ folks use the stream insertion operator (<<). In some ways, Ada's method is better because you can nest catenated expressions, which you can't do with stream-inserted expressions.

The problem here is that there aren't any handy equivalents to the C++ formatters like setfill(), hex, and setw(). There really ought to be, and (hex excepted) they aren't tough to write yourself, but for now they don't exist.

For example, a setw()/setfill() equivalent would be something like:

Fill_Char : Character := ' ';

function Set_Fill (New_Fill : Character) return String is
begin
    Fill_Char := New_Fill;
    return "";
end Set_Fill;

--// Dumb tail-recursive implementation. 
function Set_Width(Source : in String; Width : in Positive) return String is
begin
    if Width <= Source'length then --'
        return Source;
    else 
        return Fill_Char & Set_Width(Source, Width - 1);
    end if;
end Set_Width;

Unfilled_String : constant String := "123456";
Filled_String : constant String := Set_Width(Unfilled_String & Set_Fill('0'), 8);
--// The above string should end up being "00123456"

If you really want a printf() interface, printf() is quite callable from Ada of course. You have to worry about transitioning between Ada's sized strings and C's nul-terminated strings, but that's what Ada.Interfaces.C.Strings is there for.

心舞飞扬 2024-11-14 18:34:48

是的,有。虽然它不像 c 中那么容易。

看看 §A.4.4 有界-长度字符串处理了解如何创建预定义大小的字符串,并使用整数'image 来转换数字。的&运算符对于使用 ada.text_io.put_line() 连接字符串和输出非常有用。

Yes there is. Although its not as easy as in c.

Have a look at §A.4.4 Bounded-Length String Handling for how to create strings of a predefined size, and use integer'image to convert your numbers. The & operator is useful to concatenate strings and output using ada.text_io.put_line().

林空鹿饮溪 2024-11-14 18:34:48

您还可以使用 GNAT.Formatted_String 包。
它至少适用于 Ada 2012(无法检查它是否存在于 Ada 2005 中)。
它与 printf 的用法非常相似,但在语法上略有不同。

这是一个简单的工作示例http://tpcg.io/iJwfWa

with Ada.Text_IO; use Ada.Text_IO;
with GNAT.Formatted_String; use GNAT.Formatted_String;

procedure Hello is
  formatStr : constant String := "Hello, %-5s !";
  nameArray : constant array (1..3) of String  (1..4) :=
  (1 => "_Foo",
   2 => "_Bar",
   3 => "_Fuu");
  gnatFormat : Formatted_String := +(formatStr); -- initialisation needed
begin
  for index in nameArray'range loop
    gnatFormat := +(formatStr); --reaffectation needed
    Put_Line(-(gnatFormat & nameArray(index)));
  end loop;
end Hello;

输出:

(GNATMAKE v7.1.1 on https://www.tutorialspoint.com/compile_ada_online.php)
$gnatmake -o hello *.adb
gcc -c hello.adb
gnatbind -x hello.ali
gnatlink hello.ali -o hello

$hello
Hello,  _Foo !
Hello,  _Bar !
Hello,  _Fuu !

另一个带有输入的示例< a href="http://tpcg.io/iJwfWa" rel="nofollow noreferrer">http://tpcg.io/iJwfWa :

with Ada.Text_IO; use Ada.Text_IO;
with GNAT.Formatted_String; use GNAT.Formatted_String;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure Hello is
  formatStr : constant String := "%-10s | %11d | %35s | %4d-%2d-%2d";
  type T_element_descriptor is record
    name : Unbounded_String;
    number : Integer;
    city : Unbounded_String;
    birth_y : Integer; -- should use a date object ...
    birth_m : Integer;
    birth_d : Integer;
  end record;
  elementArray : constant array (1..3) of T_element_descriptor :=
  (1 => (To_Unbounded_String("Ashley"), 01033438392, To_Unbounded_String("Wellington, New Zealand"), 1987, 4, 14),
   2 => (To_Unbounded_String("Aloha"), 01087651234, To_Unbounded_String("Hawaii, United States of America"), 1988, 9, 23),
   3 => (To_Unbounded_String("Jack"),  01082840184, To_Unbounded_String("Beijing, China"), 1989, 6, 19));
  gnatFormat : Formatted_String := +formatStr;
begin
  for index in elementArray'range loop
    gnatFormat := +(formatStr);
    Put_Line(-(gnatFormat
    & To_String(elementArray(index).name)
    & elementArray(index).number
    & To_String(elementArray(index).city)
    & elementArray(index).birth_y
    & elementArray(index).birth_m
    & elementArray(index).birth_d
    ));
  end loop;
end Hello;

输出:

(GNATMAKE v7.1.1 on https://www.tutorialspoint.com/compile_ada_online.php)
$gnatmake -o hello *.adb
gcc -c hello.adb
gnatbind -x hello.ali
gnatlink hello.ali -o hello

$hello
Ashley     |  1033438392 |             Wellington, New Zealand | 1987- 4-14
Aloha      |  1087651234 |    Hawaii, United States of America | 1988- 9-23
Jack       |  1082840184 |                      Beijing, China | 1989- 6-19

gnat 提供的 g-forstr.ads 文件中给出了最好的示例:

--  This package add support for formatted string as supported by C printf()

--  A simple usage is:
--
--     Put_Line (-(+"%s" & "a string"));
--
--  or with a constant for the format:
--
--     declare
--       Format : constant Formatted_String := +"%s";
--     begin
--       Put_Line (-(Format & "a string"));
--     end;
--
--  Finally a more complex example:
--
--     declare
--        F : Formatted_String := +"['%c' ; %10d]";
--        C : Character := 'v';
--        I : Integer := 98;
--     begin
--        F := F & C & I;
--        Put_Line (-F);
--     end;

--  Which will display:

--     ['v' ;         98]

--  Each format specifier is: %[flags][width][.precision][length]specifier

--  Specifiers:
--    d or i    Signed decimal integer
--    u         Unsigned decimal integer
--    o         Unsigned octal
--    x         Unsigned hexadecimal integer
--    X         Unsigned hexadecimal integer (uppercase)
--    f         Decimal floating point, lowercase
--    F         Decimal floating point, uppercase
--    e         Scientific notation (mantissa/exponent), lowercase
--    E         Scientific notation (mantissa/exponent), uppercase
--    g         Use the shortest representation: %e or %f
--    G         Use the shortest representation: %E or %F
--    c         Character
--    s         String of characters
--    p         Pointer address
--    %         A % followed by another % character will write a single %

--  Flags:

--    -         Left-justify within the given field width;
--              Right justification is the default.

--    +         Forces to preceed the result with a plus or minus sign (+ or -)
--              even for positive numbers. By default, only negative numbers
--              are preceded with a - sign.

--    (space)   If no sign is going to be written, a blank space is inserted
--              before the value.

--    #         Used with o, x or X specifiers the value is preceeded with
--              0, 0x or 0X respectively for values different than zero.
--              Used with a, A, e, E, f, F, g or G it forces the written
--              output to contain a decimal point even if no more digits
--              follow. By default, if no digits follow, no decimal point is
--              written.

--    ~         As above, but using Ada style based <base>#<number>#

--    0         Left-pads the number with zeroes (0) instead of spaces when
--              padding is specified.

--  Width:
--    number    Minimum number of characters to be printed. If the value to
--              be printed is shorter than this number, the result is padded
--              with blank spaces. The value is not truncated even if the
--              result is larger.

--    *         The width is not specified in the format string, but as an
--              additional integer value argument preceding the argument that
--              has to be formatted.
--  Precision:
--    number    For integer specifiers (d, i, o, u, x, X): precision specifies
--              the minimum number of digits to be written. If the value to be
--              written is shorter than this number, the result is padded with
--              leading zeros. The value is not truncated even if the result
--              is longer. A precision of 0 means that no character is written
--              for the value 0.

--              For e, E, f and F specifiers: this is the number of digits to
--              be printed after the decimal point (by default, this is 6).
--              For g and G specifiers: This is the maximum number of
--              significant digits to be printed.

--              For s: this is the maximum number of characters to be printed.
--              By default all characters are printed until the ending null
--              character is encountered.

--              If the period is specified without an explicit value for
--              precision, 0 is assumed.

--    .*        The precision is not specified in the format string, but as an
--              additional integer value argument preceding the argument that
--              has to be formatted.

You can also use the GNAT.Formatted_String package.
It works at least with Ada 2012 (can't check if it exists in Ada 2005).
It is very similar to printf usage, but with a slight syntactical difference.

Here is a working simple example http://tpcg.io/iJwfWa :

with Ada.Text_IO; use Ada.Text_IO;
with GNAT.Formatted_String; use GNAT.Formatted_String;

procedure Hello is
  formatStr : constant String := "Hello, %-5s !";
  nameArray : constant array (1..3) of String  (1..4) :=
  (1 => "_Foo",
   2 => "_Bar",
   3 => "_Fuu");
  gnatFormat : Formatted_String := +(formatStr); -- initialisation needed
begin
  for index in nameArray'range loop
    gnatFormat := +(formatStr); --reaffectation needed
    Put_Line(-(gnatFormat & nameArray(index)));
  end loop;
end Hello;

Output :

(GNATMAKE v7.1.1 on https://www.tutorialspoint.com/compile_ada_online.php)
$gnatmake -o hello *.adb
gcc -c hello.adb
gnatbind -x hello.ali
gnatlink hello.ali -o hello

$hello
Hello,  _Foo !
Hello,  _Bar !
Hello,  _Fuu !

Another example with your inputs http://tpcg.io/iJwfWa :

with Ada.Text_IO; use Ada.Text_IO;
with GNAT.Formatted_String; use GNAT.Formatted_String;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure Hello is
  formatStr : constant String := "%-10s | %11d | %35s | %4d-%2d-%2d";
  type T_element_descriptor is record
    name : Unbounded_String;
    number : Integer;
    city : Unbounded_String;
    birth_y : Integer; -- should use a date object ...
    birth_m : Integer;
    birth_d : Integer;
  end record;
  elementArray : constant array (1..3) of T_element_descriptor :=
  (1 => (To_Unbounded_String("Ashley"), 01033438392, To_Unbounded_String("Wellington, New Zealand"), 1987, 4, 14),
   2 => (To_Unbounded_String("Aloha"), 01087651234, To_Unbounded_String("Hawaii, United States of America"), 1988, 9, 23),
   3 => (To_Unbounded_String("Jack"),  01082840184, To_Unbounded_String("Beijing, China"), 1989, 6, 19));
  gnatFormat : Formatted_String := +formatStr;
begin
  for index in elementArray'range loop
    gnatFormat := +(formatStr);
    Put_Line(-(gnatFormat
    & To_String(elementArray(index).name)
    & elementArray(index).number
    & To_String(elementArray(index).city)
    & elementArray(index).birth_y
    & elementArray(index).birth_m
    & elementArray(index).birth_d
    ));
  end loop;
end Hello;

Outputs:

(GNATMAKE v7.1.1 on https://www.tutorialspoint.com/compile_ada_online.php)
$gnatmake -o hello *.adb
gcc -c hello.adb
gnatbind -x hello.ali
gnatlink hello.ali -o hello

$hello
Ashley     |  1033438392 |             Wellington, New Zealand | 1987- 4-14
Aloha      |  1087651234 |    Hawaii, United States of America | 1988- 9-23
Jack       |  1082840184 |                      Beijing, China | 1989- 6-19

Best example is given in the g-forstr.ads file provided with gnat :

--  This package add support for formatted string as supported by C printf()

--  A simple usage is:
--
--     Put_Line (-(+"%s" & "a string"));
--
--  or with a constant for the format:
--
--     declare
--       Format : constant Formatted_String := +"%s";
--     begin
--       Put_Line (-(Format & "a string"));
--     end;
--
--  Finally a more complex example:
--
--     declare
--        F : Formatted_String := +"['%c' ; %10d]";
--        C : Character := 'v';
--        I : Integer := 98;
--     begin
--        F := F & C & I;
--        Put_Line (-F);
--     end;

--  Which will display:

--     ['v' ;         98]

--  Each format specifier is: %[flags][width][.precision][length]specifier

--  Specifiers:
--    d or i    Signed decimal integer
--    u         Unsigned decimal integer
--    o         Unsigned octal
--    x         Unsigned hexadecimal integer
--    X         Unsigned hexadecimal integer (uppercase)
--    f         Decimal floating point, lowercase
--    F         Decimal floating point, uppercase
--    e         Scientific notation (mantissa/exponent), lowercase
--    E         Scientific notation (mantissa/exponent), uppercase
--    g         Use the shortest representation: %e or %f
--    G         Use the shortest representation: %E or %F
--    c         Character
--    s         String of characters
--    p         Pointer address
--    %         A % followed by another % character will write a single %

--  Flags:

--    -         Left-justify within the given field width;
--              Right justification is the default.

--    +         Forces to preceed the result with a plus or minus sign (+ or -)
--              even for positive numbers. By default, only negative numbers
--              are preceded with a - sign.

--    (space)   If no sign is going to be written, a blank space is inserted
--              before the value.

--    #         Used with o, x or X specifiers the value is preceeded with
--              0, 0x or 0X respectively for values different than zero.
--              Used with a, A, e, E, f, F, g or G it forces the written
--              output to contain a decimal point even if no more digits
--              follow. By default, if no digits follow, no decimal point is
--              written.

--    ~         As above, but using Ada style based <base>#<number>#

--    0         Left-pads the number with zeroes (0) instead of spaces when
--              padding is specified.

--  Width:
--    number    Minimum number of characters to be printed. If the value to
--              be printed is shorter than this number, the result is padded
--              with blank spaces. The value is not truncated even if the
--              result is larger.

--    *         The width is not specified in the format string, but as an
--              additional integer value argument preceding the argument that
--              has to be formatted.
--  Precision:
--    number    For integer specifiers (d, i, o, u, x, X): precision specifies
--              the minimum number of digits to be written. If the value to be
--              written is shorter than this number, the result is padded with
--              leading zeros. The value is not truncated even if the result
--              is longer. A precision of 0 means that no character is written
--              for the value 0.

--              For e, E, f and F specifiers: this is the number of digits to
--              be printed after the decimal point (by default, this is 6).
--              For g and G specifiers: This is the maximum number of
--              significant digits to be printed.

--              For s: this is the maximum number of characters to be printed.
--              By default all characters are printed until the ending null
--              character is encountered.

--              If the period is specified without an explicit value for
--              precision, 0 is assumed.

--    .*        The precision is not specified in the format string, but as an
--              additional integer value argument preceding the argument that
--              has to be formatted.
橘和柠 2024-11-14 18:34:48

您可能会喜欢这个使用 Ada.Strings.Fixed 进行格式化这ASCII 图表的范围轴标签。请参阅 function Label,它使用 TailTrim 来格式化 Lower< 的 Integer'Image /code> 和上限 值。

代码:

function Label (J : Integer) return String is
   use Ada.Strings; use Ada.Strings.Fixed;
   Lower : String := Integer'Image(J * Bin_Size);
   Upper : String := Integer'Image((J + 1) * Bin_Size);
begin
   return Tail(Trim(Lower, Left), 4, '0') & "-" &
      Tail(Trim(Upper, Left), 4, '0') & " |*";
end Label;

控制台:

Distribution of lengths:
0000-0100 |**********
0100-0200 |*****************************
0200-0300 |**********************
0300-0400 |***************
0400-0500 |**********
0500-0600 |*******
0600-0700 |****
0700-0800 |****
0800-0900 |**
0900-1000 |**
1000-1100 |*
1100-1200 |*

You might like this simple card game simulation that uses Ada.Strings.Fixed to format the range axis labels for an ASCII graph. See function Label, which uses Tail and Trim to format the Integer'Image of a Lower and Upper value.

Code:

function Label (J : Integer) return String is
   use Ada.Strings; use Ada.Strings.Fixed;
   Lower : String := Integer'Image(J * Bin_Size);
   Upper : String := Integer'Image((J + 1) * Bin_Size);
begin
   return Tail(Trim(Lower, Left), 4, '0') & "-" &
      Tail(Trim(Upper, Left), 4, '0') & " |*";
end Label;

Console:

Distribution of lengths:
0000-0100 |**********
0100-0200 |*****************************
0200-0300 |**********************
0300-0400 |***************
0400-0500 |**********
0500-0600 |*******
0600-0700 |****
0700-0800 |****
0800-0900 |**
0900-1000 |**
1000-1100 |*
1100-1200 |*
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文