Ада Строка Конкатенация - PullRequest
       6

Ада Строка Конкатенация

3 голосов
/ 14 февраля 2011

У меня есть функция, которая возвращает строку для определенного элемента, и мне нужно вызывать эту функцию несколько раз и объединить эти строки в одну. Объединенная строка ограничена. Я удостоверился, что заполнил это когда пробелы в символах, когда это инициализирует, но я продолжаю получать ошибки "проверки длины не удалось". Есть что-то основное, что я делаю здесь неправильно?

FOR I IN 1..Collection.Size LOOP  
    Combined_String :=  combined_string & Tostring(Collection.Book(I));  
END LOOP;

Ответы [ 5 ]

5 голосов
/ 14 февраля 2011

Unbounded_String , вероятно, самый простой способ:

with Ada.Strings.Unbounded;
use Ada.Strings.unbounded;

   ...

Temp_Unbounded_String : Unbounded_String;  -- Is empty by default.

   ...

for I in 1 .. Collection.Size loop
   Append(Temp_Unbounded_String, ToString(Collection.Book(I));
end loop;

Если вам необходимо поместить результат в стандартную строку фиксированной длины:

declare
   Temp_String : constant String := To_String(Temp_Unbounded_String);
begin
   -- Beware! If the length of the Temp_String is greater than that of the
   -- fixed-length string, a Constraint_Error will be raised.  Some verification
   -- of source and target string lengths must be performed!
   Combined_String(Temp_String'Range) := Temp_String;
end;

В качестве альтернативы вы можете использовать процедуру Ada.Strings.Fixed Move () , чтобы перенести Unbounded_String в целевую строку фиксированной длины:

Ada.Strings.Fixed.Move(To_String(Temp_Unbounded_String), Combined_String);

В этом случае, еслиисходная строка слишком длинная, по умолчанию вызывается исключение Length_Error.Существуют и другие параметры для Move (), которые могут изменить поведение в этой ситуации, подробнее см. Предоставленную ссылку на Move .

3 голосов
/ 14 февраля 2011

Чтобы назначить Combined_String, вы должны назначить полную правильную длину сразу. Вы не можете «создать» строку и назначить ее таким образом в Ada.

Не видя остальной части вашего кода, я думаю, что Ada.Strings.Unbounded, вероятно, то, что вы должны использовать.

2 голосов
/ 16 августа 2014

Я знаю, что это древний вопрос, но теперь, когда выйдет Ада 2012, я решил поделиться своей идиомой, которую я использую ...

declare
  function Concatenate(i: Collection'index)
  is
    (tostring(Collection(i) &
      if (i = Collection'last) then
        ("")
      else
        (Concatenate(i+1))
    );

  s: string := Concatenate(Collection'first);
begin
  Put_Line(s);
end;

Напечатано в верхней частимоя голова, так что она будет полна опечаток;и если вы хотите, чтобы он работал с пустыми коллекциями, вам нужно настроить логику (это должно быть очевидно).

Функции выражений Ada 2012 потрясающие!

1 голос
/ 07 марта 2011

С AdaPower.com :

function Next_Line(File : in Ada.Text_IO.File_Type :=
   Ada.Text_Io.Standard_Input) return String is
   Answer : String(1..256);
   Last   : Natural;
begin
   Ada.Text_IO.Get_Line(File => File,
      Item => Answer,
      Last => Last);
   if Last = Answer'Last then
      return Answer & Next_Line(File);
   else
      return Answer(1..Last);
   end if;
end Next_Line;

Как видите, этот метод создает строку (используя Get_Line) неограниченной * длины из файла, из которого он читает. Итак, что вам нужно сделать, чтобы сохранить то, что у вас есть, что-то вроде:

function Combined_String (String_Collection : in String_Collection_Type)
                   Return String is      
begin
    if String_Collection'length = 1 then 
        Return String_Collection(String_Collection'First).All;
    end if;

      Recursion:
      Declare
         Data : String:= String_Collection(String_Collection'First).All;
         SubType Constraint is Positive Range
           Positive'Succ(String_Collection'First)..String_Collection'Last;
      Begin
         Return Data & Combined_String( String_Collection(Constraint'Range) );
      End Recursion;
end Combined_String;

Предполагая, что String_Collection определяется как:

 Type String_Collection is Array (Positive Range <>) of Access String;

* Фактически ограничено Integer'Range, IIRC

1 голос
/ 14 февраля 2011

Ада работает лучше всего, когда вы можете использовать массивы и строки идеального размера.Это прекрасно работает для 99% использования строк, но вызывает проблемы в любое время, когда вам нужно постепенно построить строку из чего-то другого.

Учитывая это, я бы очень хотел знать почему васнужна эта объединенная строка.

Если вам это действительно нужно, есть два хороших способа сделать это.Во-первых, использовать «неограниченные» (динамически измеряемые) строки из Ada.Strings.Unbounded, как предлагали Дейв и Марк С.

Другой - использовать немного функционального программирования (в данном случае рекурсия), чтобы создать вашу фиксированную строку.Например:

function Combined_String (String_Collection : in String_Collection_Type) return String is
begin
    if String_Collection'length = 1 then 
        return String_Collection(String_Collection'first);
    end if;    
    return String_Collection(String_Collection'first) & 
           Combined_String (String_Collection'first + 1 .. String_Collection'last);
end Combined_String;

Я не знаю, какой тип вы использовали для Collection, поэтому я делаю некоторые предположения.В частности, я предполагаю, что это неограниченный массив фиксированных строк.Если это не так, вам придется заменить часть приведенного выше кода тем, что ваш контейнер использует для возврата своих границ, доступа к элементам и выполнения нарезки.

...