Is there a way to format text output in Ada

Is there a way to format the output string? I am trying to get a great view of the following conclusion

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 programmed in C, I would do something like

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

Can this formatting be done in Ada 05?

PS Please just ignore the names, phone numbers, address and date of birth. I made them like 30 seconds ...

+6
source share
5 answers

This can be done, but the mechanisms are a bit cumbersome and quite a bit more detailed. What I usually did was write separate procedures to handle your more complex output, for example. dates and uses, which are with the rest of the string processing 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 force the use of fixed-length fields, which will optionally truncate long lines or move subsequent records to the next line. Set_Col will set the line position for the next record, potentially placing it on the next line if the current record position has already exceeded the requested one.

I threw a line stroke there to use the array handler and Text_IO output manipulation, but I'm usually not a fan of truncating by default, as it allows the line to overflow the requested width or indentation on the next line. formatting errors are more obvious.

So print something like your first line, given the code above, it might look something like this:

 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); 

The text of the IO in Hell is usually bulky, but as a rule, it makes sense to do what you do relatively clearly.

+6
source

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

In Ada, you can manipulate strings in a very similar style with C ++ streams using the & string binding operator, where C ++ people use the stream insert operator ( << ). In a sense, the Ada method is better because you can insert catenated expressions that you cannot do with stream inserts.

The problem here is that there are no convenient equivalents for C ++ formatter like setfill() , hex and setw() . It really should be there, and ( hex excluded) they are not difficult to write themselves, but so far they do not exist.

For example, the equivalent of setw()/setfill() would be something like this:

 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 need the printf() interface, printf() could very well be inferred from Ada, of course. You need to worry about switching between Ada-sized strings and strings with an n-ending character, but there is Ada.Interfaces.C.Strings for that.

+4
source

Yes there is. Although it is not as simple as in c.

See Β§A.4.4 Handling strings with length restrictions to create strings of a given size and use an integer image to convert your numbers. The and operator is useful for concatenating strings and output using ada.text_io.put_line ().

+3
source

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

the 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 |* 
+2
source

There are helper tools for this particular format setting.

Ada.Text_IO.Integer_IO Package

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

Puts a field with Item aligned to the right and white character as a filler. Where Width is the width of the field, and Base is like defualt.

Ada.Strings.Fixed Package

 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 width of the field, and Pad is the filler for the field. Head aligns the line to the left. Tail aligns the string to the right.

Let the column width be 8 characters long and use a dash as a placeholder.

 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, '-')); 

Exit

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

Discrete_type attribute 'Width

Returns the length that 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; 

Exit

  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 creating a type for a phone number, I don’t know if it should be a string or a number with heading numbering, the phone number can have different lengths, I think.

+1
source

Source: https://habr.com/ru/post/888326/


All Articles