题
我想在日志文件中输出一个标题行,然后在数据之前的“ - ”线输出。为此,我创建了一个标头字符串,然后将相同数量的“ - ”击倒。
但是,以下代码始终使用Constraint_Error失败,因为生成的字符串不是1024个字符。在ADA字符串中,分配需要完全相同的长度,而不仅仅是足够的容量。
选项1)是计算确切的长度,但这对于将来的变化来说是脆弱的。选项2)是使用字符串以外的其他东西。
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;
解决方案
许多习惯于C中构建字符串方式的人很难围绕ADA弦乐, 您应该初始化并使用原样. 。当您理解有关ADA字符串的事实时,解决方案变得更加简单。我什至可以扔掉你的“填充”例程。
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;
(注意:评论是使So So的着色器重回正轨的黑客)
如果您不必具有相同的长度,则甚至不需要声明变量。
如果是我,我会做像 Log_To_File
跟踪长度并应要求生成自己的适当大小的分离器。然后,您可以写信:
Open_Log();
Log_To_File ("# " & FLS(" Field1", 12) &
"|" & FLS(" Field2", 12) &
"|" & FLS(" Field3", 16));
Log_Separator_To_File;
其他提示
只需将MSG声明为字符串而不是字符串(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;
一种方法可能是编写一个填充固定长度字符串的函数,并带有动态大小的输入字符串,带有空格:
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;
ADA的字符串处理使您可以将任何固定的长度缓冲区传递到 Dest
和 'First
和 'Last
属性在过程的正文中是正确的。
然后,您的代码可能会变成:
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;
为了方便起见,您可以使用字符串构造函数 Ada.Strings.Fixed
, Ada.Strings.Bounded
或者 Ada.Strings.Unbounded
. 。这些超载 *运算符以“复制字符或字符串指定的次数”。例如,
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
...
Log_To_File("# " & Length(Msg) * '-');
我弄清楚了如何使用Unbounded_string。该类型将接受其他大小的字符串。
除非使用无绑带的字符串,否则您不能使用&运算符构建无界字符串,因此请使用to_unbounded_string函数。
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;