Как я создаю строку из других строк в Ada?

Я хочу произвести строку заголовка в файле журнала и затем строку '-' перед данными. Чтобы сделать это, я создаю строку заголовка и затем outpout то же количество '-'.

Но ниже кода всегда перестал работать с CONSTRAINT_ERROR, потому что сгенерированная строка не является 1 024 символами. В 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;
7
задан mat_geek 15 February 2010 в 00:52
поделиться

5 ответов

Многие люди, которые привыкли к поэтапному построению строк в языке Си, не могут сосредоточиться на строках Ада, которые вы должны инициализировать и использовать как есть . Когда вы вдумаетесь в этот факт о строках Ада, решение становится намного проще. Я даже могу отказаться от вашей рутины "Заполнения".

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;
6
ответ дан 6 December 2019 в 12:50
поделиться

Я научился использовать Unbounded_String. Этот тип принимает строки другого размера.

Вы не можете построить неограниченную строку с помощью оператора &, если вы не используете неограниченные строки, поэтому используйте функцию 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; 
1
ответ дан 6 December 2019 в 12:50
поделиться

Просто объявите 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;
4
ответ дан 6 December 2019 в 12:50
поделиться

Один из подходов может заключаться в написании функции, которая заполняет строку фиксированной длины входной строкой динамического размера с заполнением пробелами:

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;

Обработка строк в Аде позволяет вы должны передать любой буфер фиксированной длины в Dest , а атрибуты 'Первый и ' Последний будут правильными в теле процедуры.

Тогда ваш код может выглядеть так:

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
ответ дан 6 December 2019 в 12:50
поделиться

Для удобства вы можете использовать функции конструктора строк в Ada.Strings.Fixed, Ada.Strings.Bounded или Ada.Strings.Unbounded. Они перегружают оператор *, чтобы "повторить символ или строку определенное количество раз". Например,

with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
   ...
   Log_To_File("# " & Length(Msg) * '-');
2
ответ дан 6 December 2019 в 12:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: