Question

Je souhaite sortir une ligne d'en-tête dans un fichier journal puis une ligne de '-' avant les données. Pour ce faire, je crée une chaîne de l'en-tête, puis je dépasse le même nombre de '-'.

Mais le code ci-dessous échoue toujours avec une CONSTRAINT_ERROR car la chaîne générée n'est pas 1024 caractères. Dans ADA, les affectations de chaînes nécessitent exactement la même longueur et non seulement une capacité suffisante.

L'option 1) est de calculer la longueur exacte, mais cela est fragile pour les changements futurs. L'option 2) consiste à utiliser autre chose que la chaîne.

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;
Était-ce utile?

La solution

Beaucoup de gens qui sont habitués à la manière C de construire des cordes en pas ont du mal à enrouler leur esprit autour des cordes ADA, qui vous êtes censé initialiser et utiliser tel quel. Lorsque vous approchez ce fait sur les cordes ADA, la solution devient beaucoup plus simple. Je peux même jeter votre routine de "remplissage".

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;

(Remarque: le commentaire est un piratage pour récupérer le coloriseur de So sur la bonne voie)

Si vous n'aviez pas besoin d'avoir le séparateur de la même longueur, vous n'auriez même pas besoin de déclarer la variable.

Si c'était moi, je ferais quelque chose comme Log_To_File Gardez une trace des longueurs et générez son propre séparateur de bonne taille sur demande. Ensuite, vous pouvez simplement écrire:

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

Autres conseils

Déclarez simplement MSG comme une chaîne au lieu d'une chaîne (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;

Une approche pourrait être d'écrire une fonction qui remplit une chaîne de longueur fixe avec une chaîne d'entrée de taille dynamiquement, un rembourrage avec des espaces:

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 gestion des cordes d'Ada vous permet de passer n'importe quel tampon de longueur fixe dans Dest et le 'First et 'Last Les attributs seront corrects dans le corps de la procédure.

Ensuite, votre code pourrait devenir:

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;    

Comme commodité, vous pouvez utiliser les fonctions du constructeur de chaînes dans Ada.Strings.Fixed, Ada.Strings.Bounded ou Ada.Strings.Unbounded. Ceux-ci surchargent l'opérateur * pour "reproduire un caractère ou une chaîne un nombre de fois spécifié". Par exemple,

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

J'ai travaillé comment utiliser un peu lié_string. Ce type acceptera d'autres chaînes de taille.

Vous ne pouvez pas construire une chaîne non liée avec l'opérateur à moins que vous n'utilisiez des chaînes non liées, alors utilisez la fonction 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; 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top