如何在Ada中从其他字符串构建字符串?

时间:2010-02-15 00:52:06

标签: string ada

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

但是下面的代码总是因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;

5 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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;

答案 2 :(得分: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;    

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

我研究了如何使用Unbounded_String。该类型将接受其他大小的字符串。

您无法使用&amp ;;构建无界字符串运算符,除非您使用无界字符串,因此请使用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;