代码之家  ›  专栏  ›  技术社区  ›  mat_geek

如何从ADA中的其他字符串构建字符串?

  •  7
  • mat_geek  · 技术社区  · 16 年前

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

    但是下面的代码总是失败,并带有一个约束错误,因为生成的字符串不是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;
    
    5 回复  |  直到 16 年前
        1
  •  6
  •   T.E.D.    16 年前

    许多习惯于用C方法在步骤中构建字符串的人很难用Ada字符串来包装他们的思想,而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;
    
        2
  •  4
  •   T.E.D.    16 年前

    只需将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;
    
        3
  •  3
  •   Greg Hewgill    16 年前

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

    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;    
    
        4
  •  2
  •   trashgod    16 年前

    为了方便起见,可以在 Ada.Strings.Fixed , Ada.Strings.Bounded Ada.Strings.Unbounded . 这些操作将重载*运算符以“复制指定次数的字符或字符串”。例如,

    with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
       ...
       Log_To_File("# " & Length(Msg) * '-');
    
        5
  •  1
  •   mat_geek    16 年前

    我学会了如何使用无边界的弦。该类型将接受其他大小的字符串。

    除非使用无边界字符串,否则无法使用&运算符生成无边界字符串,因此请使用to ou unbounded ou 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;