Pergunta

Quero emitir uma linha de cabeçalho em um arquivo de log e, em seguida, uma linha de '-' antes dos dados. Para fazer isso, crio uma sequência do cabeçalho e depois supere o mesmo número de '-'.

Mas o código abaixo sempre falha com uma restrição_error porque a string gerada não tem 1024 caracteres. Nas atribuições de string da ADA requerem exatamente o mesmo comprimento, não apenas capacidade suficiente.

A opção 1) é calcular o comprimento exato, mas isso é quebradiço para mudanças futuras. A opção 2) é usar algo diferente da 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;
Foi útil?

Solução

Muitas pessoas que estão acostumadas com a maneira C de construir cordas em etapas têm problemas para envolver suas mentes em torno de Strings Ada, que você deveria inicializar e usar como está. Quando você obtém esse fato sobre as cordas da ADA, a solução se torna muito mais simples. Eu posso até jogar fora sua rotina de "preenchimento".

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;

(Nota: o comentário é um hack para recuperar o colorizer de So na pista)

Se você não precisasse ter o separador da mesma duração, nem precisaria declarar a variável.

Se fosse eu, eu faria algo como ter Log_To_File Acompanhe os comprimentos e gerar seu próprio separador de tamanho adequado mediante solicitação. Então você pode apenas escrever:

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

Outras dicas

Basta declarar o msg como uma string em vez de uma 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;

Uma abordagem pode ser escrever uma função que preencha uma string de comprimento fixo com uma string de entrada de tamanho dinâmico, preenchendo com espaços:

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;

O manuseio de string da ADA permite que você passe qualquer buffer de comprimento fixo para Dest e a 'First e 'Last Os atributos estarão corretos dentro do corpo do procedimento.

Então, seu código pode se tornar:

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;    

Como conveniência, você pode usar as funções do construtor de strings em Ada.Strings.Fixed, Ada.Strings.Bounded ou Ada.Strings.Unbounded. Estes sobrecarregar o operador * para "replicar um caractere ou string um número especificado de vezes". Por exemplo,

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

Eu calculei como usar o Unbored_String. Esse tipo aceitará outras cordas de tamanho.

Você não pode construir uma string ilimitada com o Operador, a menos que esteja usando strings ilimitados; portanto, use a função TO_UNBOUND_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; 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top