How to build a string from other strings in Ada?

I want to display the header line in the log file, and then the line before the "-" symbol. To do this, I create a title bar and then issue the same number "-".

But below code always fails with CONSTRAINT_ERROR, because the generated string does not have 1024 characters. Ada string assignments require exactly the same length, not just enough capacity.

Option 1) is to calculate the exact length, but it will be fragile for future changes. Option 2) is to use something other than String.

procedure F() is Msg : String(1..1024); begin Open_Log(); Msg := FLS(" Field1", 12) & "|" & FLS(" Field2", 12) & "|" & FLS(" Field3", 16); Log_To_File("# " & Msg); Log_To_File("# " & Fill_String(Msg'Last, '-')); end; 
+7
string ada
source share
5 answers

A lot of people who are used to the way of building lines in steps have problems wrapping their thoughts around Ada lines, which you should initialize and use as is . When you confirm this fact about the strings of Ada, the decision becomes much simpler. I can even throw out the Fill routine.

 procedure F() is Msg : constant String := FLS(" Field1", 12) & "|" & FLS(" Field2", 12) & "|" & FLS(" Field3", 16); Separator : constant String := (1..Msg'length => '-'); --' begin Open_Log(); Log_To_File("# " & Msg); Log_To_File("# " & Separator); end; 

(Note: a comment is a hack to get the SO colorizer back on track)

If you do not need to have a delimiter of the same length, you will not even need to declare a variable.

If it were me, I would do something like Log_To_File track the lengths and generate a custom size separator on request. Then you can simply write:

 Open_Log(); Log_To_File ("# " & FLS(" Field1", 12) & "|" & FLS(" Field2", 12) & "|" & FLS(" Field3", 16)); Log_Separator_To_File; 
+6
source share

One approach might be to write a function that fills a fixed-length string with a dynamic-size input string, filling in the blanks:

 procedure Pad_String(Str: in String; Dest: out String; Len: out Integer) is begin Len := Str'Last - Str'First + 1; Dest(Dest'First .. Dest'First + Len - 1) := Str(Str'First .. Str'First + Len - 1); Dest(Dest'First + Len .. Dest'Last) := Fill_String(Dest'Last - Len, ' '); end Pad_String; 

Processing the Ada string allows you to pass any fixed-length buffer to Dest , and the attributes 'First and 'Last will be valid within the body of the procedure.

Then your code could become:

 procedure F() is Msg : String(1..1024); Len : Integer; begin Open_Log(); Pad_String( FLS(" Field1", 12) & "|" & FLS(" Field2", 12) & "|" & FLS(" Field3", 16), Msg, Len); Log_To_File("# " & Msg(1 .. Len)); Log_To_File("# " & Fill_String(Len, '-')); end; 
+3
source share

Just declare Msg as a string instead of a string (1 .. 1024)

 procedure F() is Msg: String := FLS(" Field1", 12) & "|" & FLS(" Field2", 12) & "|" & FLS(" Field3", 16); --// this 'magically' declares Msg as a String(1 .. Something) --// with the right Something begin Open_Log(); Log_To_File("# " & Msg); Log_To_File("# " & Fill_String(Msg'Last, '-')); --' end; 
+3
source share

As a convenience, you can use the String constructor functions in Ada.Strings.Fixed , Ada.Strings.Bounded or Ada.Strings.Unbounded . They overload the * operator to "replicate a character or string a specific number of times." For example,

 with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; ... Log_To_File("# " & Length(Msg) * '-'); 
+2
source share

I developed how to use Unbounded_String. This type will accept strings of a different size.

You cannot create an unlimited row using the operator and, unless you use unlimited rows, so use the To_Unbounded_String function.

 with Ada.Strings.Unbounded; procedure F() is use Ada.Strings.Unbounded; Msg : Unbounded_String; begin Open_Log(); Msg := Ada.Strings.Unbounded.To_Unbounded_String( FLS(" Field1", 12) & "|" & FLS(" Field2", 12) & "|" & FLS(" Field3", 16)); Log_To_File("# " & Ada.Strings.Unbounded.To_String(Msg)); Log_To_File("# " & Fill_String(Ada.Strings.Unbounded.Length(Msg), '-')); end; 
+1
source share

All Articles