7

我想在日志文件中输出一个标题行,然后在数据之前输出一行“-”。为此,我创建了一个标题字符串,然后输出相同数量的“-”。

但是下面的代码总是失败并出现 CONSTRAINT_ERROR,因为生成的字符串不是 1024 个字符。在 Ada 中,字符串分配需要完全相同的长度,而不仅仅是足够的容量。

选项 1) 是计算确切的长度,但这对未来的变化很脆弱。选项 2) 是使用 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;
4

5 回答 5

6

很多习惯于 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 的着色器重回正轨的技巧)

如果您不必让分隔符具有相同的长度,您甚至不需要声明变量。

如果是我,我会做一些事情,比如Log_To_File跟踪长度并根据要求生成自己的大小合适的分隔符。然后你可以写:

Open_Log();
Log_To_File ("# " & FLS(" Field1", 12) & 
       "|" & FLS(" Field2", 12) & 
       "|" & FLS(" Field3", 16)); 
Log_Separator_To_File;
于 2010-02-17T13:42:40.900 回答
4

只需将 Msg 声明为 String 而不是 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;
于 2010-02-17T13:25:43.370 回答
3

一种方法可能是编写一个函数,用动态大小的输入字符串填充固定长度的字符串,并用空格填充:

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;    
于 2010-02-15T02:45:29.567 回答
2

Ada.Strings.Fixed为方便起见,您可以在Ada.Strings.Bounded或中使用 String 构造函数Ada.Strings.Unbounded。这些重载 * 运算符以“将字符或字符串复制指定次数”。例如,

with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
   ...
   Log_To_File("# " & Length(Msg) * '-');
于 2010-02-16T05:27:06.773 回答
1

我想出了如何使用 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; 
于 2010-02-15T06:05:32.750 回答