Domanda

Voglio produrre una riga di intestazione in un file di registro e quindi una riga di '-' prima dei dati. Per fare ciò creo una stringa di intestazione e poi esalto lo stesso numero di '-'.

Ma il codice seguente fallisce sempre con un vincolo_error perché la stringa generata non è di 1024 caratteri. In ADA String Assegnazioni richiedono esattamente la stessa lunghezza non solo sufficiente capacità.

L'opzione 1) è calcolare la lunghezza esatta ma è fragile ai cambiamenti futuri. L'opzione 2) è usare qualcosa di diverso dalla stringa.

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;
È stato utile?

Soluzione

Molte persone che sono abituate al modo C di costruire stringhe in gradini hanno difficoltà a avvolgere le loro menti attorno alle corde di Ada, che Dovresti inizializzare e usare così com'è. Quando fai questo fatto sulle stringhe di Ada, la soluzione diventa molto più semplice. Posso anche buttare via la tua routine "riempi".

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: il commento è un hack per riportare il colorder di SO in pista)

Se non dovessi avere il separatore della stessa lunghezza, non avresti nemmeno bisogno di dichiarare la variabile.

Se fossi io, farei qualcosa come avere Log_To_File Tenere traccia delle lunghezze e generare il proprio separatore di dimensioni adeguate su richiesta. Allora potresti semplicemente scrivere:

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

Altri suggerimenti

Basta dichiarare MSG come una stringa anziché una stringa (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;

Un approccio potrebbe essere quello di scrivere una funzione che riempie una stringa di lunghezza fissa con una stringa di input di dimensioni dinamiche, imbottitura con spazi:

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;

La gestione delle stringhe di ADA consente di passare qualsiasi buffer a lunghezza fissa in Dest e il 'First e 'Last Gli attributi saranno corretti all'interno del corpo della procedura.

Quindi, il tuo codice potrebbe diventare:

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;    

Per comodità, è possibile utilizzare le funzioni del costruttore di stringhe in Ada.Strings.Fixed, Ada.Strings.Bounded o Ada.Strings.Unbounded. Questi sovraccaricano l'operatore * per "replicare un carattere o una stringa un numero specificato di volte." Per esempio,

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

Ho capito come usare illimitato_string. Quel tipo accetterà le stringhe di altre dimensioni.

Non è possibile creare una stringa illimitata con l'operatore e a meno che tu non stia usando stringhe illimitate, quindi usa la funzione 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; 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top